From fb1d9089c65612fc46c7538d8fcbeda431159488 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Gaya?= <sebastien.gaya@gmail.com> Date: Mon, 4 Sep 2023 15:31:47 +0200 Subject: [PATCH] invalidate access token --- app/mailers/notification_mailer.rb | 9 +++++++++ app/models/communication/website.rb | 1 + .../communication/website/with_git_repository.rb | 10 ++++++++++ app/models/communication/website/with_managers.rb | 11 +++++++++++ app/services/git/providers/abstract.rb | 15 ++++++++------- app/services/git/providers/github.rb | 11 +++++++++++ app/services/git/providers/gitlab.rb | 13 ++++++++++++- app/services/git/repository.rb | 5 +---- .../website_invalid_access_token.html.erb | 3 +++ config/locales/en.yml | 8 ++++++-- config/locales/fr.yml | 8 ++++++-- 11 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 app/models/communication/website/with_managers.rb create mode 100644 app/views/mailers/notifications/website_invalid_access_token.html.erb diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb index 26efb189a..5b4fded48 100644 --- a/app/mailers/notification_mailer.rb +++ b/app/mailers/notification_mailer.rb @@ -21,4 +21,13 @@ class NotificationMailer < ApplicationMailer mail(from: user.university.mail_from[:full], to: user.email, subject: subject) end + def website_invalid_access_token(website, user) + @website = website + @url = edit_admin_communication_website_path(website) + merge_with_university_infos(user.university, {}) + I18n.locale = user.language.iso_code + subject = t('mailers.notifications.website_invalid_access_token.subject', website: website) + mail(from: user.university.mail_from[:full], to: user.email, subject: subject) + end + end diff --git a/app/models/communication/website.rb b/app/models/communication/website.rb index c35d720f6..1ae31f1e2 100644 --- a/app/models/communication/website.rb +++ b/app/models/communication/website.rb @@ -47,6 +47,7 @@ class Communication::Website < ApplicationRecord include WithGitRepository include WithImport include WithLanguages + include WithManagers include WithProgramCategories include WithReferences include WithSpecialPages diff --git a/app/models/communication/website/with_git_repository.rb b/app/models/communication/website/with_git_repository.rb index 43a5d6c14..93abed016 100644 --- a/app/models/communication/website/with_git_repository.rb +++ b/app/models/communication/website/with_git_repository.rb @@ -38,6 +38,16 @@ module Communication::Website::WithGitRepository end handle_asynchronously :destroy_obsolete_git_files, queue: :default + def invalidate_access_token! + # Nullify the expired token + update_column :access_token, nil + # Notify admins and website managers managing this website. + users_to_notify = university.users.admin + university.users.website_manager.where(id: manager_ids) + users_to_notify.each do |user| + NotificationMailer.website_invalid_access_token(self, user).deliver_later + end + end + # Le website devient data/website.yml # Les configs héritent du modèle website et s'exportent en différents fichiers def exportable_to_git? diff --git a/app/models/communication/website/with_managers.rb b/app/models/communication/website/with_managers.rb new file mode 100644 index 000000000..c98cf2c21 --- /dev/null +++ b/app/models/communication/website/with_managers.rb @@ -0,0 +1,11 @@ +module Communication::Website::WithManagers + extend ActiveSupport::Concern + + included do + has_and_belongs_to_many :managers, + class_name: 'User', + join_table: :communication_websites_users, + foreign_key: :communication_website_id, + association_foreign_key: :user_id + end +end diff --git a/app/services/git/providers/abstract.rb b/app/services/git/providers/abstract.rb index ceb8a3423..3debfe848 100644 --- a/app/services/git/providers/abstract.rb +++ b/app/services/git/providers/abstract.rb @@ -1,11 +1,12 @@ class Git::Providers::Abstract - attr_reader :endpoint, :branch, :access_token, :repository - - def initialize(endpoint, branch, access_token, repository) - @endpoint = endpoint - @branch = branch - @access_token = access_token - @repository = repository + attr_reader :git_repository; :endpoint, :branch, :access_token, :repository + + def initialize(git_repository) + @git_repository = git_repository + @endpoint = git_repository.website.git_endpoint + @branch = git_repository.website.git_branch + @access_token = git_repository.website.access_token + @repository = git_repository.website.repository end def valid? diff --git a/app/services/git/providers/github.rb b/app/services/git/providers/github.rb index 58dae24af..882b936b0 100644 --- a/app/services/git/providers/github.rb +++ b/app/services/git/providers/github.rb @@ -86,6 +86,17 @@ class Git::Providers::Github < Git::Providers::Abstract nil end + def valid? + return false unless super + begin + client.repository(repository) + true + rescue Octokit::Unauthorized + git_repository.website.invalidate_access_token! + false + end + end + protected def client diff --git a/app/services/git/providers/gitlab.rb b/app/services/git/providers/gitlab.rb index 39c928078..44cdfe59c 100644 --- a/app/services/git/providers/gitlab.rb +++ b/app/services/git/providers/gitlab.rb @@ -63,6 +63,17 @@ class Git::Providers::Gitlab < Git::Providers::Abstract sha end + def valid? + return false unless super + begin + client.project(repository) + true + rescue Gitlab::Error::Unauthorized + git_repository.website.invalidate_access_token! + false + end + end + def branch super.present? ? super : 'main' @@ -76,7 +87,7 @@ class Git::Providers::Gitlab < Git::Providers::Abstract end def client - @client ||= Gitlab.client( + @client ||= Gitlab.client( endpoint: endpoint, private_token: access_token ) diff --git a/app/services/git/repository.rb b/app/services/git/repository.rb index 7863c6de0..9ba136cf2 100644 --- a/app/services/git/repository.rb +++ b/app/services/git/repository.rb @@ -48,10 +48,7 @@ class Git::Repository protected def provider - @provider ||= provider_class.new website&.git_endpoint, - website&.git_branch, - website&.access_token, - website&.repository + @provider ||= provider_class.new self end def provider_class diff --git a/app/views/mailers/notifications/website_invalid_access_token.html.erb b/app/views/mailers/notifications/website_invalid_access_token.html.erb new file mode 100644 index 000000000..c4fdbbeb6 --- /dev/null +++ b/app/views/mailers/notifications/website_invalid_access_token.html.erb @@ -0,0 +1,3 @@ +<p><%= t('mailers.notifications.website_invalid_access_token.text_line_1_html', website: @website) %></p> +<p><%= t('mailers.notifications.import.text_line_2_html', url: @url) %></p> +<p><%= t('mailers.yours') %></p> diff --git a/config/locales/en.yml b/config/locales/en.yml index fc5648c67..2d621b809 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -141,7 +141,7 @@ en: successfully_quit_html: "<i>%{model}</i> successfully quit <i>%{target}</i>." successfully_removed_html: "<i>%{model}</i> was successfully removed." successfully_updated_html: "<i>%{model}</i> was successfully updated." - summary: + summary: label: Summary hint: A short text, like a heading for an article. Don't write all the content here, there are blocks for that. users_alerts: @@ -269,6 +269,10 @@ en: text_line_3_html: "Number of lines in the file: %{number}." text_error_msg: "Line %{line}: %{error}" text_errors_title: "Some errors have occured:" + website_invalid_access_token: + subject: "Expired access token for \"%{website}\"" + text_line_1_html: "The access token used for the website \"%{website}\" has expired and does not allow the website to be updated anymore." + text_line_2_html: "To solve this issue, please fill in a new access token by clicking <a href=\"%{url}\">here</a>." yours: Yours. menu: admin: Admin @@ -307,7 +311,7 @@ en: delivered: Your message has been sent filters: Filters target: Target - users: + users: one: "%{count} user" other: "%{count} users" websites: diff --git a/config/locales/fr.yml b/config/locales/fr.yml index c7e4dc9de..7a7578d75 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -141,7 +141,7 @@ fr: successfully_quit_html: "<i>%{model}</i> a bien quitté <i>%{target}</i>." successfully_removed_html: "<i>%{model}</i> a bien été retiré(e)." successfully_updated_html: "<i>%{model}</i> a bien été mis(e) à jour." - summary: + summary: label: Résumé hint: Un texte court, comme un chapô pour un article. Ne mettez pas tout le contenu ici, pour ça, il y a les blocs ! users_alerts: @@ -269,6 +269,10 @@ fr: text_line_3_html: "Nombre de lignes traitées : %{number}." text_error_msg: "Ligne %{line} : %{error}" text_errors_title: "Des erreurs sont survenues :" + website_invalid_access_token: + subject: Jeton d'accès expiré pour « %{website} » + text_line_1_html: Le jeton d'accès utilisé pour le site « %{website} » a expiré et ne permet plus la mise à jour du site. + text_line_2_html: Pour résoudre ce problème, veuillez renseigner un nouveau jeton d'accès en cliquant <a href=\"%{url}\">ici</a>. yours: Cordialement. menu: admin: Admin @@ -307,7 +311,7 @@ fr: delivered: Votre message a bien été envoyé filters: Filtres target: Cible - users: + users: one: "%{count} utilisateur" other: "%{count} utilisateurs" websites: -- GitLab