From ae738db7d117147c3887c9e95954a93a2d61769a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Mon, 1 Jul 2024 17:07:15 +0200 Subject: [PATCH 01/13] OAuth strategy --- .github/workflows/lint.yml | 65 + .github/workflows/test.yml | 67 + .gitignore | 79 +- .mdl_style.rb | 13 + .mdlrc | 1 + .rubocop.yml | 2 + .rubocop_todo.yml | 26 + .ruby-version | 1 + .simplecov | 12 + Gemfile | 31 + Gemfile.lock | 856 ++++++ LICENSE => LICENSE-AGPLv3.txt | 6 +- README.md | 45 +- Rakefile | 28 + .../decidim/omniauth_helper_override.rb | 17 + app/packs/entrypoints/decidim_ub.js | 2 + app/packs/images/ub_logo.svg | 2401 +++++++++++++++++ bin/rails | 7 + config/assets.rb | 8 + config/i18n-tasks.yml | 4 + config/locales/en.yml | 2 + decidim-ub.gemspec | 36 + lib/decidim/ub.rb | 25 + lib/decidim/ub/engine.rb | 38 + lib/decidim/ub/version.rb | 10 + .../decidim/app_templates/test/initializer.rb | 11 + lib/omniauth/strategies/ub.rb | 40 + lib/omniauth/ub.rb | 3 + spec/factories.rb | 1 + spec/lib/decidim/ub/version_spec.rb | 21 + spec/lib/overrides_spec.rb | 35 + spec/spec_helper.rb | 9 + 32 files changed, 3835 insertions(+), 67 deletions(-) create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/test.yml create mode 100644 .mdl_style.rb create mode 100644 .mdlrc create mode 100644 .rubocop.yml create mode 100644 .rubocop_todo.yml create mode 100644 .ruby-version create mode 100644 .simplecov create mode 100644 Gemfile create mode 100644 Gemfile.lock rename LICENSE => LICENSE-AGPLv3.txt (99%) create mode 100644 Rakefile create mode 100644 app/helpers/decidim/omniauth_helper_override.rb create mode 100644 app/packs/entrypoints/decidim_ub.js create mode 100644 app/packs/images/ub_logo.svg create mode 100755 bin/rails create mode 100644 config/assets.rb create mode 100644 config/i18n-tasks.yml create mode 100644 config/locales/en.yml create mode 100644 decidim-ub.gemspec create mode 100644 lib/decidim/ub.rb create mode 100644 lib/decidim/ub/engine.rb create mode 100644 lib/decidim/ub/version.rb create mode 100644 lib/generators/decidim/app_templates/test/initializer.rb create mode 100644 lib/omniauth/strategies/ub.rb create mode 100644 lib/omniauth/ub.rb create mode 100644 spec/factories.rb create mode 100644 spec/lib/decidim/ub/version_spec.rb create mode 100644 spec/lib/overrides_spec.rb create mode 100644 spec/spec_helper.rb diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..d486011 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,65 @@ +name: "[CI] Lint" +on: + push: + branches: + - main + - release/* + - "*-stable" + pull_request: + branches-ignore: + - "chore/l10n*" + +env: + CI: "true" + RUBY_VERSION: 3.1.1 + NODE_VERSION: 18.17.1 + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + main: + name: Tests + runs-on: ubuntu-latest + timeout-minutes: 30 + services: + postgres: + image: postgres:14 + ports: ["5432:5432"] + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + env: + POSTGRES_PASSWORD: postgres + env: + DATABASE_USERNAME: postgres + DATABASE_PASSWORD: postgres + DATABASE_HOST: localhost + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 1 + - uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + ruby-version: ${{ env.RUBY_VERSION }} + - uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + - name: Get npm cache directory path + id: npm-cache-dir-path + run: echo "dir=$(npm get cache)-ub" >> $GITHUB_OUTPUT + - uses: actions/cache@v3 + id: npm-cache + with: + path: ${{ steps.npm-cache-dir-path.outputs.dir }} + key: npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + npm- + - run: bundle exec rubocop -P + name: Lint Ruby files + - run: bundle exec mdl *.md + name: Lint Markdown files diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..a69ae39 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,67 @@ +name: "[CI] Test" +on: + push: + branches: + - main + - release/* + - "*-stable" + pull_request: + branches-ignore: + - "chore/l10n*" + +env: + CI: "true" + RUBY_VERSION: 3.1.1 + NODE_VERSION: 18.17.1 + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + main: + name: Lint + runs-on: ubuntu-latest + timeout-minutes: 30 + env: + DATABASE_USERNAME: postgres + DATABASE_PASSWORD: postgres + DATABASE_HOST: localhost + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 1 + - uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + ruby-version: ${{ env.RUBY_VERSION }} + - uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + - name: Get npm cache directory path + id: npm-cache-dir-path + run: echo "dir=$(npm get cache)-ub" >> $GITHUB_OUTPUT + - uses: actions/cache@v3 + id: npm-cache + with: + path: ${{ steps.npm-cache-dir-path.outputs.dir }} + key: npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + npm- + - run: bundle exec rake test_app + name: Create test app + - run: mkdir -p ./spec/decidim_dummy_app/tmp/screenshots + name: Create the screenshots folder + - uses: nanasess/setup-chromedriver@v2 + - run: RAILS_ENV=test bundle exec rails assets:precompile + name: Precompile assets + working-directory: ./spec/decidim_dummy_app/ + - run: bundle exec rspec + name: RSpec + - uses: codecov/codecov-action@v3 + - uses: actions/upload-artifact@v3 + if: always() + with: + name: screenshots + path: ./spec/decidim_dummy_app/tmp/screenshots + if-no-files-found: ignore diff --git a/.gitignore b/.gitignore index c55bb71..15b1ec6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,69 +1,22 @@ -*.rbc -capybara-*.html -.rspec -/db/*.sqlite3 -/db/*.sqlite3-journal -/db/*.sqlite3-[0-9]* -/public/system +/.bundle/ +/.yardoc +/_yardoc/ /coverage/ -/spec/tmp -*.orig -rerun.txt -pickle-email-*.html +/doc/ +/pkg/ +/spec/reports/ +/tmp/ -# Ignore all logfiles and tempfiles. -/log/* -/tmp/* -!/log/.keep -!/tmp/.keep +# rspec failure tracking +.rspec-failures -# TODO Comment out this rule if you are OK with secrets being uploaded to the repo -config/initializers/secret_token.rb -config/master.key - -# Only include if you have production secrets in this file, which is no longer a Rails default -# config/secrets.yml - -# dotenv, dotenv-rails -# TODO Comment out these rules if environment variables can be committed +# env configuration files .env -.env*.local - -## Environment normalization: -/.bundle -/vendor/bundle - -# these should all be checked in to normalize the environment: -# Gemfile.lock, .ruby-version, .ruby-gemset - -# unless supporting rvm < 1.11.0 or doing something fancy, ignore this: -.rvmrc - -# if using bower-rails ignore default bower_components path bower.json files -/vendor/assets/bower_components -*.bowerrc -bower.json - -# Ignore pow environment settings -.powenv - -# Ignore Byebug command history file. -.byebug_history - -# Ignore node_modules -node_modules/ - -# Ignore precompiled javascript packs -/public/packs -/public/packs-test -/public/assets +.envrc +.rbenv-vars -# Ignore yarn files -/yarn-error.log -yarn-debug.log* -.yarn-integrity +# default test application +spec/decidim_dummy_app -# Ignore uploaded files in development -/storage/* -!/storage/.keep -/public/uploads +# default development application +development_app diff --git a/.mdl_style.rb b/.mdl_style.rb new file mode 100644 index 0000000..5f530cc --- /dev/null +++ b/.mdl_style.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +all + +exclude_rule "first-line-h1" + +exclude_rule "line-length" + +exclude_rule "no-bare-urls" + +exclude_rule "no-inline-html" + +rule "no-trailing-punctuation", punctuation: ".,;:!" diff --git a/.mdlrc b/.mdlrc new file mode 100644 index 0000000..27f3882 --- /dev/null +++ b/.mdlrc @@ -0,0 +1 @@ +style ".mdl_style.rb" diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..928b486 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,2 @@ +inherit_gem: + decidim-dev: rubocop-decidim.yml diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..c80dd73 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,26 @@ +inherit_from: .rubocop_todo.yml + +inherit_gem: + decidim-dev: rubocop-decidim.yml + +inherit_mode: + merge: + - Exclude + +AllCops: + Include: + - "**/*.rb" + - "**/*.rake" + - "**/*.ru" + - "**/Gemfile" + - "**/Rakefile" + Exclude: + - "spec/decidim_dummy_app/**/*" + - "**/spec/decidim_dummy_app/**/*" + - "bin/**/*" + - "node_modules/**/*" + - "**/node_modules/**/*" + - "db/schema.rb" + - "db/migrate/*" + - "vendor/**/*" + - "**/vendor/**/*" diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..94ff29c --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +3.1.1 diff --git a/.simplecov b/.simplecov new file mode 100644 index 0000000..9de065b --- /dev/null +++ b/.simplecov @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +SimpleCov.start do + root ENV.fetch("ENGINE_ROOT", nil) + + add_filter "lib/generators" + add_filter "/spec" +end + +SimpleCov.command_name ENV.fetch("COMMAND_NAME", File.basename(Dir.pwd)) + +SimpleCov.merge_timeout 1800 diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..d10e83c --- /dev/null +++ b/Gemfile @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +ruby RUBY_VERSION + +DECIDIM_VERSION = "~> 0.28.0" + +gem "decidim", DECIDIM_VERSION +gem "decidim-ub", path: "." + +gem "bootsnap", "~> 1.4" + +gem "puma", ">= 6.3.1" + +group :development, :test do + gem "byebug", "~> 11.0", platform: :mri + gem "mdl" + + gem "decidim-dev", DECIDIM_VERSION +end + +group :development do + gem "faker", "~> 3.2" + gem "letter_opener_web", "~> 2.0" + gem "listen", "~> 3.1" + gem "rack-mini-profiler", require: false + gem "spring", "~> 2.0" + gem "spring-watcher-listen", "~> 2.0" + gem "web-console", "~> 4.2" +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..04031cd --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,856 @@ +PATH + remote: . + specs: + decidim-ub (0.1.0) + decidim-core (>= 0.28.0, < 0.29) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (6.1.7.8) + actionpack (= 6.1.7.8) + activesupport (= 6.1.7.8) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailbox (6.1.7.8) + actionpack (= 6.1.7.8) + activejob (= 6.1.7.8) + activerecord (= 6.1.7.8) + activestorage (= 6.1.7.8) + activesupport (= 6.1.7.8) + mail (>= 2.7.1) + actionmailer (6.1.7.8) + actionpack (= 6.1.7.8) + actionview (= 6.1.7.8) + activejob (= 6.1.7.8) + activesupport (= 6.1.7.8) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (6.1.7.8) + actionview (= 6.1.7.8) + activesupport (= 6.1.7.8) + rack (~> 2.0, >= 2.0.9) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (6.1.7.8) + actionpack (= 6.1.7.8) + activerecord (= 6.1.7.8) + activestorage (= 6.1.7.8) + activesupport (= 6.1.7.8) + nokogiri (>= 1.8.5) + actionview (6.1.7.8) + activesupport (= 6.1.7.8) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + active_link_to (1.0.5) + actionpack + addressable + activejob (6.1.7.8) + activesupport (= 6.1.7.8) + globalid (>= 0.3.6) + activemodel (6.1.7.8) + activesupport (= 6.1.7.8) + activerecord (6.1.7.8) + activemodel (= 6.1.7.8) + activesupport (= 6.1.7.8) + activestorage (6.1.7.8) + actionpack (= 6.1.7.8) + activejob (= 6.1.7.8) + activerecord (= 6.1.7.8) + activesupport (= 6.1.7.8) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (6.1.7.8) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) + acts_as_list (1.2.1) + activerecord (>= 6.1) + activesupport (>= 6.1) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + ast (2.4.2) + base64 (0.2.0) + batch-loader (1.5.0) + bcrypt (3.1.20) + better_html (2.1.1) + actionview (>= 6.0) + activesupport (>= 6.0) + ast (~> 2.0) + erubi (~> 1.4) + parser (>= 2.4) + smart_properties + bigdecimal (3.1.8) + bindex (0.8.1) + bootsnap (1.18.3) + msgpack (~> 1.2) + browser (2.7.1) + builder (3.3.0) + bullet (7.1.6) + activesupport (>= 3.0.0) + uniform_notifier (~> 1.11) + byebug (11.1.3) + capybara (3.40.0) + addressable + matrix + mini_mime (>= 0.1.3) + nokogiri (~> 1.11) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + regexp_parser (>= 1.5, < 3.0) + xpath (~> 3.2) + carrierwave (2.2.6) + activemodel (>= 5.0.0) + activesupport (>= 5.0.0) + addressable (~> 2.6) + image_processing (~> 1.1) + marcel (~> 1.0.0) + mini_mime (>= 0.1.3) + ssrf_filter (~> 1.0) + cells (4.1.7) + declarative-builder (< 0.2.0) + declarative-option (< 0.2.0) + tilt (>= 1.4, < 3) + uber (< 0.2.0) + cells-erb (0.1.0) + cells (~> 4.0) + erbse (>= 0.1.1) + cells-rails (0.1.5) + actionpack (>= 5.0) + cells (>= 4.1.6, < 5.0.0) + charlock_holmes (0.7.7) + chef-utils (18.4.12) + concurrent-ruby + childprocess (5.0.0) + commonmarker (0.23.10) + concurrent-ruby (1.3.3) + crack (1.0.0) + bigdecimal + rexml + crass (1.0.6) + css_parser (1.17.1) + addressable + csv (3.3.0) + date (3.3.4) + date_validator (0.12.0) + activemodel (>= 3) + activesupport (>= 3) + decidim (0.28.1) + decidim-accountability (= 0.28.1) + decidim-admin (= 0.28.1) + decidim-api (= 0.28.1) + decidim-assemblies (= 0.28.1) + decidim-blogs (= 0.28.1) + decidim-budgets (= 0.28.1) + decidim-comments (= 0.28.1) + decidim-core (= 0.28.1) + decidim-debates (= 0.28.1) + decidim-forms (= 0.28.1) + decidim-generators (= 0.28.1) + decidim-meetings (= 0.28.1) + decidim-pages (= 0.28.1) + decidim-participatory_processes (= 0.28.1) + decidim-proposals (= 0.28.1) + decidim-sortitions (= 0.28.1) + decidim-surveys (= 0.28.1) + decidim-system (= 0.28.1) + decidim-templates (= 0.28.1) + decidim-verifications (= 0.28.1) + decidim-accountability (0.28.1) + decidim-comments (= 0.28.1) + decidim-core (= 0.28.1) + decidim-admin (0.28.1) + active_link_to (~> 1.0) + decidim-core (= 0.28.1) + devise (~> 4.7) + devise-i18n (~> 1.2) + devise_invitable (~> 2.0, >= 2.0.9) + decidim-api (0.28.1) + commonmarker (~> 0.23.0, >= 0.23.9) + decidim-core (= 0.28.1) + graphql (~> 2.0.0) + graphql-docs (~> 3.0.1) + rack-cors (~> 1.0) + decidim-assemblies (0.28.1) + decidim-core (= 0.28.1) + decidim-blogs (0.28.1) + decidim-admin (= 0.28.1) + decidim-comments (= 0.28.1) + decidim-core (= 0.28.1) + decidim-budgets (0.28.1) + decidim-comments (= 0.28.1) + decidim-core (= 0.28.1) + decidim-comments (0.28.1) + decidim-core (= 0.28.1) + redcarpet (~> 3.5, >= 3.5.1) + decidim-core (0.28.1) + active_link_to (~> 1.0) + acts_as_list (~> 1.0) + batch-loader (~> 1.2) + browser (~> 2.7) + carrierwave (~> 2.2.5, >= 2.2.5) + cells-erb (~> 0.1.0) + cells-rails (~> 0.1.3) + charlock_holmes (~> 0.7) + date_validator (~> 0.12.0) + devise (~> 4.7) + devise-i18n (~> 1.2, < 1.11.1) + diffy (~> 3.3) + doorkeeper (~> 5.6, >= 5.6.6) + doorkeeper-i18n (~> 4.0) + file_validators (~> 3.0) + fog-local (~> 0.6) + foundation_rails_helper (~> 4.0) + geocoder (~> 1.8) + hashdiff (>= 0.4.0, < 2.0.0) + invisible_captcha (~> 0.12) + kaminari (~> 1.2, >= 1.2.1) + loofah (~> 2.19, >= 2.19.1) + mime-types (>= 1.16, < 4.0) + mini_magick (~> 4.9) + net-smtp (~> 0.3.1) + omniauth (~> 2.0) + omniauth-facebook (~> 5.0) + omniauth-google-oauth2 (~> 1.0) + omniauth-rails_csrf_protection (~> 1.0) + omniauth-twitter (~> 1.4) + paper_trail (~> 12.0) + pg (~> 1.4.0, < 2) + pg_search (~> 2.2) + premailer-rails (~> 1.10) + psych (~> 4.0) + rack (~> 2.2, >= 2.2.6.4) + rack-attack (~> 6.0) + rails (~> 6.1.7, >= 6.1.7.4) + rails-i18n (~> 6.0) + ransack (~> 3.2.1) + redis (~> 4.1) + request_store (~> 1.5.0) + rubyXL (~> 3.4) + rubyzip (~> 2.0) + seven_zip_ruby (~> 1.3) + shakapacker (~> 7.1.0) + valid_email2 (~> 4.0) + web-push (~> 3.0) + wisper (~> 2.0) + decidim-debates (0.28.1) + decidim-comments (= 0.28.1) + decidim-core (= 0.28.1) + decidim-dev (0.28.1) + bullet (~> 7.0) + byebug (~> 11.0) + capybara (~> 3.39) + decidim (= 0.28.1) + erb_lint (~> 0.4.0) + factory_bot_rails (~> 6.2) + faker (~> 3.2) + i18n-tasks (~> 1.0) + nokogiri (~> 1.14, >= 1.14.3) + parallel_tests (~> 4.2) + puma (~> 6.2, >= 6.3.1) + rails-controller-testing (~> 1.0) + rspec (~> 3.12) + rspec-cells (~> 0.3.7) + rspec-html-matchers (~> 0.10) + rspec-rails (~> 6.0) + rspec-retry (~> 0.6.2) + rspec_junit_formatter (~> 0.6.0) + rubocop (~> 1.50.0) + rubocop-faker (~> 1.1) + rubocop-rails (~> 2.19) + rubocop-rspec (~> 2.20) + selenium-webdriver (~> 4.9) + simplecov (~> 0.22.0) + simplecov-cobertura (~> 2.1.0) + w3c_rspec_validators (~> 0.3.0) + webmock (~> 3.18) + wisper-rspec (~> 1.0) + decidim-forms (0.28.1) + decidim-core (= 0.28.1) + wicked_pdf (~> 2.1) + wkhtmltopdf-binary (~> 0.12) + decidim-generators (0.28.1) + decidim-core (= 0.28.1) + decidim-meetings (0.28.1) + decidim-core (= 0.28.1) + decidim-forms (= 0.28.1) + icalendar (~> 2.5) + decidim-pages (0.28.1) + decidim-core (= 0.28.1) + decidim-participatory_processes (0.28.1) + decidim-core (= 0.28.1) + decidim-proposals (0.28.1) + decidim-comments (= 0.28.1) + decidim-core (= 0.28.1) + doc2text (~> 0.4.6) + redcarpet (~> 3.5, >= 3.5.1) + decidim-sortitions (0.28.1) + decidim-admin (= 0.28.1) + decidim-comments (= 0.28.1) + decidim-core (= 0.28.1) + decidim-proposals (= 0.28.1) + decidim-surveys (0.28.1) + decidim-core (= 0.28.1) + decidim-forms (= 0.28.1) + decidim-system (0.28.1) + active_link_to (~> 1.0) + decidim-core (= 0.28.1) + devise (~> 4.7) + devise-i18n (~> 1.2) + devise_invitable (~> 2.0, >= 2.0.9) + decidim-templates (0.28.1) + decidim-core (= 0.28.1) + decidim-forms (= 0.28.1) + decidim-verifications (0.28.1) + decidim-core (= 0.28.1) + declarative-builder (0.1.0) + declarative-option (< 0.2.0) + declarative-option (0.1.0) + devise (4.9.4) + bcrypt (~> 3.0) + orm_adapter (~> 0.1) + railties (>= 4.1.0) + responders + warden (~> 1.2.3) + devise-i18n (1.11.0) + devise (>= 4.9.0) + devise_invitable (2.0.9) + actionmailer (>= 5.0) + devise (>= 4.6) + diff-lcs (1.5.1) + diffy (3.4.2) + doc2text (0.4.7) + nokogiri (>= 1.13.2, < 1.17.0) + rubyzip (~> 2.3.0) + docile (1.4.0) + doorkeeper (5.7.1) + railties (>= 5) + doorkeeper-i18n (4.0.1) + erb_lint (0.4.0) + activesupport + better_html (>= 2.0.1) + parser (>= 2.7.1.4) + rainbow + rubocop + smart_properties + erbse (0.1.4) + temple + erubi (1.13.0) + escape_utils (1.2.2) + excon (0.110.0) + extended-markdown-filter (0.7.0) + html-pipeline (~> 2.9) + factory_bot (6.4.6) + activesupport (>= 5.0.0) + factory_bot_rails (6.4.3) + factory_bot (~> 6.4) + railties (>= 5.0.0) + faker (3.4.1) + i18n (>= 1.8.11, < 2) + faraday (2.9.2) + faraday-net_http (>= 2.0, < 3.2) + faraday-net_http (3.1.0) + net-http + ffi (1.17.0) + ffi (1.17.0-aarch64-linux-gnu) + ffi (1.17.0-aarch64-linux-musl) + ffi (1.17.0-arm-linux-gnu) + ffi (1.17.0-arm-linux-musl) + ffi (1.17.0-arm64-darwin) + ffi (1.17.0-x86-linux-gnu) + ffi (1.17.0-x86-linux-musl) + ffi (1.17.0-x86_64-darwin) + ffi (1.17.0-x86_64-linux-gnu) + ffi (1.17.0-x86_64-linux-musl) + file_validators (3.0.0) + activemodel (>= 3.2) + mime-types (>= 1.0) + fog-core (2.4.0) + builder + excon (~> 0.71) + formatador (>= 0.2, < 2.0) + mime-types + fog-local (0.8.0) + fog-core (>= 1.27, < 3.0) + formatador (1.1.0) + foundation_rails_helper (4.0.1) + actionpack (>= 4.1, < 7.1) + activemodel (>= 4.1, < 7.1) + activesupport (>= 4.1, < 7.1) + railties (>= 4.1, < 7.1) + gemoji (3.0.1) + geocoder (1.8.3) + base64 (>= 0.1.0) + csv (>= 3.0.0) + globalid (1.2.1) + activesupport (>= 6.1) + graphql (2.0.31) + base64 + graphql-docs (3.0.1) + commonmarker (~> 0.16) + escape_utils (~> 1.2.2) + extended-markdown-filter (~> 0.4) + gemoji (~> 3.0) + graphql (~> 2.0) + html-pipeline (~> 2.9) + sass (~> 3.4) + hashdiff (1.1.0) + hashie (5.0.0) + highline (3.0.1) + html-pipeline (2.14.3) + activesupport (>= 2) + nokogiri (>= 1.4) + htmlentities (4.3.4) + i18n (1.14.5) + concurrent-ruby (~> 1.0) + i18n-tasks (1.0.14) + activesupport (>= 4.0.2) + ast (>= 2.1.0) + erubi + highline (>= 2.0.0) + i18n + parser (>= 3.2.2.1) + rails-i18n + rainbow (>= 2.2.2, < 4.0) + terminal-table (>= 1.5.1) + icalendar (2.10.1) + ice_cube (~> 0.16) + ice_cube (0.16.4) + image_processing (1.12.2) + mini_magick (>= 4.9.5, < 5) + ruby-vips (>= 2.0.17, < 3) + invisible_captcha (0.13.0) + rails (>= 3.2.0) + json (2.7.2) + jwt (2.8.2) + base64 + kaminari (1.2.2) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.2.2) + kaminari-activerecord (= 1.2.2) + kaminari-core (= 1.2.2) + kaminari-actionview (1.2.2) + actionview + kaminari-core (= 1.2.2) + kaminari-activerecord (1.2.2) + activerecord + kaminari-core (= 1.2.2) + kaminari-core (1.2.2) + kramdown (2.4.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + launchy (3.0.1) + addressable (~> 2.8) + childprocess (~> 5.0) + letter_opener (1.10.0) + launchy (>= 2.2, < 4) + letter_opener_web (2.0.0) + actionmailer (>= 5.2) + letter_opener (~> 1.7) + railties (>= 5.2) + rexml + listen (3.9.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + logger (1.6.0) + loofah (2.22.0) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + mail (2.8.1) + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + marcel (1.0.4) + matrix (0.4.2) + mdl (0.13.0) + kramdown (~> 2.3) + kramdown-parser-gfm (~> 1.1) + mixlib-cli (~> 2.1, >= 2.1.1) + mixlib-config (>= 2.2.1, < 4) + mixlib-shellout + method_source (1.1.0) + mime-types (3.5.2) + mime-types-data (~> 3.2015) + mime-types-data (3.2024.0604) + mini_magick (4.13.1) + mini_mime (1.1.5) + mini_portile2 (2.8.7) + minitest (5.24.0) + mixlib-cli (2.1.8) + mixlib-config (3.0.27) + tomlrb + mixlib-shellout (3.2.8) + chef-utils + msgpack (1.7.2) + multi_xml (0.6.0) + net-http (0.4.1) + uri + net-imap (0.4.14) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.3.4) + net-protocol + nio4r (2.7.3) + nokogiri (1.16.6) + mini_portile2 (~> 2.8.2) + racc (~> 1.4) + nokogiri (1.16.6-aarch64-linux) + racc (~> 1.4) + nokogiri (1.16.6-arm-linux) + racc (~> 1.4) + nokogiri (1.16.6-arm64-darwin) + racc (~> 1.4) + nokogiri (1.16.6-x86-linux) + racc (~> 1.4) + nokogiri (1.16.6-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.16.6-x86_64-linux) + racc (~> 1.4) + oauth (1.1.0) + oauth-tty (~> 1.0, >= 1.0.1) + snaky_hash (~> 2.0) + version_gem (~> 1.1) + oauth-tty (1.0.5) + version_gem (~> 1.1, >= 1.1.1) + oauth2 (2.0.9) + faraday (>= 0.17.3, < 3.0) + jwt (>= 1.0, < 3.0) + multi_xml (~> 0.5) + rack (>= 1.2, < 4) + snaky_hash (~> 2.0) + version_gem (~> 1.1) + omniauth (2.1.2) + hashie (>= 3.4.6) + rack (>= 2.2.3) + rack-protection + omniauth-facebook (5.0.0) + omniauth-oauth2 (~> 1.2) + omniauth-google-oauth2 (1.1.2) + jwt (>= 2.0) + oauth2 (~> 2.0) + omniauth (~> 2.0) + omniauth-oauth2 (~> 1.8) + omniauth-oauth (1.2.0) + oauth + omniauth (>= 1.0, < 3) + omniauth-oauth2 (1.8.0) + oauth2 (>= 1.4, < 3) + omniauth (~> 2.0) + omniauth-rails_csrf_protection (1.0.2) + actionpack (>= 4.2) + omniauth (~> 2.0) + omniauth-twitter (1.4.0) + omniauth-oauth (~> 1.1) + rack + openssl (3.2.0) + orm_adapter (0.5.0) + paper_trail (12.3.0) + activerecord (>= 5.2) + request_store (~> 1.1) + parallel (1.25.1) + parallel_tests (4.7.1) + parallel + parser (3.3.3.0) + ast (~> 2.4.1) + racc + pg (1.4.6) + pg_search (2.3.6) + activerecord (>= 5.2) + activesupport (>= 5.2) + premailer (1.23.0) + addressable + css_parser (>= 1.12.0) + htmlentities (>= 4.0.0) + premailer-rails (1.12.0) + actionmailer (>= 3) + net-smtp + premailer (~> 1.7, >= 1.7.9) + psych (4.0.6) + stringio + public_suffix (6.0.0) + puma (6.4.2) + nio4r (~> 2.0) + racc (1.8.0) + rack (2.2.9) + rack-attack (6.7.0) + rack (>= 1.0, < 4) + rack-cors (1.1.1) + rack (>= 2.0.0) + rack-mini-profiler (3.3.1) + rack (>= 1.2.0) + rack-protection (3.2.0) + base64 (>= 0.1.0) + rack (~> 2.2, >= 2.2.4) + rack-proxy (0.7.7) + rack + rack-test (2.1.0) + rack (>= 1.3) + rails (6.1.7.8) + actioncable (= 6.1.7.8) + actionmailbox (= 6.1.7.8) + actionmailer (= 6.1.7.8) + actionpack (= 6.1.7.8) + actiontext (= 6.1.7.8) + actionview (= 6.1.7.8) + activejob (= 6.1.7.8) + activemodel (= 6.1.7.8) + activerecord (= 6.1.7.8) + activestorage (= 6.1.7.8) + activesupport (= 6.1.7.8) + bundler (>= 1.15.0) + railties (= 6.1.7.8) + sprockets-rails (>= 2.0.0) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest + nokogiri (>= 1.6) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + rails-i18n (6.0.0) + i18n (>= 0.7, < 2) + railties (>= 6.0.0, < 7) + railties (6.1.7.8) + actionpack (= 6.1.7.8) + activesupport (= 6.1.7.8) + method_source + rake (>= 12.2) + thor (~> 1.0) + rainbow (3.1.1) + rake (13.2.1) + ransack (3.2.1) + activerecord (>= 6.1.5) + activesupport (>= 6.1.5) + i18n + rb-fsevent (0.11.2) + rb-inotify (0.11.1) + ffi (~> 1.0) + redcarpet (3.6.0) + redis (4.8.1) + regexp_parser (2.9.2) + request_store (1.5.1) + rack (>= 1.4) + responders (3.1.1) + actionpack (>= 5.2) + railties (>= 5.2) + rexml (3.3.1) + strscan + rspec (3.13.0) + rspec-core (~> 3.13.0) + rspec-expectations (~> 3.13.0) + rspec-mocks (~> 3.13.0) + rspec-cells (0.3.9) + cells (>= 4.0.0, < 6.0.0) + rspec-rails (>= 3.0.0, < 6.2.0) + rspec-core (3.13.0) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-html-matchers (0.10.0) + nokogiri (~> 1) + rspec (>= 3.0.0.a) + rspec-mocks (3.13.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.13.0) + rspec-rails (6.1.3) + actionpack (>= 6.1) + activesupport (>= 6.1) + railties (>= 6.1) + rspec-core (~> 3.13) + rspec-expectations (~> 3.13) + rspec-mocks (~> 3.13) + rspec-support (~> 3.13) + rspec-retry (0.6.2) + rspec-core (> 3.3) + rspec-support (3.13.1) + rspec_junit_formatter (0.6.0) + rspec-core (>= 2, < 4, != 2.12.0) + rubocop (1.50.2) + json (~> 2.3) + parallel (~> 1.10) + parser (>= 3.2.0.0) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.28.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.31.2) + parser (>= 3.3.0.4) + rubocop-capybara (2.20.0) + rubocop (~> 1.41) + rubocop-factory_bot (2.25.1) + rubocop (~> 1.41) + rubocop-faker (1.1.0) + faker (>= 2.12.0) + rubocop (>= 0.82.0) + rubocop-rails (2.24.1) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.33.0, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) + rubocop-rspec (2.29.1) + rubocop (~> 1.40) + rubocop-capybara (~> 2.17) + rubocop-factory_bot (~> 2.22) + rubocop-rspec_rails (~> 2.28) + rubocop-rspec_rails (2.28.3) + rubocop (~> 1.40) + ruby-progressbar (1.13.0) + ruby-vips (2.2.1) + ffi (~> 1.12) + rubyXL (3.4.27) + nokogiri (>= 1.10.8) + rubyzip (>= 1.3.0) + rubyzip (2.3.2) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + selenium-webdriver (4.22.0) + base64 (~> 0.2) + logger (~> 1.4) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) + semantic_range (3.0.0) + seven_zip_ruby (1.3.0) + shakapacker (7.1.0) + activesupport (>= 5.2) + rack-proxy (>= 0.6.1) + railties (>= 5.2) + semantic_range (>= 2.3.0) + simplecov (0.22.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-cobertura (2.1.0) + rexml + simplecov (~> 0.19) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.4) + smart_properties (1.17.0) + snaky_hash (2.0.1) + hashie + version_gem (~> 1.1, >= 1.1.1) + spring (2.1.1) + spring-watcher-listen (2.0.1) + listen (>= 2.7, < 4.0) + spring (>= 1.2, < 3.0) + sprockets (4.2.1) + concurrent-ruby (~> 1.0) + rack (>= 2.2.4, < 4) + sprockets-rails (3.5.1) + actionpack (>= 6.1) + activesupport (>= 6.1) + sprockets (>= 3.0.0) + ssrf_filter (1.1.2) + stringio (3.1.1) + strscan (3.1.0) + temple (0.10.3) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + thor (1.3.1) + tilt (2.3.0) + timeout (0.4.1) + tomlrb (2.0.3) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + uber (0.1.0) + unicode-display_width (2.5.0) + uniform_notifier (1.16.0) + uri (0.13.0) + valid_email2 (4.0.6) + activemodel (>= 3.2) + mail (~> 2.5) + version_gem (1.1.4) + w3c_rspec_validators (0.3.0) + rails + rspec + w3c_validators + w3c_validators (1.3.7) + json (>= 1.8) + nokogiri (~> 1.6) + rexml (~> 3.2) + warden (1.2.9) + rack (>= 2.0.9) + web-console (4.2.1) + actionview (>= 6.0.0) + activemodel (>= 6.0.0) + bindex (>= 0.4.0) + railties (>= 6.0.0) + web-push (3.0.1) + jwt (~> 2.0) + openssl (~> 3.0) + webmock (3.23.1) + addressable (>= 2.8.0) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) + websocket (1.2.10) + websocket-driver (0.7.6) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + wicked_pdf (2.8.0) + activesupport + wisper (2.0.1) + wisper-rspec (1.1.0) + wkhtmltopdf-binary (0.12.6.7) + xpath (3.2.0) + nokogiri (~> 1.8) + zeitwerk (2.6.16) + +PLATFORMS + aarch64-linux + aarch64-linux-gnu + aarch64-linux-musl + arm-linux + arm-linux-gnu + arm-linux-musl + arm64-darwin + ruby + x86-linux + x86-linux-gnu + x86-linux-musl + x86_64-darwin + x86_64-linux + x86_64-linux-gnu + x86_64-linux-musl + +DEPENDENCIES + bootsnap (~> 1.4) + byebug (~> 11.0) + decidim (~> 0.28.0) + decidim-dev (~> 0.28.0) + decidim-ub! + faker (~> 3.2) + letter_opener_web (~> 2.0) + listen (~> 3.1) + mdl + puma (>= 6.3.1) + rack-mini-profiler + spring (~> 2.0) + spring-watcher-listen (~> 2.0) + web-console (~> 4.2) + +RUBY VERSION + ruby 3.1.1p18 + +BUNDLED WITH + 2.5.4 diff --git a/LICENSE b/LICENSE-AGPLv3.txt similarity index 99% rename from LICENSE rename to LICENSE-AGPLv3.txt index 0ad25db..dbbe355 100644 --- a/LICENSE +++ b/LICENSE-AGPLv3.txt @@ -1,7 +1,7 @@ GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -643,7 +643,7 @@ the "copyright" line and a pointer to where the full notice is found. GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. @@ -658,4 +658,4 @@ specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see -. +. diff --git a/README.md b/README.md index 6b69596..fd30cd6 100644 --- a/README.md +++ b/README.md @@ -1 +1,44 @@ -# decidim-module-ub \ No newline at end of file +# Decidim::Ub + +A Decidim module to sync users from Universitat de Barcelona who connect to the platform. + +## Installation + +Add this line to your application's Gemfile: + +```ruby +gem "decidim-ub", git: "https://github.com/Platoniq/decidim-module-ub" +``` + +And then execute: + +```bash +bundle +``` + +## Configuration + +You need to configure some environment variables for the OAuth client: + +| ENV | Description | Example | Default | +|------------------|-------------------------------------------|-----------------------------|----------------------------| +| UB_CLIENT_ID | The OAuth2 client ID | `your-client-id` | | +| UB_CLIENT_SECRET | The OAuth2 client secret | `your-client-secret` | | +| UB_SITE | The OAuth2 site | `https://example.org/oauth` | | +| UB_AUTHORIZE_URL | The path for the authorization URL | `/authorize` | | +| UB_TOKEN_URL | The path for the token URL | `/token` | | +| UB_ICON | The path for the icon shown in the button | `media/images/my_icon.svg` | `media/images/ub_logo.svg` | + +## Contributing + +Contributions are welcome ! + +We expect the contributions to follow the [Decidim's contribution guide](https://github.com/decidim/decidim/blob/develop/CONTRIBUTING.adoc). + +## Security + +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. + +## License + +This engine is distributed under the GNU AFFERO GENERAL PUBLIC LICENSE. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..b92f8a2 --- /dev/null +++ b/Rakefile @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require "decidim/dev/common_rake" +require "fileutils" + +def install_initializer(path, env) + Dir.chdir(path) do + FileUtils.cp( + "#{__dir__}/lib/generators/app_templates/#{env}/initializer.rb", + "config/initializers/decidim_ub_config.rb" + ) + end +end + +def seed_db(path) + Dir.chdir(path) do + system("bundle exec rake db:seed") + end +end + +desc "Generates a dummy app for testing" +task test_app: "decidim:generate_external_test_app" do + ENV["RAILS_ENV"] = "test" + install_initializer("spec/decidim_dummy_app", "test") +end + +desc "Generates a development app." +task development_app: "decidim:generate_external_development_app" diff --git a/app/helpers/decidim/omniauth_helper_override.rb b/app/helpers/decidim/omniauth_helper_override.rb new file mode 100644 index 0000000..c04b09d --- /dev/null +++ b/app/helpers/decidim/omniauth_helper_override.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Decidim + module OmniauthHelperOverride + extend ActiveSupport::Concern + + included do + alias_method :original_normalize_provider_name, :normalize_provider_name + + def normalize_provider_name(provider) + return "Universitat de Barcelona" if provider == :ub + + original_normalize_provider_name(provider) + end + end + end +end diff --git a/app/packs/entrypoints/decidim_ub.js b/app/packs/entrypoints/decidim_ub.js new file mode 100644 index 0000000..a516e90 --- /dev/null +++ b/app/packs/entrypoints/decidim_ub.js @@ -0,0 +1,2 @@ +// Images +require.context("../images", true) diff --git a/app/packs/images/ub_logo.svg b/app/packs/images/ub_logo.svg new file mode 100644 index 0000000..8b5341f --- /dev/null +++ b/app/packs/images/ub_logo.svg @@ -0,0 +1,2401 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000..6475be0 --- /dev/null +++ b/bin/rails @@ -0,0 +1,7 @@ +#!/usr/bin/env ruby + +# frozen_string_literal: true + +Dir.chdir("development_app") + +load "bin/rails" diff --git a/config/assets.rb b/config/assets.rb new file mode 100644 index 0000000..fd0bf59 --- /dev/null +++ b/config/assets.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +base_path = File.expand_path("..", __dir__) + +Decidim::Webpacker.register_path("#{base_path}/app/packs") +Decidim::Webpacker.register_entrypoints( + decidim_ub: "#{base_path}/app/packs/entrypoints/decidim_ub.js" +) diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml new file mode 100644 index 0000000..d6086ae --- /dev/null +++ b/config/i18n-tasks.yml @@ -0,0 +1,4 @@ +--- + +base_locale: en +locales: [en] diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 index 0000000..1491caf --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,2 @@ +--- +en: diff --git a/decidim-ub.gemspec b/decidim-ub.gemspec new file mode 100644 index 0000000..64a6470 --- /dev/null +++ b/decidim-ub.gemspec @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +$LOAD_PATH.push File.expand_path("lib", __dir__) + +require "decidim/ub/version" + +Gem::Specification.new do |s| + s.version = Decidim::Ub::VERSION + s.authors = ["Francisco Bolívar"] + s.email = ["francisco.bolivar@nazaries.com"] + s.license = "AGPL-3.0" + s.homepage = "https://decidim.org" + s.metadata = { + "bug_tracker_uri" => "https://github.com/decidim/decidim/issues", + "documentation_uri" => "https://docs.decidim.org/", + "funding_uri" => "https://opencollective.com/decidim", + "homepage_uri" => "https://decidim.org", + "source_code_uri" => "https://github.com/decidim/decidim" + } + s.required_ruby_version = "~> 3.1" + + s.name = "decidim-ub" + s.summary = "A decidim ub module" + s.description = "A Decidim module to sync UB users who connect to the platform." + + s.files = Dir.chdir(__dir__) do + `git ls-files -z`.split("\x0").select do |f| + (File.expand_path(f) == __FILE__) || + f.start_with?(*%w(app/ config/ db/ lib/ LICENSE-AGPLv3.txt Rakefile README.md)) + end + end + + s.add_dependency "decidim-core", Decidim::Ub::COMPAT_DECIDIM_VERSION + + s.add_development_dependency "decidim-dev", Decidim::Ub::COMPAT_DECIDIM_VERSION +end diff --git a/lib/decidim/ub.rb b/lib/decidim/ub.rb new file mode 100644 index 0000000..435f767 --- /dev/null +++ b/lib/decidim/ub.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require "decidim/ub/engine" + +module Decidim + module Ub + include ActiveSupport::Configurable + + OMNIAUTH_PROVIDER_NAME = "ub" + + config_accessor :omniauth do + { + enabled: ENV["UB_CLIENT_ID"].present?, + icon_path: ENV.fetch("UB_ICON", "media/images/ub_logo.svg"), + client_id: ENV["UB_CLIENT_ID"].presence, + client_secret: ENV["UB_CLIENT_SECRET"].presence, + site: ENV["UB_SITE"].presence, + authorize_url: ENV["UB_AUTHORIZE_URL"].presence, + token_url: ENV["UB_TOKEN_URL"].presence + } + end + + class Error < StandardError; end + end +end diff --git a/lib/decidim/ub/engine.rb b/lib/decidim/ub/engine.rb new file mode 100644 index 0000000..ead2bce --- /dev/null +++ b/lib/decidim/ub/engine.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require "omniauth/strategies/ub" + +module Decidim + module Ub + # This is the engine that runs on the public interface of ub. + class Engine < ::Rails::Engine + isolate_namespace Decidim::Ub + + config.to_prepare do + Decidim::OmniauthHelper.include(Decidim::OmniauthHelperOverride) + end + + initializer "decidim_ub.omniauth" do + next unless Decidim::Ub.omniauth && Decidim::Ub.omniauth[:client_id] + + # Decidim use the secrets configuration to decide whether to show the omniauth provider + Rails.application.secrets[:omniauth][Decidim::Ub::OMNIAUTH_PROVIDER_NAME.to_sym] = Decidim::Ub.omniauth + + Rails.application.config.middleware.use OmniAuth::Builder do + provider Decidim::Ub::OMNIAUTH_PROVIDER_NAME, + client_id: Decidim::Ub.omniauth[:client_id], + client_secret: Decidim::Ub.omniauth[:client_secret], + client_options: { + site: Decidim::Ub.omniauth[:site], + authorize_url: Decidim::Ub.omniauth[:authorize_url], + token_url: Decidim::Ub.omniauth[:token_url] + } + end + end + + initializer "decidim_ub.webpacker.assets_path" do + Decidim.register_assets_path File.expand_path("app/packs", root) + end + end + end +end diff --git a/lib/decidim/ub/version.rb b/lib/decidim/ub/version.rb new file mode 100644 index 0000000..70be601 --- /dev/null +++ b/lib/decidim/ub/version.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Decidim + # This holds the decidim-meetings version. + module Ub + VERSION = "0.1.0" + DECIDIM_VERSION = "~> 0.28.0" + COMPAT_DECIDIM_VERSION = [">= 0.28.0", "< 0.29"].freeze + end +end diff --git a/lib/generators/decidim/app_templates/test/initializer.rb b/lib/generators/decidim/app_templates/test/initializer.rb new file mode 100644 index 0000000..3957faf --- /dev/null +++ b/lib/generators/decidim/app_templates/test/initializer.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +Decidim::Ub.configure do |config| + config.omniauth = { + client_id: "test-client-id", + client_secret: "test-client-secret", + site: "https://test.example.org", + authorize_url: "/authorize", + token_url: "/token" + } +end diff --git a/lib/omniauth/strategies/ub.rb b/lib/omniauth/strategies/ub.rb new file mode 100644 index 0000000..ca3ef54 --- /dev/null +++ b/lib/omniauth/strategies/ub.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require "omniauth-oauth2" + +module OmniAuth + module Strategies + class Ub < OmniAuth::Strategies::OAuth2 + option :name, "ub" + option :token_options, %w(client_id client_secret) + + uid do + token_info["uid"] + end + + info do + { + name: token_info["cn"], + nickname: token_info["dni"], + email: token_info["mail"] + } + end + + def callback_url + full_host + callback_path + end + + def token_info + @token_info ||= begin + connection = Faraday.new(url: options.client_options[:site], ssl: { verify: true }) do |conn| + conn.headers["Authorization"] = "#{access_token.response.parsed.token_type} #{access_token.token}" + end + response = connection.get("/api/adas/oauth2/tokendata") + raise Error, "Unable to fetch the user information" unless response.success? + + JSON.parse(response.body).to_h + end + end + end + end +end diff --git a/lib/omniauth/ub.rb b/lib/omniauth/ub.rb new file mode 100644 index 0000000..10e740c --- /dev/null +++ b/lib/omniauth/ub.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require "omniauth/strategies/ub" diff --git a/spec/factories.rb b/spec/factories.rb new file mode 100644 index 0000000..8e9b8f9 --- /dev/null +++ b/spec/factories.rb @@ -0,0 +1 @@ +# frozen_string_literal: true diff --git a/spec/lib/decidim/ub/version_spec.rb b/spec/lib/decidim/ub/version_spec.rb new file mode 100644 index 0000000..83d4c05 --- /dev/null +++ b/spec/lib/decidim/ub/version_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + describe Ub do + subject { described_class } + + it "has version" do + expect(subject::VERSION).to eq("0.1.0") + end + + it "has decidim version" do + expect(subject::DECIDIM_VERSION).to eq("~> 0.28.0") + end + + it "has compatible decidim version" do + expect(subject::COMPAT_DECIDIM_VERSION).to eq([">= 0.28.0", "< 0.29"]) + end + end +end diff --git a/spec/lib/overrides_spec.rb b/spec/lib/overrides_spec.rb new file mode 100644 index 0000000..021a5c4 --- /dev/null +++ b/spec/lib/overrides_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require "spec_helper" + +# We make sure that the checksum of the file overridden is the same +# as the expected. If this test fails, it means that the overridden +# file should be updated to match any change/bug fix introduced in the core +checksums = [ + { + package: "decidim-core", + files: { + # Show "Universitat de Barcelona" in the OAuth button + "/app/helpers/decidim/omniauth_helper.rb" => "5c310ce2f67a173e802c8cb5c0918f31" + } + } +] + +describe "Overridden files", type: :view do + checksums.each do |item| + spec = Gem::Specification.find_by_name(item[:package]) + next unless spec + + item[:files].each do |file, signature| + it "#{spec.gem_dir}#{file} matches checksum" do + expect(md5("#{spec.gem_dir}#{file}")).to eq(signature) + end + end + end + + private + + def md5(file) + Digest::MD5.hexdigest(File.read(file)) + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..a30b234 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require "decidim/dev" + +ENV["ENGINE_ROOT"] = File.dirname(__dir__) + +Decidim::Dev.dummy_app_path = File.expand_path(File.join("spec", "decidim_dummy_app")) + +require "decidim/dev/test/base_spec_helper" From b2f5404fb389887ec2c549034bd9f201e8823169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Thu, 4 Jul 2024 13:02:32 +0200 Subject: [PATCH 02/13] Properly fetch user attributes from the retrieved info --- lib/omniauth/strategies/ub.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/omniauth/strategies/ub.rb b/lib/omniauth/strategies/ub.rb index ca3ef54..02c940d 100644 --- a/lib/omniauth/strategies/ub.rb +++ b/lib/omniauth/strategies/ub.rb @@ -5,18 +5,20 @@ module OmniAuth module Strategies class Ub < OmniAuth::Strategies::OAuth2 + REGEXP_SANITIZER = /[<>?%&^*#@()\[\]=+:;"{}\\|]/ + option :name, "ub" option :token_options, %w(client_id client_secret) uid do - token_info["uid"] + raw_info.dig("employeenumber", 0) end info do { - name: token_info["cn"], - nickname: token_info["dni"], - email: token_info["mail"] + name: raw_info.dig("cn", 0).gsub(REGEXP_SANITIZER, ""), + nickname: Decidim::UserBaseEntity.nicknamize(raw_info.dig("uidnet", 0)), + email: raw_info.dig("mail", 0) } end @@ -24,8 +26,8 @@ def callback_url full_host + callback_path end - def token_info - @token_info ||= begin + def raw_info + @raw_info ||= begin connection = Faraday.new(url: options.client_options[:site], ssl: { verify: true }) do |conn| conn.headers["Authorization"] = "#{access_token.response.parsed.token_type} #{access_token.token}" end From 4736fcd1a2c17be9e597fb19cd6bfd3185e374c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Tue, 9 Jul 2024 18:01:01 +0200 Subject: [PATCH 03/13] Auto verification for users --- .rubocop.yml | 24 ++++++++ .rubocop_todo.yml | 26 --------- Rakefile | 12 +++- app/commands/decidim/ub/sync_user.rb | 39 +++++++++++++ .../decidim/devise_authentication_methods.rb | 11 ++++ app/forms/decidim/ub/verifications/ub.rb | 33 +++++++++++ app/forms/decidim/ub/verifications/ub_ant.rb | 11 ++++ app/forms/decidim/ub/verifications/ub_est.rb | 11 ++++ app/forms/decidim/ub/verifications/ub_pas.rb | 11 ++++ app/forms/decidim/ub/verifications/ub_pdi.rb | 11 ++++ app/forms/decidim/ub/verifications/ub_pex.rb | 11 ++++ .../decidim/omniauth_helper_override.rb | 17 ------ .../decidim/ub/omniauth_helper_override.rb | 19 +++++++ app/jobs/decidim/ub/auto_verification_job.rb | 55 +++++++++++++++++++ app/jobs/decidim/ub/omniauth_user_sync_job.rb | 24 ++++++++ .../concerns/decidim/ub/user_override.rb | 19 +++++++ config/i18n-tasks.yml | 5 +- config/locales/ca.yml | 31 +++++++++++ config/locales/en.yml | 29 ++++++++++ config/locales/es.yml | 31 +++++++++++ .../20240709154301_add_ub_roles_to_users.rb | 7 +++ lib/decidim/ub.rb | 11 ++++ lib/decidim/ub/engine.rb | 21 ++++++- lib/omniauth/strategies/ub.rb | 3 +- spec/lib/overrides_spec.rb | 6 +- 25 files changed, 430 insertions(+), 48 deletions(-) create mode 100644 app/commands/decidim/ub/sync_user.rb create mode 100644 app/controllers/concerns/decidim/devise_authentication_methods.rb create mode 100644 app/forms/decidim/ub/verifications/ub.rb create mode 100644 app/forms/decidim/ub/verifications/ub_ant.rb create mode 100644 app/forms/decidim/ub/verifications/ub_est.rb create mode 100644 app/forms/decidim/ub/verifications/ub_pas.rb create mode 100644 app/forms/decidim/ub/verifications/ub_pdi.rb create mode 100644 app/forms/decidim/ub/verifications/ub_pex.rb delete mode 100644 app/helpers/decidim/omniauth_helper_override.rb create mode 100644 app/helpers/decidim/ub/omniauth_helper_override.rb create mode 100644 app/jobs/decidim/ub/auto_verification_job.rb create mode 100644 app/jobs/decidim/ub/omniauth_user_sync_job.rb create mode 100644 app/models/concerns/decidim/ub/user_override.rb create mode 100644 config/locales/ca.yml create mode 100644 config/locales/es.yml create mode 100644 db/migrate/20240709154301_add_ub_roles_to_users.rb diff --git a/.rubocop.yml b/.rubocop.yml index 928b486..c80dd73 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,2 +1,26 @@ +inherit_from: .rubocop_todo.yml + inherit_gem: decidim-dev: rubocop-decidim.yml + +inherit_mode: + merge: + - Exclude + +AllCops: + Include: + - "**/*.rb" + - "**/*.rake" + - "**/*.ru" + - "**/Gemfile" + - "**/Rakefile" + Exclude: + - "spec/decidim_dummy_app/**/*" + - "**/spec/decidim_dummy_app/**/*" + - "bin/**/*" + - "node_modules/**/*" + - "**/node_modules/**/*" + - "db/schema.rb" + - "db/migrate/*" + - "vendor/**/*" + - "**/vendor/**/*" diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index c80dd73..e69de29 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,26 +0,0 @@ -inherit_from: .rubocop_todo.yml - -inherit_gem: - decidim-dev: rubocop-decidim.yml - -inherit_mode: - merge: - - Exclude - -AllCops: - Include: - - "**/*.rb" - - "**/*.rake" - - "**/*.ru" - - "**/Gemfile" - - "**/Rakefile" - Exclude: - - "spec/decidim_dummy_app/**/*" - - "**/spec/decidim_dummy_app/**/*" - - "bin/**/*" - - "node_modules/**/*" - - "**/node_modules/**/*" - - "db/schema.rb" - - "db/migrate/*" - - "vendor/**/*" - - "**/vendor/**/*" diff --git a/Rakefile b/Rakefile index b92f8a2..743f4c3 100644 --- a/Rakefile +++ b/Rakefile @@ -3,6 +3,13 @@ require "decidim/dev/common_rake" require "fileutils" +def install_module(path) + Dir.chdir(path) do + system("bundle exec rake decidim_ub:install:migrations") + system("bundle exec rake db:migrate") + end +end + def install_initializer(path, env) Dir.chdir(path) do FileUtils.cp( @@ -22,7 +29,10 @@ desc "Generates a dummy app for testing" task test_app: "decidim:generate_external_test_app" do ENV["RAILS_ENV"] = "test" install_initializer("spec/decidim_dummy_app", "test") + install_module("spec/decidim_dummy_app") end desc "Generates a development app." -task development_app: "decidim:generate_external_development_app" +task development_app: "decidim:generate_external_development_app" do + install_module("development_app") +end diff --git a/app/commands/decidim/ub/sync_user.rb b/app/commands/decidim/ub/sync_user.rb new file mode 100644 index 0000000..33e5ca6 --- /dev/null +++ b/app/commands/decidim/ub/sync_user.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Decidim + module Ub + class SyncUser < Decidim::Command + # Public: Initializes the command. + # + # user - A decidim user + # roles - The roles of the user + def initialize(user, roles) + @user = user + @roles = roles + end + + # Executes the command. Broadcasts these events: + # + # - :ok when everything is valid. + # - :invalid if we couldn't proceed. + # + # Returns nothing. + def call + update_user! + ActiveSupport::Notifications.publish("decidim.ub.user.updated", user.id) + broadcast(:ok) + rescue StandardError => e + broadcast(:invalid, e.message) + end + + private + + attr_reader :user, :roles + + def update_user! + user.ub_roles = roles + user.save! + end + end + end +end diff --git a/app/controllers/concerns/decidim/devise_authentication_methods.rb b/app/controllers/concerns/decidim/devise_authentication_methods.rb new file mode 100644 index 0000000..9550009 --- /dev/null +++ b/app/controllers/concerns/decidim/devise_authentication_methods.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Decidim + module DeviseAuthenticationMethods + def first_login_and_not_authorized?(user) + return false if user.ub_identity? + + super + end + end +end diff --git a/app/forms/decidim/ub/verifications/ub.rb b/app/forms/decidim/ub/verifications/ub.rb new file mode 100644 index 0000000..eefd847 --- /dev/null +++ b/app/forms/decidim/ub/verifications/ub.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require "digest" + +module Decidim + module Ub + module Verifications + class Ub < Decidim::AuthorizationHandler + validate :user_valid + + def unique_id + Digest::SHA512.hexdigest("#{role}/#{uid}-#{Rails.application.secrets.secret_key_base}") + end + + protected + + def organization + current_organization || user&.organization + end + + def uid + user.ub_identity + end + + def user_valid + errors.add(:user, "decidim.ub.errors.missing_role") unless user.ub_roles.include?(role) + end + + def role = raise NotImplementedError + end + end + end +end diff --git a/app/forms/decidim/ub/verifications/ub_ant.rb b/app/forms/decidim/ub/verifications/ub_ant.rb new file mode 100644 index 0000000..6665fb5 --- /dev/null +++ b/app/forms/decidim/ub/verifications/ub_ant.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Decidim + module Ub + module Verifications + class UbAnt < Ub + def role = "ANT" + end + end + end +end diff --git a/app/forms/decidim/ub/verifications/ub_est.rb b/app/forms/decidim/ub/verifications/ub_est.rb new file mode 100644 index 0000000..e165f42 --- /dev/null +++ b/app/forms/decidim/ub/verifications/ub_est.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Decidim + module Ub + module Verifications + class UbEst < Ub + def role = "EST" + end + end + end +end diff --git a/app/forms/decidim/ub/verifications/ub_pas.rb b/app/forms/decidim/ub/verifications/ub_pas.rb new file mode 100644 index 0000000..5dadef2 --- /dev/null +++ b/app/forms/decidim/ub/verifications/ub_pas.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Decidim + module Ub + module Verifications + class UbPas < Ub + def role = "PAS" + end + end + end +end diff --git a/app/forms/decidim/ub/verifications/ub_pdi.rb b/app/forms/decidim/ub/verifications/ub_pdi.rb new file mode 100644 index 0000000..eb75a26 --- /dev/null +++ b/app/forms/decidim/ub/verifications/ub_pdi.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Decidim + module Ub + module Verifications + class UbPdi < Ub + def role = "PDI" + end + end + end +end diff --git a/app/forms/decidim/ub/verifications/ub_pex.rb b/app/forms/decidim/ub/verifications/ub_pex.rb new file mode 100644 index 0000000..9ed7d13 --- /dev/null +++ b/app/forms/decidim/ub/verifications/ub_pex.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Decidim + module Ub + module Verifications + class UbPex < Ub + def role = "PEX" + end + end + end +end diff --git a/app/helpers/decidim/omniauth_helper_override.rb b/app/helpers/decidim/omniauth_helper_override.rb deleted file mode 100644 index c04b09d..0000000 --- a/app/helpers/decidim/omniauth_helper_override.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -module Decidim - module OmniauthHelperOverride - extend ActiveSupport::Concern - - included do - alias_method :original_normalize_provider_name, :normalize_provider_name - - def normalize_provider_name(provider) - return "Universitat de Barcelona" if provider == :ub - - original_normalize_provider_name(provider) - end - end - end -end diff --git a/app/helpers/decidim/ub/omniauth_helper_override.rb b/app/helpers/decidim/ub/omniauth_helper_override.rb new file mode 100644 index 0000000..3ddf805 --- /dev/null +++ b/app/helpers/decidim/ub/omniauth_helper_override.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Decidim + module Ub + module OmniauthHelperOverride + extend ActiveSupport::Concern + + included do + alias_method :original_normalize_provider_name, :normalize_provider_name + + def normalize_provider_name(provider) + return "Universitat de Barcelona" if provider == :ub + + original_normalize_provider_name(provider) + end + end + end + end +end diff --git a/app/jobs/decidim/ub/auto_verification_job.rb b/app/jobs/decidim/ub/auto_verification_job.rb new file mode 100644 index 0000000..9ec0cdd --- /dev/null +++ b/app/jobs/decidim/ub/auto_verification_job.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +module Decidim + module Ub + class AutoVerificationJob < ApplicationJob + queue_as :default + + def perform(user_id) + @user = Decidim::User.find(user_id) + @auths = Decidim::Ub.roles_to_auth_name(@user.ub_roles & Decidim::Ub::ROLES) + update_auths + rescue ActiveRecord::RecordNotFound + Rails.logger.error "AutoVerificationJob: ERROR: model not found for user #{user_id}" + end + + private + + def update_auths + current_auths = user_auths.pluck(:name) + (current_auths - @auths).each { |name| remove_auth(user_auths.find_by(name:)) } + (@auths - current_auths).each { |name| create_auth(name) } + end + + def create_auth(name) + return unless (handler = Decidim::AuthorizationHandler.handler_for(name, user: @user)) + + Decidim::Verifications::AuthorizeUser.call(handler, @user.organization) do + on(:ok) do + Rails.logger.info "AutoVerificationJob: Success: created auth #{name} for user #{handler.user.id}" + end + + on(:invalid) do + Rails.logger.error "AutoVerificationJob: ERROR: not created auth #{name} for user #{handler.user&.id}" + end + end + end + + def remove_auth(auth) + Decidim::Verifications::DestroyUserAuthorization.call(auth) do + on(:ok) do + Rails.logger.info "AutoVerificationJob: Success: removed auth #{auth.name} for user #{auth.user.id}" + end + + on(:invalid) do + Rails.logger.error "AutoVerificationJob: ERROR: not removed auth #{auth.name} for user #{auth.user&.id}" + end + end + end + + def user_auths + @user_auths ||= Decidim::Authorization.where(user: @user, name: Decidim::Ub.authorizations) + end + end + end +end diff --git a/app/jobs/decidim/ub/omniauth_user_sync_job.rb b/app/jobs/decidim/ub/omniauth_user_sync_job.rb new file mode 100644 index 0000000..3ad786e --- /dev/null +++ b/app/jobs/decidim/ub/omniauth_user_sync_job.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Decidim + module Ub + class OmniauthUserSyncJob < ApplicationJob + queue_as :default + + def perform(data) + user = Decidim::User.find(data[:user_id]) + return unless user.ub_identity? + + Decidim::Ub::SyncUser.call(user, data.dig(:raw_data, :info, :roles)) do + on(:ok) do + Rails.logger.info "OmniauthUserSyncJob: Success: Ub roles updated for user #{user.id}" + end + + on(:invalid) do |message| + Rails.logger.error "OmniauthUserSyncJob: ERROR: Error updating ub roles '#{message}'" + end + end + end + end + end +end diff --git a/app/models/concerns/decidim/ub/user_override.rb b/app/models/concerns/decidim/ub/user_override.rb new file mode 100644 index 0000000..1ec653c --- /dev/null +++ b/app/models/concerns/decidim/ub/user_override.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Decidim + module Ub + module UserOverride + extend ActiveSupport::Concern + + included do + def ub_identity + identities.find_by(provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME) + end + + def ub_identity? + identities.exists?(provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME) + end + end + end + end +end diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index d6086ae..e8d0111 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -1,4 +1,7 @@ --- base_locale: en -locales: [en] +locales: + - ca + - en + - es diff --git a/config/locales/ca.yml b/config/locales/ca.yml new file mode 100644 index 0000000..344e745 --- /dev/null +++ b/config/locales/ca.yml @@ -0,0 +1,31 @@ +--- +ca: + decidim: + authorization_handlers: + ub_ant: + explanation: Verifica't com a antic alumne + name: Antic alumne (ANT) + ub_est: + explanation: Verifica't com a alumne + name: Alumne (EST) + ub_pas: + explanation: Verifica't com a personal administratiu/servicis + name: Personal administratiu/servicis (PTGAS) + ub_pdi: + explanation: Verifica't com a professor + name: Professor (PDI) + ub_pex: + explanation: Verifica't com a personal extern + name: Personal extern (PEX) + ub: + errors: + missing_role: No tens aquest rol + verifications: + authorizations: + first_login: + actions: + ub_ant: Verifica't com a antic almumne (ANT) + ub_est: Verifica't com a alumne (EST) + ub_pas: Verifica't com a personal administració/serveis (PTGAS) + ub_pdi: Verifica't com a professor (PDI) + ub_pex: Verifica't com a personal extern (PEX) diff --git a/config/locales/en.yml b/config/locales/en.yml index 1491caf..1fe189f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,2 +1,31 @@ --- en: + decidim: + authorization_handlers: + ub_ant: + explanation: Get verified as an old student + name: Old student (ANT) + ub_est: + explanation: Get verified as a student + name: Student (EST) + ub_pas: + explanation: Get verified as an administrative/services personal + name: Administrative/services personal (PTGAS) + ub_pdi: + explanation: Get verified as a teacher + name: Teacher (PDI) + ub_pex: + explanation: Get verified as an external personal + name: External personal (PEX) + ub: + errors: + missing_role: You don't have this role + verifications: + authorizations: + first_login: + actions: + ub_ant: Verify you are an old student (ANT) + ub_est: Verify you are a student (EST) + ub_pas: Verify you are an administrative/services personal (PTGAS) + ub_pdi: Verify you are a teacher (PDI) + ub_pex: Verify you are an external personal (PEX) diff --git a/config/locales/es.yml b/config/locales/es.yml new file mode 100644 index 0000000..c5f4956 --- /dev/null +++ b/config/locales/es.yml @@ -0,0 +1,31 @@ +--- +es: + decidim: + authorization_handlers: + ub_ant: + explanation: Verifícate como antiguo estudiante + name: Antiguo estudiante (ANT) + ub_est: + explanation: Verifícate como estudiante + name: Estudiante (EST) + ub_pas: + explanation: Verifícate como personal administrativo/servicios + name: Personal administrativo/servicios (PTGAS) + ub_pdi: + explanation: Verifícate como profesor + name: Profesor (PDI) + ub_pex: + explanation: Verifícate como personal externo + name: Personal externo (PEX) + ub: + errors: + missing_role: No tienes este rol + verifications: + authorizations: + first_login: + actions: + ub_ant: Verifícate como antiguo estudiante (ANT) + ub_est: Verifícate como estudiante (EST) + ub_pas: Verifícate como personal administrativo/servicios (PTGAS) + ub_pdi: Verifícate como profesor (PDI) + ub_pex: Verifícate como personal externo (PEX) diff --git a/db/migrate/20240709154301_add_ub_roles_to_users.rb b/db/migrate/20240709154301_add_ub_roles_to_users.rb new file mode 100644 index 0000000..8c7bf8b --- /dev/null +++ b/db/migrate/20240709154301_add_ub_roles_to_users.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddUbRolesToUsers < ActiveRecord::Migration[6.0] + def change + add_column :decidim_users, :ub_roles, :jsonb, default: [] + end +end diff --git a/lib/decidim/ub.rb b/lib/decidim/ub.rb index 435f767..89628a4 100644 --- a/lib/decidim/ub.rb +++ b/lib/decidim/ub.rb @@ -7,6 +7,13 @@ module Ub include ActiveSupport::Configurable OMNIAUTH_PROVIDER_NAME = "ub" + ROLES = %w(EST PAS PDI PEX ANT).freeze + + class << self + def roles_to_auth_name(roles) + roles.map { |role| "ub_#{role.downcase}" } + end + end config_accessor :omniauth do { @@ -20,6 +27,10 @@ module Ub } end + config_accessor :authorizations do + roles_to_auth_name(ROLES).freeze + end + class Error < StandardError; end end end diff --git a/lib/decidim/ub/engine.rb b/lib/decidim/ub/engine.rb index ead2bce..e92c7dc 100644 --- a/lib/decidim/ub/engine.rb +++ b/lib/decidim/ub/engine.rb @@ -9,7 +9,8 @@ class Engine < ::Rails::Engine isolate_namespace Decidim::Ub config.to_prepare do - Decidim::OmniauthHelper.include(Decidim::OmniauthHelperOverride) + Decidim::OmniauthHelper.include(Decidim::Ub::OmniauthHelperOverride) + Decidim::User.include(Decidim::Ub::UserOverride) end initializer "decidim_ub.omniauth" do @@ -33,6 +34,24 @@ class Engine < ::Rails::Engine initializer "decidim_ub.webpacker.assets_path" do Decidim.register_assets_path File.expand_path("app/packs", root) end + + initializer "decidim_ub.authorizations" do + Decidim::Ub.authorizations.each do |name| + Decidim::Verifications.register_workflow(name.to_sym) do |workflow| + workflow.form = "Decidim::Ub::Verifications::#{name.camelize}" + end + end + end + + initializer "decidim_ub.user_sync" do + ActiveSupport::Notifications.subscribe "decidim.user.omniauth_registration" do |_name, data| + Decidim::Ub::OmniauthUserSyncJob.perform_later(data) if data[:provider] == Decidim::Ub::OMNIAUTH_PROVIDER_NAME + end + + ActiveSupport::Notifications.subscribe "decidim.ub.user.updated" do |_name, data| + Decidim::Ub::AutoVerificationJob.perform_later(data) + end + end end end end diff --git a/lib/omniauth/strategies/ub.rb b/lib/omniauth/strategies/ub.rb index 02c940d..f6a510a 100644 --- a/lib/omniauth/strategies/ub.rb +++ b/lib/omniauth/strategies/ub.rb @@ -18,7 +18,8 @@ class Ub < OmniAuth::Strategies::OAuth2 { name: raw_info.dig("cn", 0).gsub(REGEXP_SANITIZER, ""), nickname: Decidim::UserBaseEntity.nicknamize(raw_info.dig("uidnet", 0)), - email: raw_info.dig("mail", 0) + email: raw_info.dig("mail", 0), + roles: raw_info["colect2"] || [] } end diff --git a/spec/lib/overrides_spec.rb b/spec/lib/overrides_spec.rb index 021a5c4..ff5618f 100644 --- a/spec/lib/overrides_spec.rb +++ b/spec/lib/overrides_spec.rb @@ -9,8 +9,12 @@ { package: "decidim-core", files: { + # Do not show first_login page if the user has registered with the UB OAuth method + "/app/controllers/concerns/decidim/devise_authentication_methods.rb" => "9d4bd40211243cca819e83bb2344972c", # Show "Universitat de Barcelona" in the OAuth button - "/app/helpers/decidim/omniauth_helper.rb" => "5c310ce2f67a173e802c8cb5c0918f31" + "/app/helpers/decidim/omniauth_helper.rb" => "5c310ce2f67a173e802c8cb5c0918f31", + # Add methods to work with UB identities + "/app/models/decidim/user.rb" => "81da9f2f82f6336a92b948d827bd0fb3" } } ] From 31852dc10b88aa531e6e8e348969ef6db283a162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Wed, 10 Jul 2024 09:57:41 +0200 Subject: [PATCH 04/13] Add coverage to CI --- .github/workflows/lint.yml | 2 +- .github/workflows/test.yml | 17 ++++++++++++++--- .simplecov | 2 ++ Gemfile | 4 ++++ Gemfile.lock | 33 ++++++++++++++++++++++----------- Rakefile | 2 +- spec/spec_helper.rb | 6 ++++++ 7 files changed, 50 insertions(+), 16 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d486011..182d596 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,7 +20,7 @@ concurrency: jobs: main: - name: Tests + name: Lint runs-on: ubuntu-latest timeout-minutes: 30 services: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a69ae39..899d81b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,13 +20,25 @@ concurrency: jobs: main: - name: Lint + name: Tests runs-on: ubuntu-latest timeout-minutes: 30 + services: + postgres: + image: postgres:11 + ports: ["5432:5432"] + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + env: + POSTGRES_PASSWORD: postgres env: DATABASE_USERNAME: postgres DATABASE_PASSWORD: postgres DATABASE_HOST: localhost + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} steps: - uses: actions/checkout@v3 with: @@ -56,9 +68,8 @@ jobs: - run: RAILS_ENV=test bundle exec rails assets:precompile name: Precompile assets working-directory: ./spec/decidim_dummy_app/ - - run: bundle exec rspec + - run: CI=1 bundle exec rspec name: RSpec - - uses: codecov/codecov-action@v3 - uses: actions/upload-artifact@v3 if: always() with: diff --git a/.simplecov b/.simplecov index 9de065b..2f0aec0 100644 --- a/.simplecov +++ b/.simplecov @@ -3,6 +3,8 @@ SimpleCov.start do root ENV.fetch("ENGINE_ROOT", nil) + track_files "{app,lib}/**/*.rb" + add_filter "lib/generators" add_filter "/spec" end diff --git a/Gemfile b/Gemfile index d10e83c..60f0390 100644 --- a/Gemfile +++ b/Gemfile @@ -29,3 +29,7 @@ group :development do gem "spring-watcher-listen", "~> 2.0" gem "web-console", "~> 4.2" end + +group :test do + gem "coveralls_reborn", require: false +end diff --git a/Gemfile.lock b/Gemfile.lock index 04031cd..ce1cce5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -129,6 +129,11 @@ GEM childprocess (5.0.0) commonmarker (0.23.10) concurrent-ruby (1.3.3) + coveralls_reborn (0.28.0) + simplecov (~> 0.22.0) + term-ansicolor (~> 1.7) + thor (~> 1.2) + tins (~> 1.32) crack (1.0.0) bigdecimal rexml @@ -356,17 +361,7 @@ GEM faraday-net_http (>= 2.0, < 3.2) faraday-net_http (3.1.0) net-http - ffi (1.17.0) - ffi (1.17.0-aarch64-linux-gnu) - ffi (1.17.0-aarch64-linux-musl) - ffi (1.17.0-arm-linux-gnu) - ffi (1.17.0-arm-linux-musl) - ffi (1.17.0-arm64-darwin) - ffi (1.17.0-x86-linux-gnu) - ffi (1.17.0-x86-linux-musl) - ffi (1.17.0-x86_64-darwin) - ffi (1.17.0-x86_64-linux-gnu) - ffi (1.17.0-x86_64-linux-musl) + ffi (1.16.3) file_validators (3.0.0) activemodel (>= 3.2) mime-types (>= 1.0) @@ -488,6 +483,8 @@ GEM tomlrb mixlib-shellout (3.2.8) chef-utils + mize (0.4.1) + protocol (~> 2.0) msgpack (1.7.2) multi_xml (0.6.0) net-http (0.4.1) @@ -576,6 +573,8 @@ GEM actionmailer (>= 3) net-smtp premailer (~> 1.7, >= 1.7.9) + protocol (2.0.0) + ruby_parser (~> 3.0) psych (4.0.6) stringio public_suffix (6.0.0) @@ -718,6 +717,9 @@ GEM rubyXL (3.4.27) nokogiri (>= 1.10.8) rubyzip (>= 1.3.0) + ruby_parser (3.21.1) + racc (~> 1.5) + sexp_processor (~> 4.16) rubyzip (2.3.2) sass (3.7.4) sass-listen (~> 4.0.0) @@ -732,6 +734,7 @@ GEM websocket (~> 1.0) semantic_range (3.0.0) seven_zip_ruby (1.3.0) + sexp_processor (4.17.2) shakapacker (7.1.0) activesupport (>= 5.2) rack-proxy (>= 0.6.1) @@ -764,12 +767,19 @@ GEM ssrf_filter (1.1.2) stringio (3.1.1) strscan (3.1.0) + sync (0.5.0) temple (0.10.3) + term-ansicolor (1.10.2) + mize + tins (~> 1.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) thor (1.3.1) tilt (2.3.0) timeout (0.4.1) + tins (1.33.0) + bigdecimal + sync tomlrb (2.0.3) tzinfo (2.0.6) concurrent-ruby (~> 1.0) @@ -836,6 +846,7 @@ PLATFORMS DEPENDENCIES bootsnap (~> 1.4) byebug (~> 11.0) + coveralls_reborn decidim (~> 0.28.0) decidim-dev (~> 0.28.0) decidim-ub! diff --git a/Rakefile b/Rakefile index 743f4c3..d349b13 100644 --- a/Rakefile +++ b/Rakefile @@ -13,7 +13,7 @@ end def install_initializer(path, env) Dir.chdir(path) do FileUtils.cp( - "#{__dir__}/lib/generators/app_templates/#{env}/initializer.rb", + "#{__dir__}/lib/generators/decidim/app_templates/#{env}/initializer.rb", "config/initializers/decidim_ub_config.rb" ) end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a30b234..e67ff19 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,6 +1,12 @@ # frozen_string_literal: true require "decidim/dev" +require "simplecov" + +if ENV["CI"] + require "coveralls" + SimpleCov.formatter = Coveralls::SimpleCov::Formatter +end ENV["ENGINE_ROOT"] = File.dirname(__dir__) From a798c0c332967d1336e7f6bfcba468025319ced9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Wed, 10 Jul 2024 10:29:49 +0200 Subject: [PATCH 05/13] Add badges to README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index fd30cd6..210f640 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # Decidim::Ub +[![[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) +[![[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) +[![Maintainability](https://api.codeclimate.com/v1/badges/c975a347c58389448503/maintainability)](https://codeclimate.com/github/Platoniq/decidim-module-ub/maintainability) +[![Coverage Status](https://coveralls.io/repos/github/Platoniq/decidim-module-ub/badge.svg?branch=HEAD)](https://coveralls.io/github/Platoniq/decidim-module-ub?branch=HEAD) + A Decidim module to sync users from Universitat de Barcelona who connect to the platform. ## Installation From f38401fb84eb01935ee3eb0325a378f9917b3961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Wed, 10 Jul 2024 17:01:53 +0200 Subject: [PATCH 06/13] Add tests for commands, forms, models, jobs and OmniAuth button --- .simplecov | 1 + app/commands/decidim/ub/sync_user.rb | 2 + lib/decidim/ub/test/factories.rb | 3 + spec/commands/decidim/ub/sync_user_spec.rb | 63 ++++++++++ spec/factories.rb | 2 + .../decidim/ub/verifications/ub_ant_spec.rb | 44 +++++++ .../decidim/ub/verifications/ub_est_spec.rb | 44 +++++++ .../decidim/ub/verifications/ub_pas_spec.rb | 44 +++++++ .../decidim/ub/verifications/ub_pdi_spec.rb | 44 +++++++ .../decidim/ub/verifications/ub_pex_spec.rb | 44 +++++++ .../decidim/ub/auto_verification_job_spec.rb | 112 ++++++++++++++++++ .../decidim/ub/omniauth_user_sync_job_spec.rb | 67 +++++++++++ spec/lib/decidim/ub/version_spec.rb | 21 ---- spec/models/decidim/user_spec.rb | 50 ++++++++ spec/system/omniauth_button_spec.rb | 47 ++++++++ 15 files changed, 567 insertions(+), 21 deletions(-) create mode 100644 lib/decidim/ub/test/factories.rb create mode 100644 spec/commands/decidim/ub/sync_user_spec.rb create mode 100644 spec/forms/decidim/ub/verifications/ub_ant_spec.rb create mode 100644 spec/forms/decidim/ub/verifications/ub_est_spec.rb create mode 100644 spec/forms/decidim/ub/verifications/ub_pas_spec.rb create mode 100644 spec/forms/decidim/ub/verifications/ub_pdi_spec.rb create mode 100644 spec/forms/decidim/ub/verifications/ub_pex_spec.rb create mode 100644 spec/jobs/decidim/ub/auto_verification_job_spec.rb create mode 100644 spec/jobs/decidim/ub/omniauth_user_sync_job_spec.rb delete mode 100644 spec/lib/decidim/ub/version_spec.rb create mode 100644 spec/models/decidim/user_spec.rb create mode 100644 spec/system/omniauth_button_spec.rb diff --git a/.simplecov b/.simplecov index 2f0aec0..372b358 100644 --- a/.simplecov +++ b/.simplecov @@ -6,6 +6,7 @@ SimpleCov.start do track_files "{app,lib}/**/*.rb" add_filter "lib/generators" + add_filter "lib/decidim/ub/version.rb" add_filter "/spec" end diff --git a/app/commands/decidim/ub/sync_user.rb b/app/commands/decidim/ub/sync_user.rb index 33e5ca6..39433e6 100644 --- a/app/commands/decidim/ub/sync_user.rb +++ b/app/commands/decidim/ub/sync_user.rb @@ -31,6 +31,8 @@ def call attr_reader :user, :roles def update_user! + return unless user.ub_identity? + user.ub_roles = roles user.save! end diff --git a/lib/decidim/ub/test/factories.rb b/lib/decidim/ub/test/factories.rb new file mode 100644 index 0000000..0e6d87b --- /dev/null +++ b/lib/decidim/ub/test/factories.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require "decidim/core/test/factories" diff --git a/spec/commands/decidim/ub/sync_user_spec.rb b/spec/commands/decidim/ub/sync_user_spec.rb new file mode 100644 index 0000000..46a38ef --- /dev/null +++ b/spec/commands/decidim/ub/sync_user_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + module Ub + describe SyncUser do + subject { described_class.new(user, roles) } + + let(:user) { create(:user) } + let!(:identity) { create(:identity, user:, provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME) } + let(:roles) { %w(PAS PDI) } + + context "when everything is ok" do + it "broadcasts ok" do + expect { subject.call }.to broadcast(:ok) + end + + it "updates the roles" do + expect { subject.call }.to change(user, :ub_roles).from([]).to(roles) + end + + context "when user already has roles" do + let(:old_roles) { %w(EST) } + let!(:user) { create(:user, ub_roles: old_roles) } + + it "updates the roles" do + sleep(1) + expect { subject.call }.to change(user, :ub_roles).from(old_roles).to(roles) + end + end + end + + context "when user has no ub identity" do + before do + allow(user).to receive(:ub_identity?).and_return(false) + end + + it "broadcasts ok" do + expect { subject.call }.to broadcast(:ok) + end + + it "does not update the roles" do + expect { subject.call }.not_to change(user, :ub_roles) + end + end + + context "when an exception is raised" do + before do + allow(user).to receive(:ub_identity?).and_raise(StandardError) + end + + it "broadcasts invalid" do + expect { subject.call }.to broadcast(:invalid) + end + + it "does not update the roles" do + expect { subject.call }.not_to change(user, :ub_roles) + end + end + end + end +end diff --git a/spec/factories.rb b/spec/factories.rb index 8e9b8f9..f3386a5 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -1 +1,3 @@ # frozen_string_literal: true + +require "decidim/ub/test/factories" diff --git a/spec/forms/decidim/ub/verifications/ub_ant_spec.rb b/spec/forms/decidim/ub/verifications/ub_ant_spec.rb new file mode 100644 index 0000000..0a70723 --- /dev/null +++ b/spec/forms/decidim/ub/verifications/ub_ant_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + module Ub + module Verifications + describe UbAnt do + subject { described_class.from_params(attributes) } + + let(:attributes) do + { + "user" => user + } + end + let(:roles) { %w(ANT) } + let(:user) { create(:user, ub_roles: roles) } + let(:identity) { create(:identity, user:, provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME) } + + it "returns the valid role" do + expect(subject.send(:role)).to eq("ANT") + end + + context "when everything is ok" do + it { is_expected.to be_valid } + + it "returns valid organization" do + expect(subject.send(:organization)).to eq(user.organization) + end + + it "returns valid user" do + expect(subject.send(:user)).to eq(user) + end + end + + context "when the user does not have the role" do + let(:roles) { %w(EST) } + + it { is_expected.not_to be_valid } + end + end + end + end +end diff --git a/spec/forms/decidim/ub/verifications/ub_est_spec.rb b/spec/forms/decidim/ub/verifications/ub_est_spec.rb new file mode 100644 index 0000000..4b82540 --- /dev/null +++ b/spec/forms/decidim/ub/verifications/ub_est_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + module Ub + module Verifications + describe UbEst do + subject { described_class.from_params(attributes) } + + let(:attributes) do + { + "user" => user + } + end + let(:roles) { %w(EST) } + let(:user) { create(:user, ub_roles: roles) } + let(:identity) { create(:identity, user:, provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME) } + + it "returns the valid role" do + expect(subject.send(:role)).to eq("EST") + end + + context "when everything is ok" do + it { is_expected.to be_valid } + + it "returns valid organization" do + expect(subject.send(:organization)).to eq(user.organization) + end + + it "returns valid user" do + expect(subject.send(:user)).to eq(user) + end + end + + context "when the user does not have the role" do + let(:roles) { %w(ANT) } + + it { is_expected.not_to be_valid } + end + end + end + end +end diff --git a/spec/forms/decidim/ub/verifications/ub_pas_spec.rb b/spec/forms/decidim/ub/verifications/ub_pas_spec.rb new file mode 100644 index 0000000..92f1bc3 --- /dev/null +++ b/spec/forms/decidim/ub/verifications/ub_pas_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + module Ub + module Verifications + describe UbPas do + subject { described_class.from_params(attributes) } + + let(:attributes) do + { + "user" => user + } + end + let(:roles) { %w(PAS) } + let(:user) { create(:user, ub_roles: roles) } + let(:identity) { create(:identity, user:, provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME) } + + it "returns the valid role" do + expect(subject.send(:role)).to eq("PAS") + end + + context "when everything is ok" do + it { is_expected.to be_valid } + + it "returns valid organization" do + expect(subject.send(:organization)).to eq(user.organization) + end + + it "returns valid user" do + expect(subject.send(:user)).to eq(user) + end + end + + context "when the user does not have the role" do + let(:roles) { %w(ANT) } + + it { is_expected.not_to be_valid } + end + end + end + end +end diff --git a/spec/forms/decidim/ub/verifications/ub_pdi_spec.rb b/spec/forms/decidim/ub/verifications/ub_pdi_spec.rb new file mode 100644 index 0000000..f3ff75f --- /dev/null +++ b/spec/forms/decidim/ub/verifications/ub_pdi_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + module Ub + module Verifications + describe UbPdi do + subject { described_class.from_params(attributes) } + + let(:attributes) do + { + "user" => user + } + end + let(:roles) { %w(PDI) } + let(:user) { create(:user, ub_roles: roles) } + let(:identity) { create(:identity, user:, provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME) } + + it "returns the valid role" do + expect(subject.send(:role)).to eq("PDI") + end + + context "when everything is ok" do + it { is_expected.to be_valid } + + it "returns valid organization" do + expect(subject.send(:organization)).to eq(user.organization) + end + + it "returns valid user" do + expect(subject.send(:user)).to eq(user) + end + end + + context "when the user does not have the role" do + let(:roles) { %w(ANT) } + + it { is_expected.not_to be_valid } + end + end + end + end +end diff --git a/spec/forms/decidim/ub/verifications/ub_pex_spec.rb b/spec/forms/decidim/ub/verifications/ub_pex_spec.rb new file mode 100644 index 0000000..fea578f --- /dev/null +++ b/spec/forms/decidim/ub/verifications/ub_pex_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + module Ub + module Verifications + describe UbPex do + subject { described_class.from_params(attributes) } + + let(:attributes) do + { + "user" => user + } + end + let(:roles) { %w(PEX) } + let(:user) { create(:user, ub_roles: roles) } + let(:identity) { create(:identity, user:, provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME) } + + it "returns the valid role" do + expect(subject.send(:role)).to eq("PEX") + end + + context "when everything is ok" do + it { is_expected.to be_valid } + + it "returns valid organization" do + expect(subject.send(:organization)).to eq(user.organization) + end + + it "returns valid user" do + expect(subject.send(:user)).to eq(user) + end + end + + context "when the user does not have the role" do + let(:roles) { %w(ANT) } + + it { is_expected.not_to be_valid } + end + end + end + end +end diff --git a/spec/jobs/decidim/ub/auto_verification_job_spec.rb b/spec/jobs/decidim/ub/auto_verification_job_spec.rb new file mode 100644 index 0000000..2ef8b16 --- /dev/null +++ b/spec/jobs/decidim/ub/auto_verification_job_spec.rb @@ -0,0 +1,112 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + module Ub + describe AutoVerificationJob do + subject { described_class } + + shared_examples_for "no authorization is created" do + it "does not create an authorization" do + expect { subject.perform_now(params) }.not_to change(Decidim::Authorization, :count) + end + end + + shared_examples_for "authorizations for the roles are created or removed" do |number| + it "creates authorizations for the roles" do + expect { subject.perform_now(params) }.to change(Decidim::Authorization, :count).by(number) + end + + it "creates authorizations for the roles provided" do + subject.perform_now(params) + expect(Decidim::Authorization.where(user: user).map(&:name)).to match_array(Decidim::Ub.roles_to_auth_name(roles & Decidim::Ub::ROLES)) + end + end + + describe "queue" do + it "is queued to events" do + expect(subject.queue_name).to eq "default" + end + end + + describe "perform" do + let(:roles) { %w(PAS PDI) } + let(:user) { create(:user, ub_roles: roles) } + let(:params) { user.id } + + before do + allow(Rails.logger).to receive(:info).and_call_original + allow(Rails.logger).to receive(:error).and_call_original + end + + it_behaves_like "authorizations for the roles are created or removed", 2 + + context "when the user already has the authorization for the roles" do + let!(:authorization_pas) { create(:authorization, name: "ub_pas", user:) } + let!(:authorization_pdi) { create(:authorization, name: "ub_pdi", user:) } + + it_behaves_like "no authorization is created" + + context "when the roles are different from the user roles" do + let(:roles) { %w(ANT EST PEX) } + + it_behaves_like "authorizations for the roles are created or removed", 1 + + context "when the authorization cannot be removed" do + before do + # rubocop: disable RSpec/AnyInstance + allow_any_instance_of(Decidim::Verifications::DestroyUserAuthorization).to receive(:authorization).and_return(nil) + # rubocop: enable RSpec/AnyInstance + end + + it "writes an error log" do + subject.perform_now(params) + expect(Rails.logger).to have_received(:error).with(/AutoVerificationJob: ERROR: not removed auth ub_pas/) + expect(Rails.logger).to have_received(:error).with(/AutoVerificationJob: ERROR: not removed auth ub_pdi/) + end + end + + context "when the authorization cannot be created" do + before do + # rubocop: disable RSpec/AnyInstance + allow_any_instance_of(Decidim::AuthorizationHandler).to receive(:invalid?).and_return(true) + # rubocop: enable RSpec/AnyInstance + end + + it "writes an error log" do + subject.perform_now(params) + expect(Rails.logger).to have_received(:error).with(/AutoVerificationJob: ERROR: not created auth ub_ant/) + expect(Rails.logger).to have_received(:error).with(/AutoVerificationJob: ERROR: not created auth ub_est/) + expect(Rails.logger).to have_received(:error).with(/AutoVerificationJob: ERROR: not created auth ub_pex/) + end + end + end + + context "when the roles are removed" do + let(:roles) { [] } + + it_behaves_like "authorizations for the roles are created or removed", -2 + end + + context "when the role does not exist" do + let(:roles) { %w(FOO) } + + it_behaves_like "authorizations for the roles are created or removed", -2 + end + end + + context "when the user does not exist" do + let(:params) { -1 } + + it_behaves_like "no authorization is created" + + it "writes an error log" do + subject.perform_now(params) + expect(Rails.logger).to have_received(:error).with(/AutoVerificationJob: ERROR: model not found for user/) + end + end + end + end + end +end diff --git a/spec/jobs/decidim/ub/omniauth_user_sync_job_spec.rb b/spec/jobs/decidim/ub/omniauth_user_sync_job_spec.rb new file mode 100644 index 0000000..5bf6a35 --- /dev/null +++ b/spec/jobs/decidim/ub/omniauth_user_sync_job_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + module Ub + describe OmniauthUserSyncJob do + subject { described_class } + + describe "queue" do + it "is queued to events" do + expect(subject.queue_name).to eq "default" + end + end + + describe "perform" do + let(:roles) { %w(PAS PDI) } + let(:user) { create(:user, ub_roles: roles) } + let(:params) { { user_id: user.id, raw_data: { info: { roles: } } } } + + before do + allow(Rails.logger).to receive(:info).and_call_original + allow(Rails.logger).to receive(:error).and_call_original + subject.perform_now(params) + end + + context "when the user has no identity" do + it "does not call the sync job" do + expect(Decidim::Ub::SyncUser).not_to receive(:call) + end + + it "does not enqueue job" do + expect { subject.perform_now(params) }.not_to have_enqueued_job(Decidim::Ub::AutoVerificationJob) + end + end + + context "when the user has identity" do + let!(:identity) { create(:identity, user:, provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME) } + + context "when the sync runs successfully" do + it "writes an info log" do + subject.perform_now(params) + expect(Rails.logger).to have_received(:info).with(/OmniauthUserSyncJob: Success/) + end + + it "enqueues one job" do + expect { subject.perform_now(params) }.to have_enqueued_job(Decidim::Ub::AutoVerificationJob).exactly(1) + end + end + + context "when the sync fails" do + before do + # rubocop: disable RSpec/AnyInstance + allow_any_instance_of(Decidim::Ub::SyncUser).to receive(:update_user!).and_raise + # rubocop: enable RSpec/AnyInstance + end + + it "writes an error log" do + subject.perform_now(params) + expect(Rails.logger).to have_received(:error).with(/OmniauthUserSyncJob: ERROR/) + end + end + end + end + end + end +end diff --git a/spec/lib/decidim/ub/version_spec.rb b/spec/lib/decidim/ub/version_spec.rb deleted file mode 100644 index 83d4c05..0000000 --- a/spec/lib/decidim/ub/version_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -require "spec_helper" - -module Decidim - describe Ub do - subject { described_class } - - it "has version" do - expect(subject::VERSION).to eq("0.1.0") - end - - it "has decidim version" do - expect(subject::DECIDIM_VERSION).to eq("~> 0.28.0") - end - - it "has compatible decidim version" do - expect(subject::COMPAT_DECIDIM_VERSION).to eq([">= 0.28.0", "< 0.29"]) - end - end -end diff --git a/spec/models/decidim/user_spec.rb b/spec/models/decidim/user_spec.rb new file mode 100644 index 0000000..e29af81 --- /dev/null +++ b/spec/models/decidim/user_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require "spec_helper" + +module Decidim + describe User do + let!(:user) { create(:user) } + let!(:organization) { user.organization } + + describe "#ub_identity?" do + subject { user.ub_identity? } + + context "when user has a ub-provided identity" do + let!(:identity) { create(:identity, user:, provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME) } + + it { is_expected.to be_truthy } + end + + context "when user doesn't have a ub-provided identity" do + let!(:identity) { create(:identity, user:, provider: "other") } + + it { is_expected.to be_falsey } + end + + context "when user doesn't have an identity" do + it { is_expected.to be_falsey } + end + end + + describe "#ub_identity" do + subject { user.ub_identity } + + context "when user has a ub-provided identity" do + let!(:identity) { create(:identity, user:, provider: Decidim::Ub::OMNIAUTH_PROVIDER_NAME) } + + it { is_expected.to be_a Decidim::Identity } + end + + context "when user doesn't have a ub-provided identity" do + let!(:identity) { create(:identity, user:, provider: "other") } + + it { is_expected.to be_nil } + end + + context "when user doesn't have an identity" do + it { is_expected.to be_nil } + end + end + end +end diff --git a/spec/system/omniauth_button_spec.rb b/spec/system/omniauth_button_spec.rb new file mode 100644 index 0000000..45c45d2 --- /dev/null +++ b/spec/system/omniauth_button_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe "OmniAuth button" do + let!(:organization) { create(:organization) } + + before do + organization.omniauth_settings = omniauth_settings.transform_values do |v| + Decidim::OmniauthProvider.value_defined?(v) ? Decidim::AttributeEncryptor.encrypt(v) : v + end + organization.save + + switch_to_host(organization.host) + visit decidim.new_user_session_path + end + + context "when ub enabled" do + let(:omniauth_settings) do + { + omniauth_settings_ub_enabled: true, + omniauth_settings_ub_icon_path: "media/images/ub_logo.svg", + omniauth_settings_ub_client_id: "test-client-id", + omniauth_settings_ub_client_secret: "test-client-secret", + omniauth_settings_ub_site: "https://test.example.org", + omniauth_settings_ub_authorize_url: "/authorize", + omniauth_settings_ub_token_url: "/token" + } + end + + it "has button" do + expect(page).to have_content "Universitat De Barcelona" + end + end + + context "when odoo disabled" do + let(:omniauth_settings) do + { + omniauth_settings_odoo_keycloak_enabled: false + } + end + + it "has no button" do + expect(page).not_to have_content "Universitat De Barcelona" + end + end +end From 3fe2cc69e9d88d92cc66115b332d94f9cb9b5911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Wed, 10 Jul 2024 17:07:33 +0200 Subject: [PATCH 07/13] Lint --- spec/jobs/decidim/ub/auto_verification_job_spec.rb | 2 +- spec/system/omniauth_button_spec.rb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/jobs/decidim/ub/auto_verification_job_spec.rb b/spec/jobs/decidim/ub/auto_verification_job_spec.rb index 2ef8b16..f21d607 100644 --- a/spec/jobs/decidim/ub/auto_verification_job_spec.rb +++ b/spec/jobs/decidim/ub/auto_verification_job_spec.rb @@ -20,7 +20,7 @@ module Ub it "creates authorizations for the roles provided" do subject.perform_now(params) - expect(Decidim::Authorization.where(user: user).map(&:name)).to match_array(Decidim::Ub.roles_to_auth_name(roles & Decidim::Ub::ROLES)) + expect(Decidim::Authorization.where(user:).map(&:name)).to match_array(Decidim::Ub.roles_to_auth_name(roles & Decidim::Ub::ROLES)) end end diff --git a/spec/system/omniauth_button_spec.rb b/spec/system/omniauth_button_spec.rb index 45c45d2..3e7e47b 100644 --- a/spec/system/omniauth_button_spec.rb +++ b/spec/system/omniauth_button_spec.rb @@ -33,15 +33,15 @@ end end - context "when odoo disabled" do + context "when ub disabled" do let(:omniauth_settings) do { - omniauth_settings_odoo_keycloak_enabled: false + omniauth_settings_ub_keycloak_enabled: false } end it "has no button" do - expect(page).not_to have_content "Universitat De Barcelona" + expect(page).to have_no_content "Universitat De Barcelona" end end end From 1f4eb4e9ea3a73fbd1eb64715df40dcc253b2bad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Wed, 10 Jul 2024 17:31:14 +0200 Subject: [PATCH 08/13] Add OAuth strategy test --- spec/omni_auth/strategies/ub_keycloak_spec.rb | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 spec/omni_auth/strategies/ub_keycloak_spec.rb diff --git a/spec/omni_auth/strategies/ub_keycloak_spec.rb b/spec/omni_auth/strategies/ub_keycloak_spec.rb new file mode 100644 index 0000000..b4cb866 --- /dev/null +++ b/spec/omni_auth/strategies/ub_keycloak_spec.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe OmniAuth::Strategies::Ub do + subject do + described_class.new({}, client_id, client_secret, client_options:).tap do |strategy| + allow(strategy).to receive_messages(request:, session: []) + end + end + + let(:client_id) { "test-client-id" } + let(:client_secret) { "test-client-secret" } + let(:client_options) { { site: "https://test.example.org", authorize_url: "/authorize", token_url: "/token" } } + let(:request) { double("Request", params: {}, cookies: {}, env: {}, scheme: "https", url: "") } + + let(:id) { "314159" } + let(:nickname) { "mr_john_doe" } + let(:email) { "john.doe@example.org" } + let(:name) { "John Doe" } + let(:roles) { %w(PAS PDI) } + + let(:raw_info) { { employeenumber: [id], cn: [name], mail: [email], uidnet: [nickname], colect2: roles }.stringify_keys } + + describe "client options" do + it "has correct name" do + expect(subject.options.name).to eq("ub") + end + + it "has correct client id" do + expect(subject.options.client_id).to eq(client_id) + end + + it "has correct client secret" do + expect(subject.options.client_secret).to eq(client_secret) + end + + it "has correct site" do + expect(subject.options.client_options.site).to eq(client_options[:site]) + end + + it "has correct authorize_url" do + expect(subject.options.client_options.authorize_url).to eq(client_options[:authorize_url]) + end + + it "has correct token_url" do + expect(subject.options.client_options.token_url).to eq(client_options[:token_url]) + end + end + + describe "info" do + before do + # rubocop: disable RSpec/SubjectStub + allow(subject).to receive(:raw_info).and_return(raw_info) + # rubocop: enable RSpec/SubjectStub + end + + it "returns the uid" do + expect(subject.uid).to eq(id) + end + + it "returns the nickname" do + expect(subject.info[:nickname]).to eq(nickname) + end + + it "returns the email" do + expect(subject.info[:email]).to eq(email) + end + + it "returns the name" do + expect(subject.info[:name]).to eq(name) + end + + it "returns the roles" do + expect(subject.info[:roles]).to eq(roles) + end + + context "when the name is invalid" do + let(:name) { "John+Doe" } + + it "is sanitized" do + expect(subject.info[:name]).to eq("JohnDoe") + end + end + + context "when the nickname is invalid" do + let(:nickname) { "john.doe" } + + it "is sanitized" do + expect(subject.info[:nickname]).to eq("john_doe") + end + end + end +end From de3ebb485a0cdec50b077e8f30620bd9758a6745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Wed, 10 Jul 2024 17:36:45 +0200 Subject: [PATCH 09/13] Test auto verification --- spec/lib/ub/ub_automatic_verification_spec.rb | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 spec/lib/ub/ub_automatic_verification_spec.rb diff --git a/spec/lib/ub/ub_automatic_verification_spec.rb b/spec/lib/ub/ub_automatic_verification_spec.rb new file mode 100644 index 0000000..c4d1ba2 --- /dev/null +++ b/spec/lib/ub/ub_automatic_verification_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require "spec_helper" + +# rubocop:disable RSpec/DescribeClass +describe "Automatic verification after oauth sign up" do + let!(:user) { create(:user) } + + context "when a user is registered with omniauth" do + it "runs the OmniauthUserSyncJob" do + expect do + ActiveSupport::Notifications.publish( + "decidim.user.omniauth_registration", + user_id: user.id, + identity_id: 1234, + provider: "ub", + uid: "aaa", + email: user.email, + name: "Ub User", + nickname: "ub_user", + avatar_url: "https://example.org/foo.jpg", + raw_data: {} + ) + end.to have_enqueued_job(Decidim::Ub::OmniauthUserSyncJob) + end + end + + context "when a ub user is updated" do + it "runs the AutoVerificationJob" do + expect do + ActiveSupport::Notifications.publish( + "decidim.ub.user.updated", + user.id + ) + end.to have_enqueued_job(Decidim::Ub::AutoVerificationJob) + end + end +end + +# rubocop:enable RSpec/DescribeClass From 32be342a68a13ce8b2cfb519a92a5522bbceee6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Wed, 10 Jul 2024 18:36:59 +0200 Subject: [PATCH 10/13] Improve coverage --- .rubocop_todo.yml | 8 ++++++++ .simplecov | 1 + spec/jobs/decidim/ub/auto_verification_job_spec.rb | 4 ---- spec/jobs/decidim/ub/omniauth_user_sync_job_spec.rb | 2 -- spec/lib/ub/ub_automatic_verification_spec.rb | 3 --- .../strategies/{ub_keycloak_spec.rb => ub_spec.rb} | 12 ++++++------ 6 files changed, 15 insertions(+), 15 deletions(-) rename spec/omni_auth/strategies/{ub_keycloak_spec.rb => ub_spec.rb} (86%) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index e69de29..c6abf79 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -0,0 +1,8 @@ +RSpec/AnyInstance: + Exclude: + - 'spec/jobs/decidim/ub/auto_verification_job_spec.rb' + - 'spec/jobs/decidim/ub/omniauth_user_sync_job_spec.rb' + - 'spec/omni_auth/strategies/ub_spec.rb' +RSpec/DescribeClass: + Exclude: + - 'spec/lib/ub/ub_automatic_verification_spec.rb' diff --git a/.simplecov b/.simplecov index 372b358..0e37e73 100644 --- a/.simplecov +++ b/.simplecov @@ -7,6 +7,7 @@ SimpleCov.start do add_filter "lib/generators" add_filter "lib/decidim/ub/version.rb" + add_filter "lib/omniauth/strategies/ub.rb" add_filter "/spec" end diff --git a/spec/jobs/decidim/ub/auto_verification_job_spec.rb b/spec/jobs/decidim/ub/auto_verification_job_spec.rb index f21d607..086f05d 100644 --- a/spec/jobs/decidim/ub/auto_verification_job_spec.rb +++ b/spec/jobs/decidim/ub/auto_verification_job_spec.rb @@ -55,9 +55,7 @@ module Ub context "when the authorization cannot be removed" do before do - # rubocop: disable RSpec/AnyInstance allow_any_instance_of(Decidim::Verifications::DestroyUserAuthorization).to receive(:authorization).and_return(nil) - # rubocop: enable RSpec/AnyInstance end it "writes an error log" do @@ -69,9 +67,7 @@ module Ub context "when the authorization cannot be created" do before do - # rubocop: disable RSpec/AnyInstance allow_any_instance_of(Decidim::AuthorizationHandler).to receive(:invalid?).and_return(true) - # rubocop: enable RSpec/AnyInstance end it "writes an error log" do diff --git a/spec/jobs/decidim/ub/omniauth_user_sync_job_spec.rb b/spec/jobs/decidim/ub/omniauth_user_sync_job_spec.rb index 5bf6a35..dede06c 100644 --- a/spec/jobs/decidim/ub/omniauth_user_sync_job_spec.rb +++ b/spec/jobs/decidim/ub/omniauth_user_sync_job_spec.rb @@ -50,9 +50,7 @@ module Ub context "when the sync fails" do before do - # rubocop: disable RSpec/AnyInstance allow_any_instance_of(Decidim::Ub::SyncUser).to receive(:update_user!).and_raise - # rubocop: enable RSpec/AnyInstance end it "writes an error log" do diff --git a/spec/lib/ub/ub_automatic_verification_spec.rb b/spec/lib/ub/ub_automatic_verification_spec.rb index c4d1ba2..547d80f 100644 --- a/spec/lib/ub/ub_automatic_verification_spec.rb +++ b/spec/lib/ub/ub_automatic_verification_spec.rb @@ -2,7 +2,6 @@ require "spec_helper" -# rubocop:disable RSpec/DescribeClass describe "Automatic verification after oauth sign up" do let!(:user) { create(:user) } @@ -36,5 +35,3 @@ end end end - -# rubocop:enable RSpec/DescribeClass diff --git a/spec/omni_auth/strategies/ub_keycloak_spec.rb b/spec/omni_auth/strategies/ub_spec.rb similarity index 86% rename from spec/omni_auth/strategies/ub_keycloak_spec.rb rename to spec/omni_auth/strategies/ub_spec.rb index b4cb866..f21d0e4 100644 --- a/spec/omni_auth/strategies/ub_keycloak_spec.rb +++ b/spec/omni_auth/strategies/ub_spec.rb @@ -21,6 +21,12 @@ let(:roles) { %w(PAS PDI) } let(:raw_info) { { employeenumber: [id], cn: [name], mail: [email], uidnet: [nickname], colect2: roles }.stringify_keys } + let(:access_token) { OpenStruct.new(token: "secret-token", response: OpenStruct.new(parsed: OpenStruct.new(token_type: "Bearer"))) } + + before do + allow_any_instance_of(described_class).to receive(:access_token).and_return(access_token) + stub_request(:get, "https://test.example.org/api/adas/oauth2/tokendata").to_return(status: 200, body: raw_info.to_json) + end describe "client options" do it "has correct name" do @@ -49,12 +55,6 @@ end describe "info" do - before do - # rubocop: disable RSpec/SubjectStub - allow(subject).to receive(:raw_info).and_return(raw_info) - # rubocop: enable RSpec/SubjectStub - end - it "returns the uid" do expect(subject.uid).to eq(id) end From b5cc7dc103667c0b5c9710f54c1d62ea01019c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Wed, 10 Jul 2024 18:40:29 +0200 Subject: [PATCH 11/13] Add callback_url test --- spec/omni_auth/strategies/ub_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spec/omni_auth/strategies/ub_spec.rb b/spec/omni_auth/strategies/ub_spec.rb index f21d0e4..9faa8f6 100644 --- a/spec/omni_auth/strategies/ub_spec.rb +++ b/spec/omni_auth/strategies/ub_spec.rb @@ -20,10 +20,15 @@ let(:name) { "John Doe" } let(:roles) { %w(PAS PDI) } + let(:full_host) { "https://test.example.org" } + let(:callback_path) { "/auth/ub/callback" } + let(:raw_info) { { employeenumber: [id], cn: [name], mail: [email], uidnet: [nickname], colect2: roles }.stringify_keys } let(:access_token) { OpenStruct.new(token: "secret-token", response: OpenStruct.new(parsed: OpenStruct.new(token_type: "Bearer"))) } before do + allow_any_instance_of(described_class).to receive(:full_host).and_return(full_host) + allow_any_instance_of(described_class).to receive(:callback_path).and_return(callback_path) allow_any_instance_of(described_class).to receive(:access_token).and_return(access_token) stub_request(:get, "https://test.example.org/api/adas/oauth2/tokendata").to_return(status: 200, body: raw_info.to_json) end @@ -54,6 +59,12 @@ end end + describe "callback_url" do + it "returns the full callback url" do + expect(subject.callback_url).to eq("#{full_host}#{callback_path}") + end + end + describe "info" do it "returns the uid" do expect(subject.uid).to eq(id) From 91ba559823b29bb369be236a460f9a6ad8ad52fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Wed, 10 Jul 2024 18:43:12 +0200 Subject: [PATCH 12/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 210f640..8845594 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![[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) [![[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) [![Maintainability](https://api.codeclimate.com/v1/badges/c975a347c58389448503/maintainability)](https://codeclimate.com/github/Platoniq/decidim-module-ub/maintainability) -[![Coverage Status](https://coveralls.io/repos/github/Platoniq/decidim-module-ub/badge.svg?branch=HEAD)](https://coveralls.io/github/Platoniq/decidim-module-ub?branch=HEAD) +[![Coverage Status](https://coveralls.io/repos/github/Platoniq/decidim-module-ub/badge.svg?branch=main)](https://coveralls.io/github/Platoniq/decidim-module-ub?branch=main) A Decidim module to sync users from Universitat de Barcelona who connect to the platform. From 79a979ec93077c18c677ec133174b5e1610c3584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Bol=C3=ADvar?= Date: Wed, 10 Jul 2024 18:49:31 +0200 Subject: [PATCH 13/13] Fix .simplecov --- .simplecov | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.simplecov b/.simplecov index 0e37e73..ed44218 100644 --- a/.simplecov +++ b/.simplecov @@ -7,7 +7,7 @@ SimpleCov.start do add_filter "lib/generators" add_filter "lib/decidim/ub/version.rb" - add_filter "lib/omniauth/strategies/ub.rb" + add_filter "lib/omniauth/ub.rb" add_filter "/spec" end