FEATURE: Limit oauth scope

FEATURE: Limit oauth scope

This commit requires you change your config.

  • Added a site setting that determines whether to send comments back to github,
  • Removed need for github repo permission to be given by users,
  • Comments are now (optionally) sent back to github using the github token provided,
  • A new rake task, code_review_delete_user_github_access_tokens, deletes all collected access tokens that are now unnecessary,
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index dcabec4..293101e 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -1,9 +1,10 @@
 en:
   site_settings:
     code_review_enabled: 'enable Discourse code review'
+    code_review_github_token: "Token to use for github API, this can be generated via https://github.com/settings/tokens/new . 'repo' permission is required if sync_to_github or code_review_allow_private_clone is enabled"
+    code_review_sync_to_github: 'REQUIRES: code_review_github_token, should comments here be sent to github?'
     code_review_catch_up_commits: 'When a new repo is added create this number of topics for old commits'
-    code_review_api_username: 'OAuth key of this username will be used for API calls, this means we get 5000 an hour vs 60'
-    code_review_allow_private_clone: 'REQUIRES: code_review_api_username, will clone the repos as the entered user name, this safeguard is in place to disable cloning of private repos on public sites.'
+    code_review_allow_private_clone: 'REQUIRES: code_review_github_token, will clone the repos as the associated user, this safeguard is in place to disable cloning of private repos on public sites.'
     code_review_pending_tag: 'Tag to apply to pending commits'
     code_review_followup_tag: 'Tag to apply to follow up commits'
     code_review_approved_tag: 'Tag to apply to approved commits'
diff --git a/config/settings.yml b/config/settings.yml
index e740a72..3737ad6 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -1,7 +1,8 @@
 plugins:
   code_review_enabled: false
+  code_review_github_token: ""
+  code_review_sync_to_github: false
   code_review_catch_up_commits: 10
-  code_review_api_username: ""
   code_review_allow_private_clone: false
   code_review_pending_tag:
     client: true
diff --git a/lib/discourse_code_review/github_repo.rb b/lib/discourse_code_review/github_repo.rb
index 8d32530..7a55a5d 100644
--- a/lib/discourse_code_review/github_repo.rb
+++ b/lib/discourse_code_review/github_repo.rb
@@ -193,9 +193,11 @@ module DiscourseCodeReview
     end
 
     def clone(path)
+      github_token = SiteSetting.code_review_github_token
+
       url =
-        if (SiteSetting.code_review_allow_private_clone && SiteSetting.code_review_api_username.present?)
-          "https://#{octokit_client.access_token}@github.com/#{@name}.git"
+        if (SiteSetting.code_review_allow_private_clone && github_token.present?)
+          "https://#{github_token}@github.com/#{@name}.git"
         else
           "https://github.com/#{@name}.git"
         end
diff --git a/plugin.rb b/plugin.rb
index 97eb76f..aacc5b1 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -20,37 +20,19 @@ module HackGithubAuthenticator
   def after_authenticate(auth_token, existing_account: nil)
     result = super(auth_token, existing_account: existing_account)
 
-    if SiteSetting.code_review_enabled
+    if SiteSetting.code_review_enabled?
       if user_id = result.user&.id
         token = auth_token.credentials.token
 
         user = result.user
-        user.custom_fields[DiscourseCodeReview::UserToken] = token
         user.custom_fields[DiscourseCodeReview::GithubId] = auth_token[:uid]
         user.custom_fields[DiscourseCodeReview::GithubLogin] = auth_token.info.nickname
         user.save_custom_fields
-
       end
     end
 
     result
   end
-
-  def register_middleware(omniauth)
-    scope = "user:email"
-
-    if SiteSetting.code_review_enabled
-      scope = "user:email,repo"
-    end
-
-    omniauth.provider :github,
-           setup: lambda { |env|
-             strategy = env["omniauth.strategy"]
-              strategy.options[:client_id] = SiteSetting.github_client_id
-              strategy.options[:client_secret] = SiteSetting.github_client_secret
-           },
-           scope: scope
-  end
 end
 
 class ::Auth::GithubAuthenticator
@@ -67,30 +49,64 @@ after_initialize do
   module ::DiscourseCodeReview
     PluginName = 'discourse-code-review'
 
+    class APIUserError < StandardError
+    end
+
     class Engine < ::Rails::Engine
       engine_name 'code-review'
       isolate_namespace DiscourseCodeReview
     end
 
-    UserToken = 'github user token'
     CommitHash = 'commit hash'
     GithubId = 'github id'
     GithubLogin = 'github login'
     CommentPath = 'comment path'
     CommentPosition = 'comment position'
 
+    def self.octokit_bot_client
+      token = SiteSetting.code_review_github_token
+
+      if token.nil? || token.empty?
+        raise APIUserError, "code_review_github_token not set"
+      end
+
+      Octokit::Client.new(access_token: token)
+    end
+
     def self.octokit_client
-      client = Octokit::Client.new
+      self.octokit_bot_client
+    rescue APIUserError
+      Octokit::Client.new
+    end
+
+    def self.sync_post_to_github(client, post)
+      topic = post.topic
+      hash = topic&.custom_fields[DiscourseCodeReview::CommitHash]
+      user = post.user
+
+      if post.post_number > 1 && !post.whisper? && post.raw.present? && topic && hash && user
+        if !post.custom_fields[DiscourseCodeReview::GithubId]
+          fields = post.reply_to_post&.custom_fields || {}
+          path = fields[DiscourseCodeReview::CommentPath]
+          position = fields[DiscourseCodeReview::CommentPosition]
+
+          if repo = post.topic.category.custom_fields[DiscourseCodeReview::Importer::GithubRepoName]
+            post_user_name = user.name || user.username
+
+            github_post_contents = [
+              "[#{post_user_name} posted](#{post.full_url}):",
+              '',
+              post.raw
+            ].join("\n")
 
-      if username = SiteSetting.code_review_api_username.presence
-        username = username.downcase
-        id = User.where(username_lower: username).pluck(:id).first
-        if id && (token = UserCustomField.where(user_id: id, name: DiscourseCodeReview::UserToken).pluck(:value).first)
-          client = Octokit::Client.new(access_token: token)
+            comment = client.create_commit_comment(repo, hash, github_post_contents, path, nil, position)
+            post.custom_fields[DiscourseCodeReview::GithubId] = comment.id
+            post.custom_fields[DiscourseCodeReview::CommentPath] = path if path.present?
+            post.custom_fields[DiscourseCodeReview::CommentPosition] = position if position.present?
+            post.save_custom_fields
+          end
         end
       end
-
-      client
     end
   end
 
@@ -109,24 +125,9 @@ after_initialize do
   end
 
   on(:post_process_cooked) do |doc, post|
-    if post.post_number > 1 && !post.whisper? && post.raw.present? && (topic = post.topic) && (hash = topic.custom_fields[DiscourseCodeReview::CommitHash])
-
-      if !post.custom_fields[DiscourseCodeReview::GithubId] && post.user
-        if token = post.user.custom_fields[DiscourseCodeReview::UserToken]
-          client = Octokit::Client.new(access_token: token)
-          fields = post.reply_to_post&.custom_fields || {}
-          path = fields[DiscourseCodeReview::CommentPath]
-          position = fields[DiscourseCodeReview::CommentPosition]
-
-          if repo = post.topic.category.custom_fields[DiscourseCodeReview::Importer::GithubRepoName]
-            comment = client.create_commit_comment(repo, hash, post.raw, path, nil, position)
-            post.custom_fields[DiscourseCodeReview::GithubId] = comment.id
-            post.custom_fields[DiscourseCodeReview::CommentPath] = path if path.present?
-            post.custom_fields[DiscourseCodeReview::CommentPosition] = position if position.present?
-            post.save_custom_fields
-          end
-        end
-      end
+    if SiteSetting.code_review_sync_to_github?
+      client = DiscourseCodeReview.octokit_bot_client
+      DiscourseCodeReview.sync_post_to_github(client, post)
     end
   end
 
@@ -136,3 +137,8 @@ after_initialize do
     end
   end
 end
+

[... diff too long, it was truncated ...]

GitHub sha: d3e12cbb

1 Like

This is my first merge as a discourse team member

2 Likes