Add account management
This commit is contained in:
parent
882d0a51ed
commit
4f190f67f0
5
Gemfile
5
Gemfile
@ -4,13 +4,14 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
||||
ruby "3.1.2"
|
||||
|
||||
gem "bootsnap", require: false
|
||||
gem "clearance"
|
||||
gem "dotenv-rails"
|
||||
gem "importmap-rails"
|
||||
gem "pg", "~> 1.1"
|
||||
gem "propshaft"
|
||||
gem "puma", "~> 5.0"
|
||||
gem "rails", "~> 7.0.3"
|
||||
gem "dotenv-rails"
|
||||
gem "pundit"
|
||||
gem "rails", "~> 7.0.3"
|
||||
gem "ransack"
|
||||
|
||||
group :development, :test do
|
||||
|
19
Gemfile.lock
19
Gemfile.lock
@ -66,10 +66,22 @@ GEM
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
tzinfo (~> 2.0)
|
||||
argon2 (2.1.1)
|
||||
ffi (~> 1.14)
|
||||
ffi-compiler (~> 1.0)
|
||||
bcrypt (3.1.18)
|
||||
bindex (0.8.1)
|
||||
bootsnap (1.12.0)
|
||||
msgpack (~> 1.2)
|
||||
builder (3.2.4)
|
||||
clearance (2.6.0)
|
||||
actionmailer (>= 5.0)
|
||||
activemodel (>= 5.0)
|
||||
activerecord (>= 5.0)
|
||||
argon2 (~> 2.0, >= 2.0.2)
|
||||
bcrypt (>= 3.1.1)
|
||||
email_validator (~> 2.0)
|
||||
railties (>= 5.0)
|
||||
concurrent-ruby (1.1.10)
|
||||
crass (1.0.6)
|
||||
debug (1.5.0)
|
||||
@ -80,7 +92,13 @@ GEM
|
||||
dotenv-rails (2.7.6)
|
||||
dotenv (= 2.7.6)
|
||||
railties (>= 3.2)
|
||||
email_validator (2.2.3)
|
||||
activemodel
|
||||
erubi (1.10.0)
|
||||
ffi (1.15.5)
|
||||
ffi-compiler (1.0.1)
|
||||
ffi (>= 1.0.0)
|
||||
rake
|
||||
globalid (1.0.0)
|
||||
activesupport (>= 5.0)
|
||||
i18n (1.10.0)
|
||||
@ -186,6 +204,7 @@ PLATFORMS
|
||||
|
||||
DEPENDENCIES
|
||||
bootsnap
|
||||
clearance
|
||||
debug
|
||||
dotenv-rails
|
||||
importmap-rails
|
||||
|
@ -1,2 +1,3 @@
|
||||
class ApplicationController < ActionController::Base
|
||||
include Clearance::Controller
|
||||
end
|
||||
|
20
app/controllers/boards_controller.rb
Normal file
20
app/controllers/boards_controller.rb
Normal file
@ -0,0 +1,20 @@
|
||||
class BoardsController < ApplicationController
|
||||
before_action :require_login
|
||||
|
||||
def edit
|
||||
@users = User.where(active: true)
|
||||
@users += Array.new(5 - @users.size) { User.new }
|
||||
end
|
||||
|
||||
def update
|
||||
User.update_board_members(board_params)
|
||||
|
||||
redirect_to edit_board_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def board_params
|
||||
params.require('users')
|
||||
end
|
||||
end
|
@ -1,4 +1,5 @@
|
||||
class ContributionsController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :set_member, only: %i[ new create ]
|
||||
before_action :set_contribution, only: %i[ edit update delete destroy ]
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
class MembersController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :set_member, only: %i[ show edit update delete destroy ]
|
||||
helper_method :sort_params
|
||||
|
||||
|
9
app/guards/active_guard.rb
Normal file
9
app/guards/active_guard.rb
Normal file
@ -0,0 +1,9 @@
|
||||
class ActiveGuard < Clearance::SignInGuard
|
||||
def call
|
||||
if signed_in? && !current_user.active
|
||||
failure(t('sessions.new.deactivated_error'))
|
||||
else
|
||||
next_guard
|
||||
end
|
||||
end
|
||||
end
|
27
app/models/user.rb
Normal file
27
app/models/user.rb
Normal file
@ -0,0 +1,27 @@
|
||||
class User < ApplicationRecord
|
||||
include Clearance::User
|
||||
|
||||
def self.update_board_members(new_emails)
|
||||
where(active: true).each do |user|
|
||||
if !new_emails.include?(user.email)
|
||||
user.update(active: false)
|
||||
|
||||
# TODO: notify board member of deactivation
|
||||
end
|
||||
end
|
||||
|
||||
new_emails.each do |email|
|
||||
user = User.find_by(email: email)
|
||||
|
||||
if user
|
||||
if !user.active?
|
||||
# TODO: notify board member of activation
|
||||
user.update(active: true, password: SecureRandom.hex(32))
|
||||
end
|
||||
else
|
||||
# TODO: notify board member of activation
|
||||
User.create(email: email, password: SecureRandom.hex(32))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
19
app/views/boards/edit.html.erb
Normal file
19
app/views/boards/edit.html.erb
Normal file
@ -0,0 +1,19 @@
|
||||
<h1><%= t('boards.edit.title') %></h1>
|
||||
|
||||
<p><%= t('boards.edit.warning') %></p>
|
||||
|
||||
<%= form_with scope: :users, url: board_path, method: :put do |form| %>
|
||||
<table class='lined'>
|
||||
<% @users.each do |user| %>
|
||||
<tr>
|
||||
<td>
|
||||
<%= form.email_field nil, value: user.email %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
|
||||
<div>
|
||||
<%= form.submit %>
|
||||
</div>
|
||||
<% end %>
|
8
app/views/clearance_mailer/change_password.html.erb
Normal file
8
app/views/clearance_mailer/change_password.html.erb
Normal file
@ -0,0 +1,8 @@
|
||||
<p><%= t(".opening") %></p>
|
||||
|
||||
<p>
|
||||
<%= link_to t(".link_text", default: "Change my password"),
|
||||
url_for([@user, :password, action: :edit, token: @user.confirmation_token]) %>
|
||||
</p>
|
||||
|
||||
<p><%= t(".closing") %></p>
|
5
app/views/clearance_mailer/change_password.text.erb
Normal file
5
app/views/clearance_mailer/change_password.text.erb
Normal file
@ -0,0 +1,5 @@
|
||||
<%= t(".opening") %>
|
||||
|
||||
<%= url_for([@user, :password, action: :edit, token: @user.confirmation_token]) %>
|
||||
|
||||
<%= t(".closing") %>
|
@ -11,9 +11,19 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav>
|
||||
<%= link_to t('navigation.members'), members_path %>
|
||||
</nav>
|
||||
<% if signed_in? %>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><%= link_to t('navigation.members'), members_path %></li>
|
||||
<li><%= link_to t('navigation.board'), edit_board_path %></li>
|
||||
<li>
|
||||
<%= button_to sign_out_path, method: :delete do %>
|
||||
Sign out of <%= current_user.email %>
|
||||
<% end %>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<% end %>
|
||||
|
||||
<%= yield %>
|
||||
</body>
|
||||
|
3
app/views/passwords/create.html.erb
Normal file
3
app/views/passwords/create.html.erb
Normal file
@ -0,0 +1,3 @@
|
||||
<div id="clearance" class="password-reset">
|
||||
<p><%= t(".description") %></p>
|
||||
</div>
|
18
app/views/passwords/edit.html.erb
Normal file
18
app/views/passwords/edit.html.erb
Normal file
@ -0,0 +1,18 @@
|
||||
<div id="clearance" class="password-reset">
|
||||
<h2><%= t(".title") %></h2>
|
||||
|
||||
<p><%= t(".description") %></p>
|
||||
|
||||
<%= form_for :password_reset,
|
||||
url: [@user, :password, token: @user.confirmation_token],
|
||||
html: { method: :put } do |form| %>
|
||||
<div class="password-field">
|
||||
<%= form.label :password %>
|
||||
<%= form.password_field :password %>
|
||||
</div>
|
||||
|
||||
<div class="submit-field">
|
||||
<%= form.submit %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
16
app/views/passwords/new.html.erb
Normal file
16
app/views/passwords/new.html.erb
Normal file
@ -0,0 +1,16 @@
|
||||
<div id="clearance" class="password-reset">
|
||||
<h2><%= t(".title") %></h2>
|
||||
|
||||
<p><%= t(".description") %></p>
|
||||
|
||||
<%= form_for :password, url: passwords_path do |form| %>
|
||||
<div class="text-field">
|
||||
<%= form.label :email %>
|
||||
<%= form.email_field :email %>
|
||||
</div>
|
||||
|
||||
<div class="submit-field">
|
||||
<%= form.submit %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
28
app/views/sessions/_form.html.erb
Normal file
28
app/views/sessions/_form.html.erb
Normal file
@ -0,0 +1,28 @@
|
||||
<%= form_for :session, url: session_path do |form| %>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<%= form.label :email %>
|
||||
</td>
|
||||
<td>
|
||||
<%= form.email_field :email %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><%= form.label :password %></td>
|
||||
<td><%= form.password_field :password %></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="submit-field">
|
||||
<%= form.submit %>
|
||||
</div>
|
||||
|
||||
<div class="other-links">
|
||||
<% if Clearance.configuration.allow_sign_up? %>
|
||||
<%= link_to t(".sign_up"), sign_up_path %>
|
||||
<% end %>
|
||||
<%= link_to t(".forgot_password"), new_password_path %>
|
||||
</div>
|
||||
<% end %>
|
5
app/views/sessions/new.html.erb
Normal file
5
app/views/sessions/new.html.erb
Normal file
@ -0,0 +1,5 @@
|
||||
<div id="clearance" class="sign-in">
|
||||
<h2><%= t(".title") %></h2>
|
||||
|
||||
<%= render partial: '/sessions/form' %>
|
||||
</div>
|
@ -53,6 +53,10 @@ Rails.application.configure do
|
||||
enable_starttls_auto: true,
|
||||
}
|
||||
|
||||
config.action_mailer.default_url_options = {
|
||||
host: ENV['BASE_HOST'],
|
||||
}
|
||||
|
||||
# Print deprecation notices to the Rails logger.
|
||||
config.active_support.deprecation = :log
|
||||
|
||||
|
8
config/initializers/clearance.rb
Normal file
8
config/initializers/clearance.rb
Normal file
@ -0,0 +1,8 @@
|
||||
Clearance.configure do |config|
|
||||
config.allow_sign_up = false
|
||||
config.mailer_sender = ENV['SMTP_FROM_ADDRESS']
|
||||
config.rotate_csrf_on_sign_in = true
|
||||
config.secure_cookie = true
|
||||
config.signed_cookie = true
|
||||
config.sign_in_guards = ["ActiveGuard"]
|
||||
end
|
64
config/locales/clearance.en.yml
Normal file
64
config/locales/clearance.en.yml
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
en:
|
||||
clearance:
|
||||
models:
|
||||
clearance_mailer:
|
||||
change_password: Change your password
|
||||
clearance_mailer:
|
||||
change_password:
|
||||
closing: If you didn't request this, ignore this email. Your password has
|
||||
not been changed.
|
||||
link_text: Change my password
|
||||
opening: "Someone, hopefully you, requested we send you a link to change
|
||||
your password:"
|
||||
flashes:
|
||||
failure_after_create: Bad email or password.
|
||||
failure_after_update: Password can't be blank.
|
||||
failure_when_forbidden: Please double check the URL or try submitting
|
||||
the form again.
|
||||
failure_when_not_signed_in: Please sign in to continue.
|
||||
failure_when_missing_email: Email can't be blank.
|
||||
helpers:
|
||||
label:
|
||||
password:
|
||||
email: Email address
|
||||
password_reset:
|
||||
password: Choose password
|
||||
session:
|
||||
password: Password
|
||||
user:
|
||||
password: Password
|
||||
submit:
|
||||
password:
|
||||
submit: Reset password
|
||||
password_reset:
|
||||
submit: Save this password
|
||||
session:
|
||||
submit: Sign in
|
||||
user:
|
||||
create: Sign up
|
||||
layouts:
|
||||
application:
|
||||
sign_in: Sign in
|
||||
sign_out: Sign out
|
||||
passwords:
|
||||
create:
|
||||
description: You will receive an email within the next few minutes. It
|
||||
contains instructions for changing your password.
|
||||
edit:
|
||||
description: Your password has been reset. Choose a new password below.
|
||||
title: Change your password
|
||||
new:
|
||||
description: To be emailed a link to reset your password, please enter
|
||||
your email address.
|
||||
title: Reset your password
|
||||
sessions:
|
||||
form:
|
||||
forgot_password: Forgot password?
|
||||
sign_up: Sign up
|
||||
new:
|
||||
title: Sign in
|
||||
users:
|
||||
new:
|
||||
sign_in: Sign in
|
||||
title: Sign up
|
@ -101,3 +101,14 @@ pt:
|
||||
cancelled:
|
||||
subject: "ANSOL - Inscrição cancelada"
|
||||
greetings: "Caro(a) %{display_name}"
|
||||
sessions:
|
||||
new:
|
||||
title: "Entrar"
|
||||
attributes:
|
||||
email: "oi"
|
||||
boards:
|
||||
edit:
|
||||
title: "Actualizar membros da direcção"
|
||||
warning: |
|
||||
Atenção: qualquer endereço que ficar omisso verá a sua conta suspensa e
|
||||
deixará de poder aceder a este sistema.
|
||||
|
@ -3,6 +3,8 @@ Rails.application.routes.draw do
|
||||
|
||||
# Defines the root path route ("/")
|
||||
# root "articles#index"
|
||||
#
|
||||
root to: redirect('/members')
|
||||
|
||||
resources :members do
|
||||
member do
|
||||
@ -16,4 +18,6 @@ Rails.application.routes.draw do
|
||||
get :delete
|
||||
end
|
||||
end
|
||||
|
||||
resource :board, only: [:edit, :update]
|
||||
end
|
||||
|
15
db/migrate/20220625203020_create_users.rb
Normal file
15
db/migrate/20220625203020_create_users.rb
Normal file
@ -0,0 +1,15 @@
|
||||
class CreateUsers < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table :users, id: :uuid do |t|
|
||||
t.timestamps null: false
|
||||
t.string :email, null: false
|
||||
t.string :encrypted_password, limit: 128, null: false
|
||||
t.string :confirmation_token, limit: 128
|
||||
t.string :remember_token, limit: 128, null: false
|
||||
end
|
||||
|
||||
add_index :users, :email
|
||||
add_index :users, :confirmation_token, unique: true
|
||||
add_index :users, :remember_token, unique: true
|
||||
end
|
||||
end
|
7
db/migrate/20220625210821_add_active_to_user.rb
Normal file
7
db/migrate/20220625210821_add_active_to_user.rb
Normal file
@ -0,0 +1,7 @@
|
||||
class AddActiveToUser < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
change_table :users do |t|
|
||||
t.boolean :active, null: false, default: true
|
||||
end
|
||||
end
|
||||
end
|
15
db/schema.rb
generated
15
db/schema.rb
generated
@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.0].define(version: 2022_06_25_181824) do
|
||||
ActiveRecord::Schema[7.0].define(version: 2022_06_25_210821) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pgcrypto"
|
||||
enable_extension "plpgsql"
|
||||
@ -56,6 +56,19 @@ ActiveRecord::Schema[7.0].define(version: 2022_06_25_181824) do
|
||||
t.index ["member_id"], name: "index_notifications_on_member_id"
|
||||
end
|
||||
|
||||
create_table "users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "email", null: false
|
||||
t.string "encrypted_password", limit: 128, null: false
|
||||
t.string "confirmation_token", limit: 128
|
||||
t.string "remember_token", limit: 128, null: false
|
||||
t.boolean "active", default: true, null: false
|
||||
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
|
||||
t.index ["email"], name: "index_users_on_email"
|
||||
t.index ["remember_token"], name: "index_users_on_remember_token", unique: true
|
||||
end
|
||||
|
||||
add_foreign_key "contributions", "members"
|
||||
add_foreign_key "notifications", "members"
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user