-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Generate invitations to enrol new admin users
* Adds new endpoint to handle invitations * Enables generating invitation link to share from admin user show page * Adds a signup page using token details * updates validations on password, so that password is optional
- Loading branch information
1 parent
2f05ae1
commit 67ebdfe
Showing
19 changed files
with
367 additions
and
8 deletions.
There are no files selected for viewing
23 changes: 23 additions & 0 deletions
23
app/assets/javascripts/koi/controllers/clipboard_controller.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { Controller } from "@hotwired/stimulus"; | ||
|
||
export default class ClipboardController extends Controller { | ||
static targets = ["source"]; | ||
|
||
static classes = ["supported"]; | ||
|
||
connect() { | ||
if ("clipboard" in navigator) { | ||
this.element.classList.add(this.supportedClass); | ||
} | ||
} | ||
|
||
copy(event) { | ||
event.preventDefault(); | ||
navigator.clipboard.writeText(this.sourceTarget.value); | ||
|
||
this.element.classList.add("copied"); | ||
setTimeout(() => { | ||
this.element.classList.remove("copied"); | ||
}, 2000); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
.copy-to-clipboard { | ||
position: relative; | ||
|
||
.copy-to-clipboard-feedback { | ||
animation: ease-in-out 0.5s; | ||
display: none; | ||
position: absolute; | ||
top: 0; | ||
right: 0; | ||
left: 0; | ||
margin-top: -1em; | ||
z-index: 10; | ||
white-space: nowrap; | ||
text-align: center; | ||
|
||
&:after { | ||
content: "Link copied to your clipboard!"; | ||
display: inline-block; | ||
padding: 0.33em 1em 0.33em 1em; | ||
border-radius: 3rem; | ||
color: white; | ||
background-color: black; | ||
} | ||
} | ||
|
||
&.copied .copy-to-clipboard-feedback { | ||
display: block; | ||
} | ||
|
||
.clipboard-button { | ||
display: none; | ||
} | ||
|
||
&.clipboard--supported .clipboard-button { | ||
display: initial; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
@use "actions-group"; | ||
@use "clipboard"; | ||
@use "document-field"; | ||
@use "image-field"; | ||
@use "index-actions"; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# frozen_string_literal: true | ||
|
||
module Admin | ||
class TokensController < ApplicationController | ||
include Koi::Controller::JsonWebToken | ||
|
||
skip_before_action :authenticate_admin, only: %i[show update] | ||
before_action :set_token, only: %i[show update] | ||
|
||
def create | ||
admin = Admin::User.find(params[:id]) | ||
token = encode_token(admin_id: admin.id, exp: 24.hours.from_now.to_i, iat: Time.now.to_i) | ||
|
||
render locals: { token: } | ||
end | ||
|
||
def update | ||
return redirect_to admin_dashboard_path, status: :see_other if admin_signed_in? | ||
|
||
return redirect_to new_admin_session_path, status: :see_other, notice: "invalid token" if @token.blank? | ||
|
||
admin = Admin::User.find(@token[:admin_id]) | ||
sign_in_admin(admin) | ||
|
||
redirect_to admin_admin_user_path(admin) | ||
end | ||
|
||
def show | ||
return redirect_to new_admin_session_path, notice: "invalid token" if @token.blank? | ||
|
||
admin = Admin::User.find(@token[:admin_id]) | ||
|
||
return redirect_to new_admin_session_path, notice: "token already used" if token_utilised?(admin, @token) | ||
|
||
render locals: { admin:, token: params[:token] }, layout: "koi/login" | ||
end | ||
|
||
private | ||
|
||
def set_token | ||
@token = decode_token(params[:token]) | ||
end | ||
|
||
def token_utilised?(admin, token) | ||
admin.current_sign_in_at.present? || (admin.last_sign_in_at.present? && admin.last_sign_in_at.to_i > token[:iat]) | ||
end | ||
|
||
def sign_in_admin(admin) | ||
admin.current_sign_in_at = Time.current | ||
admin.current_sign_in_ip = request.remote_ip | ||
admin.sign_in_count = 1 | ||
|
||
# disable validations to allow saving without password or passkey credentials | ||
admin.save!(validate: false) | ||
session[:admin_user_id] = admin.id | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# frozen_string_literal: true | ||
|
||
module Koi | ||
module Controller | ||
module JsonWebToken | ||
extend ActiveSupport::Concern | ||
|
||
SECRET_KEY = Rails.application.secret_key_base | ||
|
||
def encode_token(**payload) | ||
JWT.encode(payload, SECRET_KEY) | ||
end | ||
|
||
def decode_token(token) | ||
payload = JWT.decode(token, SECRET_KEY)[0] | ||
HashWithIndifferentAccess.new(payload) | ||
rescue JWT::DecodeError | ||
nil | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<%= turbo_stream.replace "invite" do %> | ||
<div class="action copy-to-clipboard govuk-input__wrapper" data-controller="clipboard" data-clipboard-supported-class="clipboard--supported"> | ||
<%= text_field_tag :invite_link, new_admin_session_url(token: url_encode(token)), readonly: true, data: { clipboard_target: "source" } %> | ||
<button class="govuk-input__suffix clipboard-button" aria-hidden="true" data-action="clipboard#copy"> | ||
Copy link | ||
</button> | ||
<div class="copy-to-clipboard-feedback" role="alert"></div> | ||
</div> | ||
<% end %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<%= render "layouts/koi/navigation_header" %> | ||
|
||
<%= form_with(model: admin, url: accept_admin_admin_user_path(admin), method: :post) do |form| %> | ||
<%= tag.input name: :token, type: :hidden, value: token %> | ||
<p>Welcome to Admin Terminal</p> | ||
<%= render Koi::SummaryListComponent.new(model: admin, class: "item-table") do |builder| %> | ||
<%= builder.text :name %> | ||
<%= builder.text :email %> | ||
<% end %> | ||
<div class="actions-group"> | ||
<%= form.admin_save "Sign up" %> | ||
</div> | ||
<% end %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,30 @@ | |
it { is_expected.to allow_values("[email protected]").for(:email) } | ||
it { is_expected.not_to allow_values("@b.com", "fail").for(:email) } | ||
|
||
describe "password validation" do | ||
subject!(:admin) { build(:admin, password: "") } | ||
|
||
it "does not validate password on create" do | ||
admin.validate | ||
expect(admin.errors).to be_empty | ||
end | ||
|
||
it "does validate password on update" do | ||
admin.save! | ||
admin.last_sign_in_at = Time.current | ||
admin.validate | ||
expect(admin.errors.messages_for(:password)).to include("can't be blank") | ||
end | ||
|
||
it "does not validate password on update when passkey is present" do | ||
admin.credentials.new(external_id: "id", public_key: "key", sign_count: 1, nickname: "pc") | ||
admin.save! | ||
admin.last_sign_in_at = Time.current | ||
admin.validate | ||
expect(admin.errors).to be_empty | ||
end | ||
end | ||
|
||
describe "#admin_search" do | ||
it { expect(described_class.admin_search(admin.name)).to include(admin) } | ||
it { expect(described_class.admin_search(admin.email)).to include(admin) } | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.