decidim-direct_verifications 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # Decidim::DirectVerifications
2
+
3
+ a [Decidim](https://github.com/decidim/decidim) that provides a verification method called `Direct verification`. Works only on the admin side, final users do not intervene in the verification process.
4
+
5
+ This plugin allows to verify users against the `Direct verification` method by default, but it is not limited to it, it can be used to directly verify users against any other method registered for the organization.
6
+
7
+ You can use this plugin in combination with the great [AccessRequests](https://github.com/mainio/decidim-module-access_requests) plugin from Maino Tech to provide and manage several levels of permissions to users in the platform Decidim.
8
+
9
+ **Other features include:**
10
+
11
+ 1. Allows to massively register users directly in the platform prior (or independently) to verify them by sending them invite emails.
12
+ > **IMPORTANT:**<br>
13
+ > You must only use this feature if you have explicit consent from your users, otherwise you might be violating the [GDPR](https://eugdpr.org/) regulation in EU.
14
+ 2. Can massively revoke authorizations given to any user with any verification method available.
15
+
16
+ ## Usage
17
+
18
+ DirectVerifications will be available as a new verification method under Participants/Verifications.
19
+
20
+ Final users take no action, verification is 100% in the admin side.
21
+
22
+ Verifications can only be managed by the admins. They have available a simple textarea form where to put a list of emails with no special format required. Emails (and names if possible) are detected automatically.
23
+
24
+ With the detected list of emails admin have different options available:
25
+
26
+ 1. Register the list of users in the platform
27
+ 2. Authorize the list of users using any verification method available (defaults to the built-in `Direct verification` method).
28
+ 3. Revoke the authorization for the list of users using any verification method available.
29
+ 4. Check the status of the users in order to know if they are verified or registered.
30
+
31
+ ## Installation
32
+
33
+ Add this line to your application's Gemfile:
34
+
35
+ ```ruby
36
+ gem "decidim-direct_verifications"
37
+ ```
38
+
39
+ And then execute:
40
+
41
+ ```bash
42
+ bundle
43
+ ```
44
+
45
+ ## Contributing
46
+
47
+ See [Decidim](https://github.com/decidim/decidim).
48
+
49
+ ### Developing
50
+
51
+ To start contributing to this project, first:
52
+
53
+ - Install the basic dependencies (such as Ruby and PostgreSQL)
54
+ - Clone this repository
55
+
56
+ Decidim's main repository also provides a Docker configuration file if you
57
+ prefer to use Docker instead of installing the dependencies locally on your
58
+ machine.
59
+
60
+ You can create the development app by running the following commands after
61
+ cloning this project:
62
+
63
+ ```bash
64
+ $ bundle
65
+ $ DATABASE_USERNAME=<username> DATABASE_PASSWORD=<password> bundle exec rake development_app
66
+ ```
67
+
68
+ Note that the database user has to have rights to create and drop a database in
69
+ order to create the dummy test app database.
70
+
71
+ Then to test how the module works in Decidim, start the development server:
72
+
73
+ ```bash
74
+ $ cd development_app
75
+ $ DATABASE_USERNAME=<username> DATABASE_PASSWORD=<password> bundle exec rails s
76
+ ```
77
+
78
+ In case you are using [rbenv](https://github.com/rbenv/rbenv) and have the
79
+ [rbenv-vars](https://github.com/rbenv/rbenv-vars) plugin installed for it, you
80
+ can add the environment variables to the root directory of the project in a file
81
+ named `.rbenv-vars`. If these are defined for the environment, you can omit
82
+ defining these in the commands shown above.
83
+
84
+ #### Code Styling
85
+
86
+ Please follow the code styling defined by the different linters that ensure we
87
+ are all talking with the same language collaborating on the same project. This
88
+ project is set to follow the same rules that Decidim itself follows.
89
+
90
+ [Rubocop](https://rubocop.readthedocs.io/) linter is used for the Ruby language.
91
+
92
+ You can run the code styling checks by running the following commands from the
93
+ console:
94
+
95
+ ```
96
+ $ bundle exec rubocop
97
+ ```
98
+
99
+ To ease up following the style guide, you should install the plugin to your
100
+ favorite editor, such as:
101
+
102
+ - Atom - [linter-rubocop](https://atom.io/packages/linter-rubocop)
103
+ - Sublime Text - [Sublime RuboCop](https://github.com/pderichs/sublime_rubocop)
104
+ - Visual Studio Code - [Rubocop for Visual Studio Code](https://github.com/misogi/vscode-ruby-rubocop)
105
+
106
+ ### Testing
107
+
108
+ To run the tests run the following in the gem development path:
109
+
110
+ ```bash
111
+ $ bundle
112
+ $ DATABASE_USERNAME=<username> DATABASE_PASSWORD=<password> bundle exec rake test_app
113
+ $ DATABASE_USERNAME=<username> DATABASE_PASSWORD=<password> bundle exec rspec
114
+ ```
115
+
116
+ Note that the database user has to have rights to create and drop a database in
117
+ order to create the dummy test app database.
118
+
119
+ In case you are using [rbenv](https://github.com/rbenv/rbenv) and have the
120
+ [rbenv-vars](https://github.com/rbenv/rbenv-vars) plugin installed for it, you
121
+ can add these environment variables to the root directory of the project in a
122
+ file named `.rbenv-vars`. In this case, you can omit defining these in the
123
+ commands shown above.
124
+
125
+ ### Test code coverage
126
+
127
+ If you want to generate the code coverage report for the tests, you can use
128
+ the `SIMPLECOV=1` environment variable in the rspec command as follows:
129
+
130
+ ```bash
131
+ $ SIMPLECOV=1 bundle exec rspec
132
+ ```
133
+
134
+ This will generate a folder named `coverage` in the project root which contains
135
+ the code coverage report.
136
+
137
+ ## License
138
+
139
+ This engine is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
140
+
141
+ ## Also check
142
+
143
+ This plugin has been inspired by these two nice verification methods:
144
+
145
+ - **Access Requests** by Maino Tech: https://github.com/mainio/decidim-module-access_requests
146
+ - **CSV Emails Verifications** by CodiTramuntana: https://github.com/CodiTramuntana/decidim-verifications-csv_emails
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/dev/common_rake"
4
+
5
+ desc "Generates a dummy app for testing"
6
+ task test_app: "decidim:generate_external_test_app"
7
+
8
+ desc "Generates a development app."
9
+ task development_app: "decidim:generate_external_development_app"
10
+
11
+ # Run all tests, include all
12
+ RSpec::Core::RakeTask.new(:spec) do |t|
13
+ t.verbose = false
14
+ end
15
+
16
+ # Run both by default
17
+ task default: [:spec]
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DirectVerifications
5
+ module Verification
6
+ class ConfirmUserAuthorization < Decidim::Verifications::ConfirmUserAuthorization
7
+ def call
8
+ return broadcast(:invalid) unless form.valid?
9
+
10
+ if confirmation_successful?
11
+ authorization.grant!
12
+ broadcast(:ok)
13
+ else
14
+ broadcast(:invalid)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DirectVerifications
5
+ module Verification
6
+ # A command to destroy an authorization.
7
+ class DestroyUserAuthorization < Rectify::Command
8
+ # Public: Initializes the command.
9
+ #
10
+ # authorization - The authorization object to destroy.
11
+ def initialize(authorization)
12
+ @authorization = authorization
13
+ end
14
+
15
+ # Executes the command. Broadcasts these events:
16
+ #
17
+ # - :ok when everything is valid.
18
+ # - :invalid if the authorization couldn't be destroyed.
19
+ #
20
+ # Returns nothing.
21
+ def call
22
+ return broadcast(:invalid) unless authorization
23
+
24
+ destroy_authorization
25
+ broadcast(:ok)
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :authorization
31
+
32
+ def destroy_authorization
33
+ authorization.destroy!
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DirectVerifications
5
+ module Verification
6
+ module Admin
7
+ class DirectVerificationsController < Decidim::Admin::ApplicationController
8
+ include NeedsPermission
9
+
10
+ layout "decidim/admin/users"
11
+
12
+ def index
13
+ enforce_permission_to :index, UserProcessor
14
+ end
15
+
16
+ def create
17
+ enforce_permission_to :create, UserProcessor
18
+
19
+ @userlist = params[:userlist]
20
+ processor = UserProcessor.new(current_organization, current_user)
21
+ processor.emails = extract_emails_to_hash @userlist
22
+ processor.authorization_handler = params[:authorization_handler] if params[:authorization_handler]
23
+ if params[:register]
24
+ processor.register_users
25
+ flash[:warning] = t(".registered", count: processor.emails.count,
26
+ registered: processor.processed[:registered].count,
27
+ errors: processor.errors[:registered].count)
28
+ end
29
+ if params[:authorize] == "in"
30
+ processor.authorize_users
31
+ flash[:notice] = t(".authorized", handler: t("#{processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
32
+ count: processor.emails.count,
33
+ authorized: processor.processed[:authorized].count,
34
+ errors: processor.errors[:authorized].count)
35
+ elsif params[:authorize] == "out"
36
+ processor.revoke_users
37
+ flash[:notice] = t(".revoked", handler: t("#{processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
38
+ count: processor.emails.count,
39
+ revoked: processor.processed[:revoked].count,
40
+ errors: processor.errors[:revoked].count)
41
+ else
42
+ flash[:info] = t(".info", handler: t("#{processor.authorization_handler}.name", scope: "decidim.authorization_handlers"),
43
+ count: processor.emails.count,
44
+ authorized: processor.total(:authorized),
45
+ unconfirmed: processor.total(:unconfirmed),
46
+ registered: processor.total(:registered))
47
+ render(action: :index) && return
48
+ end
49
+ redirect_to direct_verifications_path
50
+ end
51
+
52
+ def permission_class_chain
53
+ [
54
+ Decidim::DirectVerifications::Verification::Admin::Permissions,
55
+ Decidim::Admin::Permissions,
56
+ Decidim::Permissions
57
+ ]
58
+ end
59
+
60
+ def permission_scope
61
+ :admin
62
+ end
63
+
64
+ private
65
+
66
+ def extract_emails_to_hash(txt)
67
+ reg = /([^@\r\n]*)\b([A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,})\b/i
68
+ txt.scan(reg).map { |m| [m[1], m[0].delete("<>").strip] }.to_h
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DirectVerifications
5
+ module Verification
6
+ class AuthorizationsController < Decidim::ApplicationController
7
+ def new
8
+ flash[:alert] = t("authorizations.new.no_action", scope: "decidim.direct_verifications.verification")
9
+ redirect_to decidim_verifications.authorizations_path
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DirectVerifications
5
+ module Verification
6
+ # A form object to be used when public users want to get verified by
7
+ # DirectVerifications verificator
8
+ class DirectVerificationsForm < AuthorizationHandler
9
+ # This is the input (from the user) to validate against
10
+ attribute :name, String
11
+ attribute :email, String
12
+
13
+ # This is the validation to perform
14
+ # If passed, an authorization is created
15
+ validates :email, presence: true
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module DirectVerifications
5
+ module Verification
6
+ module Admin
7
+ # Defines the abilities related to direct_verifications for a logged in admin user.
8
+ class Permissions < Decidim::DefaultPermissions
9
+ def permissions
10
+ return permission_action if permission_action.scope != :admin
11
+ if user.organization.available_authorizations.include?("direct_verifications")
12
+ allow! if permission_action.subject == Decidim::DirectVerifications::UserProcessor
13
+ permission_action
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+
2
+ <div class="card">
3
+ <div class="card-divider">
4
+ <h2 class="card-title">
5
+ <%= t('admin.index.title', scope: 'decidim.direct_verifications.verification') %>
6
+ </h2>
7
+ </div>
8
+ <div class="card-section">
9
+ <p><%= t('decidim.direct_verifications.verification.admin.new.info') %></p>
10
+ <%= form_tag direct_verifications_path, multipart: true, class: 'form' do %>
11
+ <%= label_tag :userlist, t('admin.new.textarea', scope: 'decidim.direct_verifications.verification') %>
12
+ <%= text_area_tag :userlist, @userlist, rows: 10 %>
13
+ <label>
14
+ <%= check_box_tag :register %>
15
+ <%= t('admin.new.register', scope: 'decidim.direct_verifications.verification') %>
16
+ </label>
17
+ <label>
18
+ <%= radio_button_tag :authorize, 'in' %>
19
+ <%= t('admin.new.authorize', scope: 'decidim.direct_verifications.verification') %>
20
+ </label>
21
+ <label>
22
+ <%= radio_button_tag :authorize, 'out' %>
23
+ <%= t('admin.new.revoke', scope: 'decidim.direct_verifications.verification') %>
24
+ </label>
25
+ <label>
26
+ <%= radio_button_tag :authorize, 'check', true %>
27
+ <%= t('admin.new.check', scope: 'decidim.direct_verifications.verification') %>
28
+ </label>
29
+
30
+ <%= label_tag :userlist, t('admin.new.authorization_handler', scope: 'decidim.direct_verifications.verification') %>
31
+ <%= select_tag :authorization_handler, options_for_select(current_organization.available_authorizations.map { |a|
32
+ [t("#{a}.name", scope: "decidim.authorization_handlers"), a]
33
+ }, :direct_verifications) %>
34
+
35
+ <%= submit_tag t('admin.new.submit', scope: 'decidim.direct_verifications.verification'), class: 'button' %>
36
+
37
+ <% end %>
38
+
39
+ </div>
40
+ </div>
@@ -0,0 +1,43 @@
1
+ ---
2
+ ca:
3
+ decidim:
4
+ authorization_handlers:
5
+ admin:
6
+ direct_verifications:
7
+ help:
8
+ - 'Permet la introducció massiva d''usuaris per tal de:'
9
+ - Registrar-los directament a la organització amb l'enviament d'invitacions
10
+ - Verificar-los en qualsevol mètode de verificació actiu
11
+ - Revocar la verificació en qualsevol mètode de verificació actiu
12
+ direct_verifications:
13
+ explanation: Verificació manual per par dels administradors de l'organització
14
+ name: Verificació directa
15
+ direct_verifications:
16
+ verification:
17
+ admin:
18
+ direct_verifications:
19
+ create:
20
+ authorized: S'han verificat correctament %{authorized} usuaris utilitzant
21
+ [%{handler}] (%{count} detectats, %{errors} errors)
22
+ info: S'han detectat %{count} usuaris registrats, dels quals %{registered}
23
+ estan registrats, %{unconfirmed} sense confirmar i %{authorized} autoritzats
24
+ utilitzant [%{handler}]
25
+ registered: S'han registrat correctament %{registered} usuaris (%{count}
26
+ detectats, %{errors} errors)
27
+ revoked: S'ha revocat correctament la verificació de %{revoked} usuaris
28
+ utilitzant [%{handler}] (%{count} detectats, %{errors} errors)
29
+ index:
30
+ title: Inscriu i autoritza usuaris
31
+ new:
32
+ authorization_handler: 'Mètode de verificació:'
33
+ authorize: Autoritza els usuaris
34
+ check: Comprova l'estat dels usuaris
35
+ info: Introdueix aquí els emails, un per línia. Si els emails estan precedits
36
+ per un text, s'interpretarà com el nom de l'usuari
37
+ register: Registra els usuaris a la plataforma (si existeixen s'ignoraran)
38
+ revoke: Revoca l'autorització dels usuaris
39
+ submit: Envia i processa el llistat
40
+ textarea: 'Llista d''emails:'
41
+ authorizations:
42
+ new:
43
+ no_action: Aquest mètode requereix que un administrador us verifiqui