Previously, access control was implemented via AccessPolicy and {Access/AppliedTag}. This doesn't remove AccessPolicy/AppliedTag yet, as there are still references to them. They will be removed in a later commit. In order for the new access control to work, the authorization methods need to be passed the project_id, to force the access query to operate on a single project. That part isn't very invasive, since authorization is mostly centralized in helpers/general.rb, but it did require a couple other places to be changed: * model/invoice.rb is the only caller of Authorization.authorize outside of the Clover helpers. This is probably a layer violation that should be fixed later, but for now, add the project_id manually to the call. * In the github route, set @project so that the helpers can access it. Add Project#dissociate_subject, which handles remove the subject tags and direct access control entries when removing a user or token from a project. Call this when removing uses or tokens from a project. Remove Authorization.authorized_resources_dataset, as it was only needed by Dataset#authorize. This inlines the code into Dataset#authorize. This was done because it doesn't make sense to use the method in isolation, and the query needed in Dataset#authorize depends on the dataset, which isn't passed to Authorization.authorized_resources_dataset. Remove Authorization.expand_actions. This method has no equivalent in the new design, and it is no longer needed. For the api specs that use a personal access token, this adds the token to the Admin subject tag (which has full access). This has similar behavior as applying the admin managed policy had previously. The authorization queries do not currently support nested tags. Support for nested tags will be added later. While here, fix parameter name for Clover#all_permissions. This method is only currently called with @project.id as the argument, so it doesn't technically need an argument, but it could potentially be used later to get all permissions on an object other than the current project.
63 lines
3.5 KiB
Ruby
63 lines
3.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Clover
|
|
hash_branch("github") do |r|
|
|
r.get web?, "callback" do
|
|
oauth_code = r.params["code"]
|
|
installation_id = r.params["installation_id"]
|
|
setup_action = r.params["setup_action"]
|
|
code_response = Github.oauth_client.exchange_code_for_token(oauth_code)
|
|
|
|
if (installation = GithubInstallation[installation_id: installation_id])
|
|
@project = installation.project
|
|
authorize("Project:github", installation.project.id)
|
|
flash["notice"] = "GitHub runner integration is already enabled for #{installation.project.name} project."
|
|
Clog.emit("GitHub installation already exists") { {installation_failed: {id: installation_id, account_ubid: current_account.ubid}} }
|
|
r.redirect "#{installation.project.path}/github"
|
|
end
|
|
|
|
unless (@project = project = Project[session.delete("github_installation_project_id")])
|
|
flash["error"] = "You should initiate the GitHub App installation request from the project's GitHub runner integration page."
|
|
Clog.emit("GitHub callback failed due to lack of project in the session") { {installation_failed: {id: installation_id, account_ubid: current_account.ubid}} }
|
|
r.redirect "/project"
|
|
end
|
|
|
|
authorize("Project:github", project.id)
|
|
|
|
if setup_action == "request"
|
|
flash["notice"] = "The GitHub App installation request is awaiting approval from the GitHub organization's administrator. As GitHub will redirect your admin back to the Ubicloud console, the admin needs to have an Ubicloud account with the necessary permissions to finalize the installation. Please invite the admin to your project if they don't have an account yet."
|
|
Clog.emit("GitHub installation initiated by non-admin user") { {installation_failed: {id: installation_id, account_ubid: current_account.ubid}} }
|
|
r.redirect "#{project.path}/user"
|
|
end
|
|
|
|
unless (access_token = code_response[:access_token])
|
|
flash["error"] = "GitHub App installation failed. For any questions or assistance, reach out to our team at support@ubicloud.com"
|
|
Clog.emit("GitHub callback failed due to lack of permission") { {installation_failed: {id: installation_id, account_ubid: current_account.ubid}} }
|
|
r.redirect "#{project.path}/github"
|
|
end
|
|
|
|
unless (installation_response = Octokit::Client.new(access_token: access_token).get("/user/installations")[:installations].find { _1[:id].to_s == installation_id })
|
|
flash["error"] = "GitHub App installation failed. For any questions or assistance, reach out to our team at support@ubicloud.com"
|
|
Clog.emit("GitHub callback failed due to lack of installation") { {installation_failed: {id: installation_id, account_ubid: current_account.ubid}} }
|
|
r.redirect "#{project.path}/github"
|
|
end
|
|
|
|
unless project.active?
|
|
flash["error"] = "GitHub runner integration is not allowed for inactive projects"
|
|
Clog.emit("GitHub callback failed due to inactive project") { {installation_failed: {id: installation_id, account_ubid: current_account.ubid}} }
|
|
r.redirect "#{project.path}/dashboard"
|
|
end
|
|
|
|
GithubInstallation.create_with_id(
|
|
installation_id: installation_id,
|
|
name: installation_response[:account][:login] || installation_response[:account][:name],
|
|
type: installation_response[:account][:type],
|
|
project_id: project.id
|
|
)
|
|
|
|
flash["notice"] = "GitHub runner integration is enabled for #{project.name} project."
|
|
r.redirect "#{project.path}/github"
|
|
end
|
|
end
|
|
end
|