integration with gitlab auth
This commit is contained in:
parent
81f9ee48b1
commit
44261a5d9f
21 changed files with 51 additions and 170 deletions
|
@ -1,5 +1,5 @@
|
|||
module Ci
|
||||
class ApplicationController < ActionController::Base
|
||||
class ApplicationController < ::ApplicationController
|
||||
def self.railtie_helpers_paths
|
||||
"app/helpers/ci"
|
||||
end
|
||||
|
@ -9,49 +9,19 @@ module Ci
|
|||
rescue_from Ci::Network::UnauthorizedError, with: :invalid_token
|
||||
before_filter :default_headers
|
||||
#before_filter :check_config
|
||||
helper_method :gl_project
|
||||
|
||||
protect_from_forgery
|
||||
|
||||
helper_method :current_user
|
||||
before_filter :reset_cache
|
||||
|
||||
private
|
||||
|
||||
def current_user
|
||||
@current_user ||= session[:ci_current_user]
|
||||
end
|
||||
|
||||
def sign_in(user)
|
||||
session[:ci_current_user] = user
|
||||
end
|
||||
|
||||
def sign_out
|
||||
reset_session
|
||||
end
|
||||
|
||||
def authenticate_user!
|
||||
unless current_user
|
||||
redirect_to new_ci_user_sessions_path
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
def authenticate_admin!
|
||||
unless current_user && current_user.is_admin
|
||||
redirect_to new_ci_user_sessions_path
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
def authenticate_public_page!
|
||||
unless project.public
|
||||
unless current_user
|
||||
redirect_to(new_ci_user_sessions_path(state: generate_oauth_state(request.fullpath))) and return
|
||||
redirect_to(new_user_sessions_path) and return
|
||||
end
|
||||
|
||||
unless current_user.can_access_project?(project.gitlab_id)
|
||||
page_404 and return
|
||||
end
|
||||
return access_denied! unless can?(current_user, :read_project, gl_project)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -62,19 +32,23 @@ module Ci
|
|||
end
|
||||
|
||||
def authorize_access_project!
|
||||
unless current_user.can_access_project?(@project.gitlab_id)
|
||||
unless can?(current_user, :read_project, gl_project)
|
||||
return page_404
|
||||
end
|
||||
end
|
||||
|
||||
def authorize_project_developer!
|
||||
unless current_user.has_developer_access?(@project.gitlab_id)
|
||||
def authorize_manage_builds!
|
||||
unless can?(current_user, :manage_builds, gl_project)
|
||||
return page_404
|
||||
end
|
||||
end
|
||||
|
||||
def authenticate_admin!
|
||||
return render_404 unless current_user.is_admin?
|
||||
end
|
||||
|
||||
def authorize_manage_project!
|
||||
unless current_user.can_manage_project?(@project.gitlab_id)
|
||||
unless can?(current_user, :manage_project, gl_project)
|
||||
return page_404
|
||||
end
|
||||
end
|
||||
|
@ -83,13 +57,6 @@ module Ci
|
|||
render file: "#{Rails.root}/public/404.html", status: 404, layout: false
|
||||
end
|
||||
|
||||
# Reset user cache every day for security purposes
|
||||
def reset_cache
|
||||
if current_user && current_user.sync_at < (Time.zone.now - 24.hours)
|
||||
current_user.reset_cache
|
||||
end
|
||||
end
|
||||
|
||||
def default_headers
|
||||
headers['X-Frame-Options'] = 'DENY'
|
||||
headers['X-XSS-Protection'] = '1; mode=block'
|
||||
|
@ -129,5 +96,9 @@ module Ci
|
|||
reset_session
|
||||
redirect_to ci_root_path
|
||||
end
|
||||
|
||||
def gl_project
|
||||
::Project.find(@project.gitlab_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ module Ci
|
|||
before_filter :project
|
||||
before_filter :authorize_access_project!, except: [:status, :show]
|
||||
before_filter :authorize_manage_project!, except: [:status, :show, :retry, :cancel]
|
||||
before_filter :authorize_project_developer!, only: [:retry, :cancel]
|
||||
before_filter :authorize_manage_builds!, only: [:retry, :cancel]
|
||||
before_filter :build, except: [:show]
|
||||
|
||||
def show
|
||||
|
|
|
@ -4,7 +4,7 @@ module Ci
|
|||
before_filter :authenticate_public_page!, only: :show
|
||||
before_filter :project
|
||||
before_filter :authorize_access_project!, except: [:status, :show, :cancel]
|
||||
before_filter :authorize_project_developer!, only: [:cancel]
|
||||
before_filter :authorize_manage_builds!, only: [:cancel]
|
||||
before_filter :commit, only: :show
|
||||
|
||||
def show
|
||||
|
|
|
@ -21,12 +21,15 @@ module Ci
|
|||
@limit, @offset = (params[:limit] || PROJECTS_BATCH).to_i, (params[:offset] || 0).to_i
|
||||
@page = @offset == 0 ? 1 : (@offset / @limit + 1)
|
||||
|
||||
current_user.reset_cache if params[:reset_cache]
|
||||
@gl_projects = current_user.authorized_projects
|
||||
@gl_projects = @gl_projects.where("name LIKE %?%", params[:search]) if params[:search]
|
||||
@gl_projects = @gl_projects.page(@page).per(@limit)
|
||||
|
||||
@gl_projects = current_user.gitlab_projects(params[:search], @page, @limit)
|
||||
@projects = Ci::Project.where(gitlab_id: @gl_projects.map(&:id)).ordered_by_last_commit_date
|
||||
@total_count = @gl_projects.size
|
||||
@gl_projects.reject! { |gl_project| @projects.map(&:gitlab_id).include?(gl_project.id) }
|
||||
|
||||
@gl_projects = @gl_projects.where.not(id: @projects.map(&:gitlab_id))
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
pager_json("ci/projects/gitlab", @total_count)
|
||||
|
@ -52,7 +55,7 @@ module Ci
|
|||
def create
|
||||
project_data = OpenStruct.new(JSON.parse(params["project"]))
|
||||
|
||||
unless current_user.can_manage_project?(project_data.id)
|
||||
unless can?(current_user, :manage_project, ::Project.find(project_data.id))
|
||||
return redirect_to ci_root_path, alert: 'You have to have at least master role to enable CI for this project'
|
||||
end
|
||||
|
||||
|
|
|
@ -10,11 +10,6 @@ module Ci
|
|||
end
|
||||
|
||||
def auth
|
||||
unless is_oauth_state_valid?(params[:state])
|
||||
redirect_to new_ci_user_sessions_path
|
||||
return
|
||||
end
|
||||
|
||||
redirect_to client.auth_code.authorize_url({
|
||||
redirect_uri: callback_ci_user_sessions_url,
|
||||
state: params[:state]
|
||||
|
@ -22,11 +17,6 @@ module Ci
|
|||
end
|
||||
|
||||
def callback
|
||||
unless is_oauth_state_valid?(params[:state])
|
||||
redirect_to new_ci_user_sessions_path
|
||||
return
|
||||
end
|
||||
|
||||
token = client.auth_code.get_token(params[:code], redirect_uri: callback_ci_user_sessions_url).token
|
||||
|
||||
@user_session = Ci::UserSession.new
|
||||
|
|
|
@ -16,7 +16,7 @@ module Ci
|
|||
end
|
||||
|
||||
def commit_link(commit)
|
||||
link_to(commit.short_sha, ci_project_ref_commit_path(commit.project, commit.ref, commit.sha))
|
||||
link_to(commit.short_sha, ci_project_ref_commits_path(commit.project, commit.ref, commit.sha))
|
||||
end
|
||||
|
||||
def truncate_first_line(message, length = 50)
|
||||
|
|
|
@ -149,6 +149,7 @@ class Ability
|
|||
:admin_merge_request,
|
||||
:create_merge_request,
|
||||
:create_wiki,
|
||||
:manage_builds,
|
||||
:push_code
|
||||
]
|
||||
end
|
||||
|
|
|
@ -39,43 +39,13 @@ module Ci
|
|||
@sync_at = Time.now
|
||||
end
|
||||
|
||||
def can_access_project?(project_gitlab_id)
|
||||
!!project_info(project_gitlab_id)
|
||||
end
|
||||
|
||||
# Indicate if user has developer access or higher
|
||||
def has_developer_access?(project_gitlab_id)
|
||||
data = project_info(project_gitlab_id)
|
||||
|
||||
return false unless data && data["permissions"]
|
||||
|
||||
permissions = data["permissions"]
|
||||
|
||||
if permissions["project_access"] && permissions["project_access"]["access_level"] >= DEVELOPER_ACCESS
|
||||
return true
|
||||
end
|
||||
|
||||
if permissions["group_access"] && permissions["group_access"]["access_level"] >= DEVELOPER_ACCESS
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
def can_manage_project?(project_gitlab_id)
|
||||
Rails.cache.fetch(cache_key('manage', project_gitlab_id, sync_at)) do
|
||||
!!Ci::Network.new.project_hooks(authenticate_options, project_gitlab_id)
|
||||
end
|
||||
end
|
||||
|
||||
def authorized_runners
|
||||
Ci::Runner.specific.includes(:runner_projects).
|
||||
where(Ci::RunnerProject.table_name => { project_id: authorized_projects } )
|
||||
end
|
||||
|
||||
def authorized_projects
|
||||
Ci::Project.where(gitlab_id: gitlab_projects.map(&:id)).select do |project|
|
||||
# This is slow: it makes request to GitLab for each project to verify manage permission
|
||||
can_manage_project?(project.gitlab_id)
|
||||
end
|
||||
Ci::Project.where(gitlab_id: current_user.authorized_projects.map(&:id))
|
||||
end
|
||||
|
||||
def authenticate_options
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#{build.coverage}%
|
||||
|
||||
%td
|
||||
- if defined?(controls) && current_user && current_user.has_developer_access?(@project.gitlab_id)
|
||||
- if defined?(controls) && current_user && can?(current_user, :manage_builds, gl_project)
|
||||
.pull-right
|
||||
- if build.active?
|
||||
= link_to cancel_ci_project_build_path(build.project, build, return_to: request.original_url), title: 'Cancel build' do
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
%h4.page-title
|
||||
= link_to @project.name, @project
|
||||
= link_to ci_project_path(@project)
|
||||
@
|
||||
= @commit.short_sha
|
||||
|
||||
%p
|
||||
= link_to ci_project_ref_commit_path(@project, @commit.ref, @commit.sha) do
|
||||
= link_to ci_project_ref_commits_path(@project, @commit.ref, @commit.sha) do
|
||||
← Back to project commit
|
||||
%hr
|
||||
#up-build-trace
|
||||
|
@ -12,7 +12,7 @@
|
|||
%ul.nav.nav-tabs.append-bottom-10
|
||||
- @commit.builds_without_retry_sorted.each do |build|
|
||||
%li{class: ('active' if build == @build) }
|
||||
= link_to ci_build_url(build) do
|
||||
= link_to ci_project_build_url(@project, build) do
|
||||
%i{class: build_icon_css_class(build)}
|
||||
%span
|
||||
Build ##{build.id}
|
||||
|
@ -84,7 +84,7 @@
|
|||
.build-widget
|
||||
%h4.title
|
||||
Build
|
||||
- if current_user && current_user.has_developer_access?(@project.gitlab_id)
|
||||
- if current_user && can?(current_user, :manage_builds, gl_project)
|
||||
.pull-right
|
||||
- if @build.active?
|
||||
= link_to "Cancel", cancel_ci_project_build_path(@project, @build), class: 'btn btn-sm btn-danger'
|
||||
|
@ -161,7 +161,7 @@
|
|||
- @builds.each_with_index do |build, i|
|
||||
%tr.build.alert{class: build_status_alert_class(build)}
|
||||
%td
|
||||
= link_to ci_build_url(build) do
|
||||
= link_to ci_project_build_url(@project, build) do
|
||||
%span ##{build.id}
|
||||
%td
|
||||
- if build.name
|
||||
|
@ -173,4 +173,4 @@
|
|||
|
||||
|
||||
:javascript
|
||||
new CiBuild("#{ci_build_url(@build)}", "#{@build.status}")
|
||||
new CiBuild("#{ci_project_build_url(@project, @build)}", "#{@build.status}")
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
|
||||
%td.build-link
|
||||
= link_to ci_project_ref_commit_path(commit.project, commit.ref, commit.sha) do
|
||||
= link_to ci_project_ref_commits_path(commit.project, commit.ref, commit.sha) do
|
||||
%strong #{commit.short_sha}
|
||||
|
||||
%td.build-message
|
||||
|
|
|
@ -33,10 +33,10 @@
|
|||
%span.attr-name Created at:
|
||||
#{@commit.created_at.to_s(:short)}
|
||||
|
||||
- if current_user && current_user.has_developer_access?(@project.gitlab_id)
|
||||
- if current_user && can?(current_user, :manage_builds, gl_project)
|
||||
.pull-right
|
||||
- if @commit.builds.running_or_pending.any?
|
||||
= link_to "Cancel", cancel_ci_project_ref_commit_path(@project, @commit.ref, @commit.sha), class: 'btn btn-sm btn-danger'
|
||||
= link_to "Cancel", cancel_ci_project_ref_commits_path(@project, @commit.ref, @commit.sha), class: 'btn btn-sm btn-danger'
|
||||
|
||||
|
||||
- if @commit.yaml_errors.present?
|
||||
|
|
|
@ -11,5 +11,5 @@
|
|||
Added
|
||||
- else
|
||||
= form_tag ci_projects_path do
|
||||
= hidden_field_tag :project, project.to_h.to_json
|
||||
= hidden_field_tag :project, project.to_json
|
||||
= submit_tag 'Add project to CI', class: 'btn btn-default btn-sm'
|
||||
|
|
|
@ -4,10 +4,6 @@
|
|||
Fetched from GitLab (#{link_to GitlabCi.config.gitlab_server.url, GitlabCi.config.gitlab_server.url, no_turbolink})
|
||||
- if params[:search].present?
|
||||
by keyword: "#{params[:search]}",
|
||||
#{time_ago_in_words(current_user.sync_at)} ago.
|
||||
= link_to gitlab_ci_projects_path(reset_cache: true, search: params[:search]), class: 'sync-now btn btn-sm btn-default reset-cache' do
|
||||
%i.fa.fa-refresh
|
||||
Sync now
|
||||
%br
|
||||
|
||||
.pull-right
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
= render 'ci/shared/guide' unless @project.setup_finished?
|
||||
|
||||
- if current_user && current_user.can_manage_project?(@project.gitlab_id) && !@project.any_runners?
|
||||
- if current_user && can?(current_user, :manage_project, gl_project) && !@project.any_runners?
|
||||
.alert.alert-danger
|
||||
Builds for this project wont be served unless you configure runners on
|
||||
= link_to "Runners page", ci_project_runners_path(@project)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
%h3
|
||||
Hi, #{@user.name}
|
||||
|
||||
- if @user.is_admin
|
||||
- if @user.is_admin?
|
||||
%span.label.label-success Admin
|
||||
|
||||
.profile-block
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
- if notice
|
||||
.alert.alert-info= notice
|
||||
|
||||
- if current_user && current_user.is_admin && Ci::Runner.count.zero?
|
||||
- if current_user && current_user.is_admin? && Ci::Runner.count.zero?
|
||||
= render 'ci/shared/no_runners'
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
.collapse.navbar-collapse
|
||||
%ul.nav.navbar-nav
|
||||
- if current_user && current_user.is_admin
|
||||
- if current_user && current_user.is_admin?
|
||||
%li
|
||||
= link_to ci_admin_projects_path do
|
||||
Admin
|
||||
|
@ -19,12 +19,12 @@
|
|||
%ul.nav.navbar-nav.pull-right
|
||||
- if current_user
|
||||
%li
|
||||
= link_to ci_user_sessions_path do
|
||||
= link_to new_user_session_path do
|
||||
.profile-holder
|
||||
= image_tag user_avatar_url(current_user, 64), class: 'avatar s32', alt: ''
|
||||
%span= current_user.name
|
||||
%li
|
||||
= link_to ci_user_sessions_path, class: "logout", method: :delete do
|
||||
= link_to destroy_user_session_path, class: "logout", method: :delete do
|
||||
%i.fa.fa-signout
|
||||
Logout
|
||||
- else
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
= link_to 'View on GitLab', @project.gitlab_url, no_turbolink.merge( class: 'btn btn-sm' )
|
||||
%hr
|
||||
.container
|
||||
- if current_user && current_user.can_manage_project?(@project.gitlab_id)
|
||||
- if current_user && can?(current_user, :manage_project, gl_project)
|
||||
.row
|
||||
.col-md-2.append-bottom-20
|
||||
= render 'layouts/ci/nav_project'
|
||||
|
|
|
@ -66,7 +66,7 @@ module Ci
|
|||
get ":id" do
|
||||
project = Ci::Project.find(params[:id])
|
||||
|
||||
unauthorized! unless current_user.can_access_project?(project.gitlab_id)
|
||||
unauthorized! unless can?(current_user, :read_project, gl_project)
|
||||
|
||||
present project, with: Entities::Project
|
||||
end
|
||||
|
@ -118,7 +118,7 @@ module Ci
|
|||
put ":id" do
|
||||
project = Ci::Project.find(params[:id])
|
||||
|
||||
unauthorized! unless current_user.can_manage_project?(project.gitlab_id)
|
||||
unauthorized! unless can?(current_user, :manage_project, gl_project)
|
||||
|
||||
attrs = attributes_for_keys [:name, :gitlab_id, :path, :gitlab_url, :default_ref, :ssh_url_to_repo]
|
||||
|
||||
|
@ -144,7 +144,7 @@ module Ci
|
|||
delete ":id" do
|
||||
project = Ci::Project.find(params[:id])
|
||||
|
||||
unauthorized! unless current_user.can_manage_project?(project.gitlab_id)
|
||||
unauthorized! unless can?(current_user, :manage_project, gl_project)
|
||||
|
||||
project.destroy
|
||||
end
|
||||
|
@ -160,7 +160,7 @@ module Ci
|
|||
project = Ci::Project.find(params[:id])
|
||||
runner = Ci::Runner.find(params[:runner_id])
|
||||
|
||||
unauthorized! unless current_user.can_manage_project?(project.gitlab_id)
|
||||
unauthorized! unless can?(current_user, :manage_project, gl_project)
|
||||
|
||||
options = {
|
||||
project_id: project.id,
|
||||
|
@ -188,7 +188,7 @@ module Ci
|
|||
project = Ci::Project.find(params[:id])
|
||||
runner = Ci::Runner.find(params[:runner_id])
|
||||
|
||||
unauthorized! unless current_user.can_manage_project?(project.gitlab_id)
|
||||
unauthorized! unless can?(current_user, :manage_project, gl_project)
|
||||
|
||||
options = {
|
||||
project_id: project.id,
|
||||
|
|
|
@ -2,56 +2,6 @@ require 'spec_helper'
|
|||
|
||||
describe Ci::User do
|
||||
|
||||
describe "has_developer_access?" do
|
||||
before do
|
||||
@user = User.new({})
|
||||
end
|
||||
|
||||
let(:project_with_owner_access) do
|
||||
{
|
||||
"name" => "gitlab-shell",
|
||||
"permissions" => {
|
||||
"project_access" => {
|
||||
"access_level"=> 10,
|
||||
"notification_level" => 3
|
||||
},
|
||||
"group_access" => {
|
||||
"access_level" => 50,
|
||||
"notification_level" => 3
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
let(:project_with_reporter_access) do
|
||||
{
|
||||
"name" => "gitlab-shell",
|
||||
"permissions" => {
|
||||
"project_access" => {
|
||||
"access_level" => 20,
|
||||
"notification_level" => 3
|
||||
},
|
||||
"group_access" => {
|
||||
"access_level" => 10,
|
||||
"notification_level" => 3
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it "returns false for reporter" do
|
||||
@user.stub(:project_info).and_return(project_with_reporter_access)
|
||||
|
||||
@user.has_developer_access?(1).should be_false
|
||||
end
|
||||
|
||||
it "returns true for owner" do
|
||||
@user.stub(:project_info).and_return(project_with_owner_access)
|
||||
|
||||
@user.has_developer_access?(1).should be_true
|
||||
end
|
||||
end
|
||||
|
||||
describe "authorized_projects" do
|
||||
let (:user) { User.new({}) }
|
||||
|
||||
|
|
Loading…
Reference in a new issue