Class: CamaleonCms::Admin::UsersController

Inherits:
CamaleonCms::AdminController show all
Includes:
CustomFieldsConcern
Defined in:
app/controllers/camaleon_cms/admin/users_controller.rb

Constant Summary collapse

SELF_TARGET_ACTIONS =

Member actions resolve a single target user, so a caller acting on their own record is legitimately exempt from :manage, :users. The collection actions (index/new/create) resolve no such target, so a self-referential ?user_id= must not exempt them from the capability check.

%w[show edit update destroy impersonate updated_ajax].freeze

Instance Method Summary collapse

Methods inherited from CamaleonCms::AdminController

#ajax, #cama_get_i18n_frontend, #dashboard, #search

Instance Method Details

#createObject



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 132

def create
  @user = current_site.users.new(user_params)
  r = { user: @user }
  hooks_run('user_create', r)
  if @user.save
    @user.set_metas(user_meta_params) if params[:meta].present?
    @user.set_field_values(cama_permitted_field_options(user_field_scope)) if params[:field_options].present?
    r = { user: @user }
    hooks_run('user_created', r)
    flash[:notice] = t('camaleon_cms.admin.users.message.created')
    redirect_to action: :index
  else
    new
  end
end

#current_user_is?(user) ⇒ Boolean

Returns:

  • (Boolean)


111
112
113
114
115
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 111

def current_user_is?(user)
  user_auth_token_from_cookie == user.auth_token
rescue StandardError
  false
end

#destroyObject



148
149
150
151
152
153
154
155
156
157
158
159
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 148

def destroy
  if cama_current_user.id == @user.id
    flash[:error] =
      t('camaleon_cms.admin.users.message.user_can_not_delete_own_account',
        default: 'User can not delete own account')
  elsif @user.destroy
    flash[:notice] = t('camaleon_cms.admin.users.message.deleted')
    r = { user: @user }
    hooks_run('user_destroyed', r)
  end
  redirect_to action: :index
end

#editObject



117
118
119
120
121
122
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 117

def edit
  add_breadcrumb I18n.t('camaleon_cms.admin.button.edit')
  r = { user: @user, render: 'form' }
  hooks_run('user_edit', r)
  render r[:render]
end

#impersonateObject



161
162
163
164
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 161

def impersonate
  authorize! :impersonate, @user
  session_switch_user(@user, cama_admin_dashboard_path)
end

#indexObject



17
18
19
20
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 17

def index
  add_breadcrumb I18n.t('camaleon_cms.admin.users.list_users')
  @users = current_site.users.paginate(page: params[:page], per_page: current_site.admin_per_page)
end

#newObject



124
125
126
127
128
129
130
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 124

def new
  @user ||= current_site.users.new
  add_breadcrumb I18n.t('camaleon_cms.admin.button.new')
  r = { user: @user, render: 'form' }
  hooks_run('user_new', r)
  render r[:render]
end

#profileObject



22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 22

def profile
  add_breadcrumb I18n.t('camaleon_cms.admin.users.profile')
  user_id = params[:user_id]
  # Authorize from the parameter before loading, so a denied caller cannot tell
  # whether the requested user exists from the shape of the response.
  authorize! :manage, :users if user_id.present? && user_id.to_i != cama_current_user.id
  @user = user_id.present? ? current_site.the_user(user_id.to_i)&.object : cama_current_user.object
  if @user.blank?
    flash[:error] = t('camaleon_cms.admin.users.message.error')
    return redirect_to(cama_admin_path)
  end

  edit
end

#profile_editObject



37
38
39
40
41
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 37

def profile_edit
  add_breadcrumb I18n.t('camaleon_cms.admin.users.profile')
  @user = cama_current_user.object
  edit
end

#showObject



43
44
45
46
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 43

def show
  add_breadcrumb I18n.t('camaleon_cms.admin.users.profile')
  render 'profile'
end

#updateObject



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 48

def update
  r = { user: @user }
  hooks_run('user_update', r)
  if @user.update(user_params)
    @user.set_metas(user_meta_params) if params[:meta].present?
    @user.set_field_values(cama_permitted_field_options(user_field_scope)) if params[:field_options].present?
    r = { user: @user, message: t('camaleon_cms.admin.users.message.updated'), params: params }
    hooks_run('user_after_edited', r)
    flash[:notice] = r[:message]
    r = { user: @user }
    hooks_run('user_updated', r)
    if cama_current_user.id == @user.id
      redirect_to action: :profile_edit
    else
      redirect_to action: :index
    end
  else
    render 'form'
  end
end


100
101
102
103
104
105
106
107
108
109
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 100

def update_auth_token_in_cookie(token)
  return unless cookie_auth_token_complete?

  current_token = cookie_split_auth_token
  updated_token = [token, *current_token[1..]]
  # Route through the shared hardened-cookie options (audit M3/M4): a bare assignment here
  # re-issued the auth cookie without HttpOnly/Secure/domain/expiry when a user changed their
  # own password, undoing the M3 hardening for that session.
  cookies[:auth_token] = cama_auth_cookie_options(updated_token.join('&'))
end

#updated_ajaxObject

update some ajax requests from profile or user form



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'app/controllers/camaleon_cms/admin/users_controller.rb', line 70

def updated_ajax
  @user = current_site.users.find(user_id_param)
  # Only an admin may reset an admin's password; a `:manage, :users` holder who could would sign in
  # as that admin (H10). Self-service and non-admin targets are unaffected.
  unless cama_current_user.may_edit_credentials?(@user)
    return render plain: t('camaleon_cms.admin.users.message.error'), status: :forbidden
  end

  update_session = current_user_is?(@user)
  attrs = params.require(:password).permit(%i[password password_confirmation])
  @user.update(password: attrs.require(:password), password_confirmation: attrs.require(:password_confirmation))

  return render plain: @user.errors.full_messages.join(', '), status: :unprocessable_entity if @user.errors.any?

  # A newly provisioned admin (see harden-installer-default-admin) owes a password change; clearing
  # the marker on a real change lets them past the enforce_password_change gate.
  @user.delete_meta('must_change_password') if @user.saved_change_to_password_digest?

  # keep user logged in when changing their own password
  update_auth_token_in_cookie @user.auth_token if update_session && @user.saved_change_to_password_digest?
rescue ActiveRecord::RecordNotFound
  # The other failure paths of this action answer with a status and a short text body, so an
  # unresolvable target does too rather than falling through to the framework's HTML error
  # page. Catch this class only, never StandardError, so a genuine lookup failure still
  # surfaces instead of being reported as a missing user.
  render plain: t('camaleon_cms.admin.users.message.error'), status: :not_found
rescue ActionController::ParameterMissing => e
  render plain: "ERROR: #{e.class.name}, #{e.message}", status: :bad_request
end