decidim-ub 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +51 -0
- data/Rakefile +38 -0
- data/app/commands/decidim/ub/sync_user.rb +41 -0
- data/app/controllers/concerns/decidim/devise_authentication_methods.rb +11 -0
- data/app/forms/decidim/ub/verifications/ub.rb +33 -0
- data/app/forms/decidim/ub/verifications/ub_ant.rb +11 -0
- data/app/forms/decidim/ub/verifications/ub_est.rb +11 -0
- data/app/forms/decidim/ub/verifications/ub_pas.rb +11 -0
- data/app/forms/decidim/ub/verifications/ub_pdi.rb +11 -0
- data/app/forms/decidim/ub/verifications/ub_pex.rb +11 -0
- data/app/helpers/decidim/ub/omniauth_helper_override.rb +19 -0
- data/app/jobs/decidim/ub/auto_verification_job.rb +55 -0
- data/app/jobs/decidim/ub/omniauth_user_sync_job.rb +24 -0
- data/app/models/concerns/decidim/ub/user_override.rb +19 -0
- data/app/packs/entrypoints/decidim_ub.js +2 -0
- data/app/packs/images/ub_logo.svg +2401 -0
- data/config/assets.rb +8 -0
- data/config/i18n-tasks.yml +7 -0
- data/config/locales/ca.yml +31 -0
- data/config/locales/en.yml +31 -0
- data/config/locales/es.yml +31 -0
- data/db/migrate/20240709154301_add_ub_roles_to_users.rb +7 -0
- data/lib/decidim/ub/engine.rb +57 -0
- data/lib/decidim/ub/test/factories.rb +3 -0
- data/lib/decidim/ub/version.rb +10 -0
- data/lib/decidim/ub.rb +36 -0
- data/lib/generators/decidim/app_templates/test/initializer.rb +11 -0
- data/lib/omniauth/strategies/ub.rb +43 -0
- data/lib/omniauth/ub.rb +3 -0
- metadata +118 -0
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Decidim::Ub
|
2
|
+
|
3
|
+
[![[CI] Lint](https://github.com/Platoniq/decidim-module-ub/actions/workflows/lint.yml/badge.svg)](https://github.com/Platoniq/decidim-module-ub/actions/workflows/lint.yml)
|
4
|
+
[![[CI] Test](https://github.com/Platoniq/decidim-module-ub/actions/workflows/test.yml/badge.svg)](https://github.com/Platoniq/decidim-module-ub/actions/workflows/test.yml)
|
5
|
+
[](https://codeclimate.com/github/Platoniq/decidim-module-ub/maintainability)
|
6
|
+
[](https://coveralls.io/github/Platoniq/decidim-module-ub?branch=main)
|
7
|
+
|
8
|
+
A Decidim module to sync users from Universitat de Barcelona who connect to the platform.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem "decidim-ub", git: "https://github.com/Platoniq/decidim-module-ub"
|
16
|
+
```
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
|
20
|
+
```bash
|
21
|
+
bundle
|
22
|
+
bundle exec rails decidim_ub:install:migrations
|
23
|
+
bundle exec rails db:migrate
|
24
|
+
```
|
25
|
+
|
26
|
+
## Configuration
|
27
|
+
|
28
|
+
You need to configure some environment variables for the OAuth client:
|
29
|
+
|
30
|
+
| ENV | Description | Example | Default |
|
31
|
+
|------------------|-------------------------------------------|-----------------------------|----------------------------|
|
32
|
+
| UB_CLIENT_ID | The OAuth2 client ID | `your-client-id` | |
|
33
|
+
| UB_CLIENT_SECRET | The OAuth2 client secret | `your-client-secret` | |
|
34
|
+
| UB_SITE | The OAuth2 site | `https://example.org/oauth` | |
|
35
|
+
| UB_AUTHORIZE_URL | The path for the authorization URL | `/authorize` | |
|
36
|
+
| UB_TOKEN_URL | The path for the token URL | `/token` | |
|
37
|
+
| UB_ICON | The path for the icon shown in the button | `media/images/my_icon.svg` | `media/images/ub_logo.svg` |
|
38
|
+
|
39
|
+
## Contributing
|
40
|
+
|
41
|
+
Contributions are welcome !
|
42
|
+
|
43
|
+
We expect the contributions to follow the [Decidim's contribution guide](https://github.com/decidim/decidim/blob/develop/CONTRIBUTING.adoc).
|
44
|
+
|
45
|
+
## Security
|
46
|
+
|
47
|
+
Security is very important to us. If you have any issue regarding security, please disclose the information responsibly by sending an email to __francisco.bolivar [at] nazaries [dot] com__ and not by creating a Github issue.
|
48
|
+
|
49
|
+
## License
|
50
|
+
|
51
|
+
This engine is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/dev/common_rake"
|
4
|
+
require "fileutils"
|
5
|
+
|
6
|
+
def install_module(path)
|
7
|
+
Dir.chdir(path) do
|
8
|
+
system("bundle exec rake decidim_ub:install:migrations")
|
9
|
+
system("bundle exec rake db:migrate")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def install_initializer(path, env)
|
14
|
+
Dir.chdir(path) do
|
15
|
+
FileUtils.cp(
|
16
|
+
"#{__dir__}/lib/generators/decidim/app_templates/#{env}/initializer.rb",
|
17
|
+
"config/initializers/decidim_ub_config.rb"
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def seed_db(path)
|
23
|
+
Dir.chdir(path) do
|
24
|
+
system("bundle exec rake db:seed")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Generates a dummy app for testing"
|
29
|
+
task test_app: "decidim:generate_external_test_app" do
|
30
|
+
ENV["RAILS_ENV"] = "test"
|
31
|
+
install_initializer("spec/decidim_dummy_app", "test")
|
32
|
+
install_module("spec/decidim_dummy_app")
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Generates a development app."
|
36
|
+
task development_app: "decidim:generate_external_development_app" do
|
37
|
+
install_module("development_app")
|
38
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Ub
|
5
|
+
class SyncUser < Decidim::Command
|
6
|
+
# Public: Initializes the command.
|
7
|
+
#
|
8
|
+
# user - A decidim user
|
9
|
+
# roles - The roles of the user
|
10
|
+
def initialize(user, roles)
|
11
|
+
@user = user
|
12
|
+
@roles = roles
|
13
|
+
end
|
14
|
+
|
15
|
+
# Executes the command. Broadcasts these events:
|
16
|
+
#
|
17
|
+
# - :ok when everything is valid.
|
18
|
+
# - :invalid if we couldn't proceed.
|
19
|
+
#
|
20
|
+
# Returns nothing.
|
21
|
+
def call
|
22
|
+
update_user!
|
23
|
+
ActiveSupport::Notifications.publish("decidim.ub.user.updated", user.id)
|
24
|
+
broadcast(:ok)
|
25
|
+
rescue StandardError => e
|
26
|
+
broadcast(:invalid, e.message)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :user, :roles
|
32
|
+
|
33
|
+
def update_user!
|
34
|
+
return unless user.ub_identity?
|
35
|
+
|
36
|
+
user.ub_roles = roles
|
37
|
+
user.save!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module Ub
|
7
|
+
module Verifications
|
8
|
+
class Ub < Decidim::AuthorizationHandler
|
9
|
+
validate :user_valid
|
10
|
+
|
11
|
+
def unique_id
|
12
|
+
Digest::SHA512.hexdigest("#{role}/#{uid}-#{Rails.application.secrets.secret_key_base}")
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def organization
|
18
|
+
current_organization || user&.organization
|
19
|
+
end
|
20
|
+
|
21
|
+
def uid
|
22
|
+
user.ub_identity
|
23
|
+
end
|
24
|
+
|
25
|
+
def user_valid
|
26
|
+
errors.add(:user, "decidim.ub.errors.missing_role") unless user.ub_roles.include?(role)
|
27
|
+
end
|
28
|
+
|
29
|
+
def role = raise NotImplementedError
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Ub
|
5
|
+
module OmniauthHelperOverride
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
alias_method :original_normalize_provider_name, :normalize_provider_name
|
10
|
+
|
11
|
+
def normalize_provider_name(provider)
|
12
|
+
return "Universitat de Barcelona" if provider == :ub
|
13
|
+
|
14
|
+
original_normalize_provider_name(provider)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Ub
|
5
|
+
class AutoVerificationJob < ApplicationJob
|
6
|
+
queue_as :default
|
7
|
+
|
8
|
+
def perform(user_id)
|
9
|
+
@user = Decidim::User.find(user_id)
|
10
|
+
@auths = Decidim::Ub.roles_to_auth_name(@user.ub_roles & Decidim::Ub::ROLES)
|
11
|
+
update_auths
|
12
|
+
rescue ActiveRecord::RecordNotFound
|
13
|
+
Rails.logger.error "AutoVerificationJob: ERROR: model not found for user #{user_id}"
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def update_auths
|
19
|
+
current_auths = user_auths.pluck(:name)
|
20
|
+
(current_auths - @auths).each { |name| remove_auth(user_auths.find_by(name:)) }
|
21
|
+
(@auths - current_auths).each { |name| create_auth(name) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_auth(name)
|
25
|
+
return unless (handler = Decidim::AuthorizationHandler.handler_for(name, user: @user))
|
26
|
+
|
27
|
+
Decidim::Verifications::AuthorizeUser.call(handler, @user.organization) do
|
28
|
+
on(:ok) do
|
29
|
+
Rails.logger.info "AutoVerificationJob: Success: created auth #{name} for user #{handler.user.id}"
|
30
|
+
end
|
31
|
+
|
32
|
+
on(:invalid) do
|
33
|
+
Rails.logger.error "AutoVerificationJob: ERROR: not created auth #{name} for user #{handler.user&.id}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def remove_auth(auth)
|
39
|
+
Decidim::Verifications::DestroyUserAuthorization.call(auth) do
|
40
|
+
on(:ok) do
|
41
|
+
Rails.logger.info "AutoVerificationJob: Success: removed auth #{auth.name} for user #{auth.user.id}"
|
42
|
+
end
|
43
|
+
|
44
|
+
on(:invalid) do
|
45
|
+
Rails.logger.error "AutoVerificationJob: ERROR: not removed auth #{auth.name} for user #{auth.user&.id}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def user_auths
|
51
|
+
@user_auths ||= Decidim::Authorization.where(user: @user, name: Decidim::Ub.authorizations)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Ub
|
5
|
+
class OmniauthUserSyncJob < ApplicationJob
|
6
|
+
queue_as :default
|
7
|
+
|
8
|
+
def perform(data)
|
9
|
+
user = Decidim::User.find(data[:user_id])
|
10
|
+
return unless user.ub_identity?
|
11
|
+
|
12
|
+
Decidim::Ub::SyncUser.call(user, data.dig(:raw_data, :info, :roles)) do
|
13
|
+
on(:ok) do
|
14
|
+
Rails.logger.info "OmniauthUserSyncJob: Success: Ub roles updated for user #{user.id}"
|
15
|
+
end
|
16
|
+
|
17
|
+
on(:invalid) do |message|
|
18
|
+
Rails.logger.error "OmniauthUserSyncJob: ERROR: Error updating ub roles '#{message}'"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Ub
|
5
|
+
module UserOverride
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
def ub_identity
|
10
|
+
identities.find_by(provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME)
|
11
|
+
end
|
12
|
+
|
13
|
+
def ub_identity?
|
14
|
+
identities.exists?(provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|