forked from AjuntamentdeBarcelona/decidim-module-kids
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add minors management for users (AjuntamentdeBarcelona#15)
* update the form to allow authorizations * update commands * fix system test * normalize * add minors menu * add user concerns and permissions * add permissions spec * add minor account relationship migration * add tutor/minors relationship * add seeds * fix rakefile * add more restrictions on users to be tutors/minors * prevent minors to have minors accounts * init architecture docs * add tutor authorization * normalize locales * fix permissions * add personal_data attribute * add authorizations checks * fix checking specific verification method * refactor personal_data * fix tests * change workflow * check for authorization expiration Co-authored-by: Fran Bolívar <[email protected]>
- Loading branch information
1 parent
10488db
commit 690898d
Showing
28 changed files
with
778 additions
and
14 deletions.
There are no files selected for viewing
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,24 @@ | ||
--- | ||
include: | ||
- "**/*.rb" | ||
exclude: | ||
- spec/**/* | ||
- test/**/* | ||
- vendor/**/* | ||
- node_modules/**/* | ||
- development_app/**/* | ||
- ".bundle/**/*" | ||
require: [] | ||
domains: [] | ||
reporters: | ||
- rubocop | ||
- require_not_found | ||
formatter: | ||
rubocop: | ||
cops: safe | ||
except: [] | ||
only: [] | ||
extra_args: [] | ||
require_paths: [] | ||
plugins: [] | ||
max_files: 10000 |
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,52 @@ | ||
# frozen_string_literal: true | ||
|
||
module Decidim | ||
module Kids | ||
class UserMinorsController < ApplicationController | ||
include Decidim::UserProfile | ||
|
||
before_action do | ||
if tutor_adapter.blank? | ||
flash[:alert] = t("user_minors.no_tutor_authorization", scope: "decidim.kids") | ||
redirect_to decidim.account_path | ||
end | ||
end | ||
|
||
before_action except: [:unverified] do | ||
enforce_permission_to :index, :minor_accounts | ||
redirect_to unverified_user_minors_path unless tutor_verified? | ||
end | ||
|
||
helper_method :minors, :tutor_adapter | ||
|
||
def index; end | ||
|
||
def unverified | ||
redirect_to user_minors_path if tutor_verified? | ||
end | ||
|
||
private | ||
|
||
def minors | ||
current_user.minors | ||
end | ||
|
||
def tutor_verified? | ||
@tutor_verified ||= begin | ||
authorization = granted_authorizations(current_user).where(name: current_organization.tutors_authorization) | ||
authorization.any? && !authorization.first.expired? | ||
end | ||
end | ||
|
||
def tutor_adapter | ||
@tutor_adapter ||= Decidim::Verifications::Adapter.from_element(current_organization.tutors_authorization) | ||
rescue Decidim::Verifications::UnregisteredVerificationManifest | ||
nil | ||
end | ||
|
||
def granted_authorizations(user) | ||
Decidim::Verifications::Authorizations.new(organization: current_organization, user:, granted: true).query | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# frozen_string_literal: true | ||
|
||
module Decidim | ||
module Kids | ||
module UserOverride | ||
extend ActiveSupport::Concern | ||
|
||
included do | ||
has_many :minor_accounts, class_name: "Decidim::Kids::MinorAccount", foreign_key: :decidim_tutor_id, dependent: :destroy | ||
has_many :tutor_accounts, class_name: "Decidim::Kids::MinorAccount", foreign_key: :decidim_minor_id, dependent: :destroy | ||
has_many :minors, through: :minor_accounts, class_name: "Decidim::User", foreign_key: :decidim_minor_id | ||
has_many :tutors, through: :tutor_accounts, class_name: "Decidim::User", foreign_key: :decidim_tutor_id | ||
has_one :minor_data, | ||
foreign_key: "decidim_user_id", | ||
class_name: "Decidim::Kids::MinorData", | ||
inverse_of: :user, | ||
dependent: :destroy | ||
|
||
delegate :name, :email, :birthday, :extra_data, to: :minor_data, prefix: true, allow_nil: true | ||
|
||
def minor? | ||
tutor_accounts.exists? | ||
end | ||
|
||
def tutor? | ||
minor_accounts.exists? | ||
end | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# frozen_string_literal: true | ||
|
||
module Decidim | ||
module Kids | ||
class MinorAccount < ApplicationRecord | ||
self.table_name = "decidim_kids_minor_accounts" | ||
|
||
belongs_to :tutor, | ||
foreign_key: "decidim_tutor_id", | ||
class_name: "Decidim::User" | ||
belongs_to :minor, | ||
foreign_key: "decidim_minor_id", | ||
class_name: "Decidim::User" | ||
|
||
validate :same_organization | ||
validate :can_be_tutor | ||
validate :can_be_minor | ||
|
||
private | ||
|
||
def same_organization | ||
return if tutor.try(:organization) == minor.try(:organization) | ||
|
||
errors.add(:tutor, :invalid) | ||
errors.add(:minor, :invalid) | ||
end | ||
|
||
def can_be_tutor | ||
return unless tutor.minor? || !tutor.confirmed? | ||
|
||
errors.add(:tutor, :invalid) | ||
end | ||
|
||
def can_be_minor | ||
return unless minor.tutor? || minor.admin? | ||
|
||
errors.add(:minor, :invalid) | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# frozen_string_literal: true | ||
|
||
module Decidim | ||
module Kids | ||
class MinorData < ApplicationRecord | ||
include Decidim::RecordEncryptor | ||
self.table_name = "decidim_kids_minor_data" | ||
|
||
belongs_to :user, | ||
foreign_key: "decidim_user_id", | ||
class_name: "Decidim::User" | ||
|
||
encrypt_attribute :name, type: :string | ||
encrypt_attribute :email, type: :string | ||
encrypt_attribute :birthday, type: :string | ||
|
||
validate :user_is_minor | ||
|
||
private | ||
|
||
def user_is_minor | ||
return if user.minor? | ||
|
||
errors.add(:user, :invalid) | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# frozen_string_literal: true | ||
|
||
module Decidim | ||
module Kids | ||
class Permissions < Decidim::DefaultPermissions | ||
def permissions | ||
# return Decidim::Kids::Admin::Permissions.new(user, permission_action, context).permissions if permission_action.scope == :admin | ||
return permission_action if permission_action.scope == :admin | ||
|
||
return permission_action unless user | ||
|
||
if permission_action.subject == :minor_accounts | ||
if !user.organization.minors_participation_enabled? || user.minor? || !user.confirmed? | ||
disallow! | ||
else | ||
case permission_action.action | ||
when :index | ||
allow! | ||
end | ||
end | ||
end | ||
|
||
permission_action | ||
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<% add_decidim_page_title(t("menu", scope: "decidim.kids.user")) %> | ||
<% content_for(:subtitle) { t("menu", scope: "decidim.kids.user") } %> | ||
|
||
list my kids | ||
|
||
<%= minors.pluck :name %> |
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,6 @@ | ||
<% add_decidim_page_title(t("menu", scope: "decidim.kids.user")) %> | ||
<% content_for(:subtitle) { t("menu", scope: "decidim.kids.user") } %> | ||
|
||
<div class="callout warning">You need to verify your identity as a tutor to access this page</div> | ||
|
||
verify yourself sir please with <a href="<%= tutor_adapter.root_path %>"><%= tutor_adapter.description %></a> |
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
13 changes: 13 additions & 0 deletions
13
db/migrate/20221024124523_create_decidim_kids_minor_accounts.rb
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 @@ | ||
# frozen_string_literal: true | ||
|
||
class CreateDecidimKidsMinorAccounts < ActiveRecord::Migration[6.1] | ||
def change | ||
create_table :decidim_kids_minor_accounts do |t| | ||
t.references :decidim_tutor, null: false, index: true, foreign_key: { to_table: "decidim_users" } | ||
t.references :decidim_minor, null: false, index: true, foreign_key: { to_table: "decidim_users" } | ||
t.timestamps | ||
end | ||
|
||
add_index :decidim_kids_minor_accounts, [:decidim_tutor_id, :decidim_minor_id], unique: true, name: "decidim_kids_minor_accounts_unique_tutor_and_minor_ids" | ||
end | ||
end |
14 changes: 14 additions & 0 deletions
14
db/migrate/20221027211859_create_decidim_kids_minor_data.decidim_kids.rb
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,14 @@ | ||
# frozen_string_literal: true | ||
|
||
class CreateDecidimKidsMinorData < ActiveRecord::Migration[6.1] | ||
def change | ||
create_table :decidim_kids_minor_data do |t| | ||
t.references :decidim_user, null: false, index: true | ||
t.string :name # encrypted | ||
t.string :birthday # encrypted | ||
t.string :email # encrypted | ||
t.jsonb :extra_data, null: false, default: {} | ||
t.timestamps | ||
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,31 @@ | ||
# frozen_string_literal: true | ||
|
||
# create some seeds for the admin@example and the user@example | ||
if !Rails.env.production? || ENV.fetch("SEED", nil) | ||
print "Creating seeds for decidim_kids...\n" unless Rails.env.test? | ||
|
||
Decidim::Kids::OrganizationConfig.create!( | ||
organization: Decidim::Organization.first, | ||
enable_minors_participation: true, | ||
tutors_authorization: "dummy_authorization_handler", | ||
minors_authorization: "dummy_authorization_handler" | ||
) | ||
|
||
Decidim::User.where(email: ["[email protected]", "[email protected]"]).each do |user| | ||
2.times do | ||
minor = Decidim::User.create!( | ||
name: "Minor - #{Faker::Name.name}", | ||
nickname: Faker::Twitter.unique.screen_name, | ||
organization: user.organization, | ||
email: Faker::Internet.email, | ||
confirmed_at: Time.current, | ||
locale: I18n.default_locale, | ||
tos_agreement: true, | ||
password: "decidim123456789", | ||
password_confirmation: "decidim123456789", | ||
accepted_tos_version: user.organization.tos_version + 1.hour | ||
) | ||
Decidim::Kids::MinorAccount.create!(minor:, tutor: user) | ||
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,27 @@ | ||
# Minors architecture | ||
|
||
## Organization tweaks | ||
|
||
... | ||
|
||
## Minors an tutors definitions | ||
|
||
1. A minor is a normal user that has a link in the table `minor_accounts` (key `decidim_minor_id`). This table links two users, a tutor and a minor. | ||
2. Similarly, a tutor is a normal user that has a link to the table `minor_accounts` (key `decidim_tutor_id`). | ||
|
||
## Minors account creation workflow | ||
|
||
 | ||
|
||
1. A confirmed and verified (using the system's configured workflow) user account (that is not itself a minor, called a **tutor** from now on) can create a new minor account from the profile menu page. | ||
2. The tutor introduces the minor's personal data (name, email, birth date), this data remains encrypted in the table `minor_accounts` in a JSONB field (`minor_data`). | ||
3. After saving the data, a new user is created in the table `decidim_users` but blocked. No personal data will be stored in this user yet, except for the email. Attributes for the model will be: `blocked: true, blocked_at: Time.current, name: "Pending minor user"`. No emails are sent at this point (no confirmation or invitation emails). | ||
4. Tutor can now click on the "verify minor" and is redirected to the authorization controller in order to verify the minor's data. This verification handler might ask for more personal data to authorize this user. | ||
5. Depending on the configuration of the module (see `Decidim::Kids.minor_authorization_age_attributes`), check that the age returned by the verification is in the configured range. If not, remove the verification. | ||
6. If the verification goes through, the `Authorization` gets stored, and the user is unblocked and personal data is transferred from the table `minor_accounts->minor_data` to the user created (the minor). | ||
7. An email is sent to the new user (aka: confirm the email), once is confirmed it can log in (maybe automatically). A notification to the tutor will be sent when the minor confirms the email. | ||
|
||
|
||
## Emancipation workflow | ||
|
||
... |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.