From aa6fb327101c82d55562d15ff0c3ec09ffc8e49b Mon Sep 17 00:00:00 2001 From: Daniel Baark <5101747+baarkerlounger@users.noreply.github.com> Date: Mon, 22 Nov 2021 09:31:29 +0000 Subject: [PATCH] CLDC-724: Admin Panel requires authentication (#104) * Admi Users must sign in to access panel * Add ADR doc for design decision * Add AdminUsers dashboard to ActiveAdmin --- app/admin/admin_users.rb | 27 ++++++++++++++++++++ app/models/admin_user.rb | 5 ++++ config/initializers/active_admin.rb | 4 +-- config/routes.rb | 1 + db/migrate/20211119120910_add_admin_users.rb | 18 +++++++++++++ db/schema.rb | 14 ++++++++-- db/seeds.rb | 1 + docs/adr/adr-010-admin-users-vs-users.md | 9 +++++++ 8 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 app/admin/admin_users.rb create mode 100644 app/models/admin_user.rb create mode 100644 db/migrate/20211119120910_add_admin_users.rb create mode 100644 docs/adr/adr-010-admin-users-vs-users.md diff --git a/app/admin/admin_users.rb b/app/admin/admin_users.rb new file mode 100644 index 000000000..fed0ec1a8 --- /dev/null +++ b/app/admin/admin_users.rb @@ -0,0 +1,27 @@ +ActiveAdmin.register AdminUser do + permit_params :email, :password, :password_confirmation + + index do + selectable_column + id_column + column :email + column :current_sign_in_at + column :sign_in_count + column :created_at + actions + end + + filter :email + filter :current_sign_in_at + filter :sign_in_count + filter :created_at + + form do |f| + f.inputs do + f.input :email + f.input :password + f.input :password_confirmation + end + f.actions + end +end diff --git a/app/models/admin_user.rb b/app/models/admin_user.rb new file mode 100644 index 000000000..14ea71789 --- /dev/null +++ b/app/models/admin_user.rb @@ -0,0 +1,5 @@ +class AdminUser < ApplicationRecord + # Include default devise modules. Others available are: + # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable + devise :database_authenticatable, :recoverable, :rememberable, :validatable +end diff --git a/config/initializers/active_admin.rb b/config/initializers/active_admin.rb index 5afdcdc12..6e78e39d6 100644 --- a/config/initializers/active_admin.rb +++ b/config/initializers/active_admin.rb @@ -54,7 +54,7 @@ ActiveAdmin.setup do |config| # # This setting changes the method which Active Admin calls # within the application controller. - # config.authentication_method = :authenticate_admin_user! + config.authentication_method = :authenticate_admin_user! # == User Authorization # @@ -91,7 +91,7 @@ ActiveAdmin.setup do |config| # # This setting changes the method which Active Admin calls # (within the application controller) to return the currently logged in user. - # config.current_user_method = :current_admin_user + config.current_user_method = :current_admin_user # == Logging Out # diff --git a/config/routes.rb b/config/routes.rb index 2c0b14673..10cc71b6c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,5 @@ Rails.application.routes.draw do + devise_for :admin_users, ActiveAdmin::Devise.config devise_for :users, controllers: { passwords: "users/passwords" } devise_scope :user do get "confirmations/reset", to: "users/passwords#reset_confirmation" diff --git a/db/migrate/20211119120910_add_admin_users.rb b/db/migrate/20211119120910_add_admin_users.rb new file mode 100644 index 000000000..05bce9747 --- /dev/null +++ b/db/migrate/20211119120910_add_admin_users.rb @@ -0,0 +1,18 @@ +class AddAdminUsers < ActiveRecord::Migration[6.1] + def change + create_table :admin_users do |t| + ## Database authenticatable + t.string :email, null: false, default: "" + t.string :encrypted_password, null: false, default: "" + + ## Recoverable + t.string :reset_password_token + t.datetime :reset_password_sent_at + + ## Rememberable + t.datetime :remember_created_at + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 18a7999e6..408d07b07 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,21 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_11_18_090831) do +ActiveRecord::Schema.define(version: 2021_11_19_120910) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + create_table "admin_users", force: :cascade do |t| + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false + t.string "reset_password_token" + t.datetime "reset_password_sent_at" + t.datetime "remember_created_at" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + create_table "case_logs", force: :cascade do |t| t.integer "status", default: 0 t.datetime "created_at", precision: 6, null: false @@ -88,7 +98,6 @@ ActiveRecord::Schema.define(version: 2021_11_18_090831) do t.integer "tcharge" t.integer "layear" t.integer "lawaitlist" - t.string "property_postcode" t.integer "reasonpref" t.string "reasonable_preference_reason" t.integer "cbl" @@ -153,6 +162,7 @@ ActiveRecord::Schema.define(version: 2021_11_18_090831) do t.datetime "sale_completion_date" t.datetime "startdate" t.integer "armedforces" + t.string "property_postcode" t.index ["discarded_at"], name: "index_case_logs_on_discarded_at" end diff --git a/db/seeds.rb b/db/seeds.rb index cb36e5af4..6156dff01 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -7,3 +7,4 @@ # Character.create(name: 'Luke', movie: movies.first) User.create!(email: "test@example.com", password: "password") +AdminUser.create!(email: "admin@example.com", password: "password") diff --git a/docs/adr/adr-010-admin-users-vs-users.md b/docs/adr/adr-010-admin-users-vs-users.md new file mode 100644 index 000000000..e293eea9f --- /dev/null +++ b/docs/adr/adr-010-admin-users-vs-users.md @@ -0,0 +1,9 @@ +### ADR - 010: Admin Users vs Users + +#### Why do we have 2 User classes, AdminUser and User? + +This is modelling a real life split. `AdminUsers` are internal DLUHC users or helpdesk employees. While `Users` are external users working at data providing organisations. So local authority/housing association's "admin" users, i.e. Data Co-ordinators are a type of the User class. They have the ability to add or remove other users to or from their organisation, and to update their organisation details etc, but only through the designed UI. They do not get direct access to ActiveAdmin. + +AdminUsers on the other hand get direct access to ActiveAdmin. From there they can download entire datasets (via CSV, XML, JSON), view any log from any organisation, and add or remove users of any type including other Admin users. This means TDA will likely also require more stringent authentication for them using MFA (which users will likely not require). So the class split also helps there. + +A potential downside to this approach is that it does not currently allow for `AdminUsers` to sign into the application UI itself with their Admin credentials. However, we need to see if there's an actual use case for this and what it would be (since they aren't part of an organisation to be uploading data for, but could add or amend data or user or org details through ActiveAdmin anyway). If there is a strong use case for it this could be work around by either: providing them with two sets of credentials, or modifying the `authenticate_user` method to also check `AdminUser` credentials.