Skip to content
Snippets Groups Projects
Commit 148816cd authored by Bob Van Landuyt's avatar Bob Van Landuyt
Browse files

Port `read_cross_project` ability from EE

parent b5306075
No related branches found
No related tags found
No related merge requests found
Showing
with 310 additions and 188 deletions
Loading
Loading
@@ -159,7 +159,18 @@ class Issue < ActiveRecord::Base
object.all_references(current_user, extractor: ext)
end
 
ext.merge_requests.sort_by(&:iid)
merge_requests = ext.merge_requests.sort_by(&:iid)
cross_project_filter = -> (merge_requests) do
merge_requests.select { |mr| mr.target_project == project }
end
Ability.merge_requests_readable_by_user(
merge_requests, current_user,
filters: {
read_cross_project: cross_project_filter
}
)
end
 
# All branches containing the current issue's ID, except for
Loading
Loading
Loading
Loading
@@ -85,6 +85,7 @@ class NotificationRecipient
return false unless user.can?(:receive_notifications)
return true if @skip_read_ability
 
return false if @target && !user.can?(:read_cross_project)
return false if @project && !user.can?(:read_project, @project)
 
return true unless read_ability
Loading
Loading
Loading
Loading
@@ -1036,6 +1036,9 @@ class Project < ActiveRecord::Base
end
 
def user_can_push_to_empty_repo?(user)
return false unless empty_repo?
return false unless Ability.allowed?(user, :push_code, self)
!ProtectedBranch.default_branch_protected? || team.max_member_access(user.id) > Gitlab::Access::DEVELOPER
end
 
Loading
Loading
Loading
Loading
@@ -15,4 +15,7 @@ class BasePolicy < DeclarativePolicy::Base
condition(:restricted_public_level, scope: :global) do
Gitlab::CurrentSettings.current_application_settings.restricted_visibility_levels.include?(Gitlab::VisibilityLevel::PUBLIC)
end
# This is prevented in some cases in `gitlab-ee`
rule { default }.enable :read_cross_project
end
Loading
Loading
@@ -3,6 +3,19 @@ class IssuablePolicy < BasePolicy
 
condition(:locked, scope: :subject, score: 0) { @subject.discussion_locked? }
 
# We aren't checking `:read_issue` or `:read_merge_request` in this case
# because it could be possible for a user to see an issuable-iid
# (`:read_issue_iid` or `:read_merge_request_iid`) but then wouldn't be allowed
# to read the actual issue after a more expensive `:read_issue` check.
#
# `:read_issue` & `:read_issue_iid` could diverge in gitlab-ee.
condition(:visible_to_user, score: 4) do
Project.where(id: @subject.project)
.public_or_visible_to_user(@user)
.with_feature_available_for_user(@subject, @user)
.any?
end
condition(:is_project_member) { @user && @subject.project && @subject.project.team.member?(@user) }
 
desc "User is the assignee or author"
Loading
Loading
Loading
Loading
@@ -13,7 +13,10 @@ class IssuePolicy < IssuablePolicy
 
rule { confidential & ~can_read_confidential }.policy do
prevent :read_issue
prevent :read_issue_iid
prevent :update_issue
prevent :admin_issue
end
rule { can?(:read_issue) | visible_to_user }.enable :read_issue_iid
end
class MergeRequestPolicy < IssuablePolicy
# pass
rule { can?(:read_merge_request) | visible_to_user }.enable :read_merge_request_iid
end
Loading
Loading
@@ -80,8 +80,9 @@ class ProjectPolicy < BasePolicy
rule { reporter }.enable :reporter_access
rule { developer }.enable :developer_access
rule { master }.enable :master_access
rule { owner | admin }.enable :owner_access
 
rule { owner | admin }.policy do
rule { can?(:owner_access) }.policy do
enable :guest_access
enable :reporter_access
enable :developer_access
Loading
Loading
@@ -98,11 +99,6 @@ class ProjectPolicy < BasePolicy
enable :remove_pages
end
 
rule { owner | reporter }.policy do
enable :build_download_code
enable :build_read_container_image
end
rule { can?(:guest_access) }.policy do
enable :read_project
enable :read_board
Loading
Loading
@@ -121,6 +117,11 @@ class ProjectPolicy < BasePolicy
enable :read_cycle_analytics
end
 
# These abilities are not allowed to admins that are not members of the project,
# that's why they are defined separatly.
rule { guest & can?(:download_code) }.enable :build_download_code
rule { guest & can?(:read_container_image) }.enable :build_read_container_image
rule { can?(:reporter_access) }.policy do
enable :download_code
enable :download_wiki_code
Loading
Loading
@@ -140,12 +141,19 @@ class ProjectPolicy < BasePolicy
enable :read_merge_request
end
 
# We define `:public_user_access` separately because there are cases in gitlab-ee
# where we enable or prevent it based on other coditions.
rule { (~anonymous & public_project) | internal_access }.policy do
enable :public_user_access
end
 
rule { can?(:public_user_access) }.policy do
enable :public_access
enable :guest_access
enable :fork_project
enable :build_download_code
enable :build_read_container_image
enable :request_access
end
 
Loading
Loading
@@ -196,14 +204,6 @@ class ProjectPolicy < BasePolicy
enable :create_cluster
end
 
rule { can?(:public_user_access) }.policy do
enable :public_access
enable :fork_project
enable :build_download_code
enable :build_read_container_image
end
rule { archived }.policy do
prevent :create_merge_request
prevent :push_code
Loading
Loading
Loading
Loading
@@ -11,9 +11,7 @@ class GroupChildEntity < Grape::Entity
end
 
expose :can_edit do |instance|
return false unless request.respond_to?(:current_user)
can?(request.current_user, "admin_#{type}", instance)
can_edit?
end
 
expose :edit_path do |instance|
Loading
Loading
@@ -83,4 +81,17 @@ class GroupChildEntity < Grape::Entity
def markdown_description
markdown_field(object, :description)
end
def can_edit?
return false unless request.respond_to?(:current_user)
if project?
# Avoid checking rights for each project, as it might be expensive if the
# user cannot read cross project.
can?(request.current_user, :read_cross_project) &&
can?(request.current_user, :admin_project, object)
else
can?(request.current_user, :admin_group, object)
end
end
end
Loading
Loading
@@ -247,7 +247,7 @@ class IssuableBaseService < BaseService
when 'add'
todo_service.mark_todo(issuable, current_user)
when 'done'
todo = TodosFinder.new(current_user).execute.find_by(target: issuable)
todo = TodosFinder.new(current_user).find_by(target: issuable)
todo_service.mark_todos_as_done_by_ids(todo, current_user) if todo
end
end
Loading
Loading
- message = local_assigns.fetch(:message)
- content_for(:title, 'Access Denied')
%img{ :alt => "GitLab Logo", :src => image_path('logo.svg') }
%h1
Loading
Loading
@@ -5,5 +7,9 @@
.container
%h3 Access Denied
%hr
%p You are not allowed to access this page.
%p Read more about project permissions #{link_to "here", help_page_path("user/permissions"), class: "vlink"}
- if message
%p
= message
- else
%p You are not allowed to access this page.
%p Read more about project permissions #{link_to "here", help_page_path("user/permissions"), class: "vlink"}
Loading
Loading
@@ -20,29 +20,34 @@
%ul.nav.navbar-nav
- if current_user
= render 'layouts/header/new_dropdown'
%li.hidden-sm.hidden-xs
= render 'layouts/search' unless current_controller?(:search)
%li.visible-sm-inline-block.visible-xs-inline-block
= link_to search_path, title: 'Search', aria: { label: "Search" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('search', size: 16)
- if current_user
- if header_link?(:search)
%li.hidden-sm.hidden-xs
= render 'layouts/search' unless current_controller?(:search)
%li.visible-sm-inline-block.visible-xs-inline-block
= link_to search_path, title: 'Search', aria: { label: "Search" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('search', size: 16)
- if header_link?(:issues)
= nav_link(path: 'dashboard#issues', html_options: { class: "user-counter" }) do
= link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues', aria: { label: "Issues" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('issues', size: 16)
- issues_count = assigned_issuables_count(:issues)
%span.badge.issues-count{ class: ('hidden' if issues_count.zero?) }
= number_with_delimiter(issues_count)
- if header_link?(:merge_requests)
= nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter" }) do
= link_to assigned_mrs_dashboard_path, title: 'Merge requests', class: 'dashboard-shortcuts-merge_requests', aria: { label: "Merge requests" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('git-merge', size: 16)
- merge_requests_count = assigned_issuables_count(:merge_requests)
%span.badge.merge-requests-count{ class: ('hidden' if merge_requests_count.zero?) }
= number_with_delimiter(merge_requests_count)
- if header_link?(:todos)
= nav_link(controller: 'dashboard/todos', html_options: { class: "user-counter" }) do
= link_to dashboard_todos_path, title: 'Todos', aria: { label: "Todos" }, class: 'shortcuts-todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= sprite_icon('todo-done', size: 16)
%span.badge.todos-count{ class: ('hidden' if todos_pending_count.zero?) }
= todos_count_format(todos_pending_count)
- if header_link?(:user_dropdown)
%li.header-user.dropdown
= link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
= image_tag avatar_icon_for_user(current_user, 23), width: 23, height: 23, class: "header-user-avatar qa-user-avatar"
Loading
Loading
@@ -64,11 +69,11 @@
%li.divider
%li
= link_to "Sign out", destroy_user_session_path, class: "sign-out-link"
- if session[:impersonator_id]
%li.impersonation
= link_to admin_impersonation_path, class: 'impersonation-btn', method: :delete, title: "Stop impersonation", aria: { label: 'Stop impersonation' }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= icon('user-secret')
- else
- if header_link?(:admin_impersonation)
%li.impersonation
= link_to admin_impersonation_path, class: 'impersonation-btn', method: :delete, title: "Stop impersonation", aria: { label: 'Stop impersonation' }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= icon('user-secret')
- if header_link?(:sign_in)
%li
%div
= link_to "Sign in / Register", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in'
Loading
Loading
%ul.list-unstyled.navbar-sub-nav
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects qa-projects-dropdown" }) do
%a{ href: "#", data: { toggle: "dropdown" } }
Projects
= sprite_icon('angle-down', css_class: 'caret-down')
.dropdown-menu.projects-dropdown-menu
= render "layouts/nav/projects_dropdown/show"
- if dashboard_nav_link?(:projects)
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects qa-projects-dropdown" }) do
%a{ href: "#", data: { toggle: "dropdown" } }
Projects
= sprite_icon('angle-down', css_class: 'caret-down')
.dropdown-menu.projects-dropdown-menu
= render "layouts/nav/projects_dropdown/show"
 
= nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { class: "hidden-xs" }) do
= link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups qa-groups-link', title: 'Groups' do
Groups
- if dashboard_nav_link?(:groups)
= nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { class: "hidden-xs" }) do
= link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups qa-groups-link', title: 'Groups' do
Groups
 
= nav_link(path: 'dashboard#activity', html_options: { class: "visible-lg" }) do
= link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
Activity
- if dashboard_nav_link?(:activity)
= nav_link(path: 'dashboard#activity', html_options: { class: "visible-lg" }) do
= link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
Activity
 
= nav_link(controller: 'dashboard/milestones', html_options: { class: "visible-lg" }) do
= link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', title: 'Milestones' do
Milestones
- if dashboard_nav_link?(:milestones)
= nav_link(controller: 'dashboard/milestones', html_options: { class: "visible-lg" }) do
= link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', title: 'Milestones' do
Milestones
 
= nav_link(controller: 'dashboard/snippets', html_options: { class: "visible-lg" }) do
= link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', title: 'Snippets' do
Snippets
- if dashboard_nav_link?(:snippets)
= nav_link(controller: 'dashboard/snippets', html_options: { class: "visible-lg" }) do
= link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', title: 'Snippets' do
Snippets
 
%li.header-more.dropdown.hidden-lg
%a{ href: "#", data: { toggle: "dropdown" } }
More
= sprite_icon('angle-down', css_class: 'caret-down')
.dropdown-menu
%ul
= nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { class: "visible-xs" }) do
= link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', title: 'Groups' do
Groups
- if any_dashboard_nav_link?([:groups, :milestones, :activity, :snippets])
%li.header-more.dropdown.hidden-lg
%a{ href: "#", data: { toggle: "dropdown" } }
More
= sprite_icon('angle-down', css_class: 'caret-down')
.dropdown-menu
%ul
- if dashboard_nav_link?(:groups)
= nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { class: "visible-xs" }) do
= link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', title: 'Groups' do
Groups
 
= nav_link(path: 'dashboard#activity') do
= link_to activity_dashboard_path, title: 'Activity' do
Activity
- if dashboard_nav_link?(:activity)
= nav_link(path: 'dashboard#activity') do
= link_to activity_dashboard_path, title: 'Activity' do
Activity
 
= nav_link(controller: 'dashboard/milestones') do
= link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', title: 'Milestones' do
Milestones
- if dashboard_nav_link?(:milestones)
= nav_link(controller: 'dashboard/milestones') do
= link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', title: 'Milestones' do
Milestones
 
= nav_link(controller: 'dashboard/snippets') do
= link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', title: 'Snippets' do
Snippets
- if dashboard_nav_link?(:snippets)
= nav_link(controller: 'dashboard/snippets') do
= link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', title: 'Snippets' do
Snippets
 
-# Shortcut to Dashboard > Projects
%li.hidden
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
Projects
- if dashboard_nav_link?(:projects)
%li.hidden
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
Projects
 
- if current_controller?('ide')
%li.line-separator.hidden-xs
Loading
Loading
%ul.list-unstyled.navbar-sub-nav
= nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do
= link_to explore_root_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
Projects
= nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
= link_to explore_groups_path, title: 'Groups', class: 'dashboard-shortcuts-groups' do
Groups
= nav_link(controller: :snippets) do
= link_to explore_snippets_path, title: 'Snippets', class: 'dashboard-shortcuts-snippets' do
Snippets
- if explore_nav_link?(:projects)
= nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do
= link_to explore_root_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
Projects
- if explore_nav_link?(:groups)
= nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
= link_to explore_groups_path, title: 'Groups', class: 'dashboard-shortcuts-groups' do
Groups
- if explore_nav_link?(:snippets)
= nav_link(controller: :snippets) do
= link_to explore_snippets_path, title: 'Snippets', class: 'dashboard-shortcuts-snippets' do
Snippets
%li
= link_to "Help", help_path, title: 'About GitLab CE'
- issues_count = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute.count
- merge_requests_count = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened', non_archived: true).execute.count
 
- issues_sub_menu_items = ['groups#issues', 'labels#index', 'milestones#index']
.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?) }
.nav-sidebar-inner-scroll
.context-header
Loading
Loading
@@ -10,84 +12,93 @@
.sidebar-context-title
= @group.name
%ul.sidebar-top-level-items
= nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups'], html_options: { class: 'home' }) do
= link_to group_path(@group) do
.nav-icon-container
= sprite_icon('project')
%span.nav-item-name
Overview
- if group_sidebar_link?(:overview)
= nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups', 'analytics#show'], html_options: { class: 'home' }) do
= link_to group_path(@group) do
.nav-icon-container
= sprite_icon('project')
%span.nav-item-name
Overview
 
%ul.sidebar-sub-level-items
= nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups'], html_options: { class: "fly-out-top-item" } ) do
= link_to group_path(@group) do
%strong.fly-out-top-item-name
#{ _('Overview') }
%li.divider.fly-out-top-item
= nav_link(path: ['groups#show', 'groups#subgroups'], html_options: { class: 'home' }) do
= link_to group_path(@group), title: 'Group details' do
%span
Details
%ul.sidebar-sub-level-items
= nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups'], html_options: { class: "fly-out-top-item" } ) do
= link_to group_path(@group) do
%strong.fly-out-top-item-name
#{ _('Overview') }
%li.divider.fly-out-top-item
= nav_link(path: ['groups#show', 'groups#subgroups'], html_options: { class: 'home' }) do
= link_to group_path(@group), title: 'Group details' do
%span
Details
 
= nav_link(path: 'groups#activity') do
= link_to activity_group_path(@group), title: 'Activity' do
%span
Activity
- if group_sidebar_link?(:activity)
= nav_link(path: 'groups#activity') do
= link_to activity_group_path(@group), title: 'Activity' do
%span
Activity
 
= nav_link(path: ['groups#issues', 'labels#index', 'milestones#index']) do
= link_to issues_group_path(@group) do
.nav-icon-container
= sprite_icon('issues')
%span.nav-item-name
Issues
%span.badge.count= number_with_delimiter(issues_count)
- if group_sidebar_link?(:issues)
= nav_link(path: issues_sub_menu_items) do
= link_to issues_group_path(@group) do
.nav-icon-container
= sprite_icon('issues')
%span.nav-item-name
Issues
%span.badge.count= number_with_delimiter(issues_count)
 
%ul.sidebar-sub-level-items
= nav_link(path: ['groups#issues', 'labels#index', 'milestones#index'], html_options: { class: "fly-out-top-item" } ) do
= link_to issues_group_path(@group) do
%strong.fly-out-top-item-name
#{ _('Issues') }
%span.badge.count.issue_counter.fly-out-badge= number_with_delimiter(issues_count)
%li.divider.fly-out-top-item
= nav_link(path: 'groups#issues', html_options: { class: 'home' }) do
= link_to issues_group_path(@group), title: 'List' do
%span
List
%ul.sidebar-sub-level-items
= nav_link(path: ['groups#issues', 'labels#index', 'milestones#index'], html_options: { class: "fly-out-top-item" } ) do
= link_to issues_group_path(@group) do
%strong.fly-out-top-item-name
#{ _('Issues') }
%span.badge.count.issue_counter.fly-out-badge= number_with_delimiter(issues_count)
%li.divider.fly-out-top-item
= nav_link(path: 'groups#issues', html_options: { class: 'home' }) do
= link_to issues_group_path(@group), title: 'List' do
%span
List
- if group_sidebar_link?(:labels)
= nav_link(path: 'labels#index') do
= link_to group_labels_path(@group), title: 'Labels' do
%span
Labels
 
= nav_link(path: 'labels#index') do
= link_to group_labels_path(@group), title: 'Labels' do
%span
Labels
- if group_sidebar_link?(:milestones)
= nav_link(path: 'milestones#index') do
= link_to group_milestones_path(@group), title: 'Milestones' do
%span
Milestones
- if group_sidebar_link?(:merge_requests)
= nav_link(path: 'groups#merge_requests') do
= link_to merge_requests_group_path(@group) do
.nav-icon-container
= sprite_icon('git-merge')
%span.nav-item-name
Merge Requests
%span.badge.count= number_with_delimiter(merge_requests_count)
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(path: 'groups#merge_requests', html_options: { class: "fly-out-top-item" } ) do
= link_to merge_requests_group_path(@group) do
%strong.fly-out-top-item-name
#{ _('Merge Requests') }
%span.badge.count.merge_counter.js-merge-counter.fly-out-badge= number_with_delimiter(merge_requests_count)
 
= nav_link(path: 'milestones#index') do
= link_to group_milestones_path(@group), title: 'Milestones' do
%span
Milestones
- if group_sidebar_link?(:group_members)
= nav_link(path: 'group_members#index') do
= link_to group_group_members_path(@group) do
.nav-icon-container
= sprite_icon('users')
%span.nav-item-name
Members
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(path: 'group_members#index', html_options: { class: "fly-out-top-item" } ) do
= link_to group_group_members_path(@group) do
%strong.fly-out-top-item-name
#{ _('Members') }
 
= nav_link(path: 'groups#merge_requests') do
= link_to merge_requests_group_path(@group) do
.nav-icon-container
= sprite_icon('git-merge')
%span.nav-item-name
Merge Requests
%span.badge.count= number_with_delimiter(merge_requests_count)
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(path: 'groups#merge_requests', html_options: { class: "fly-out-top-item" } ) do
= link_to merge_requests_group_path(@group) do
%strong.fly-out-top-item-name
#{ _('Merge Requests') }
%span.badge.count.merge_counter.js-merge-counter.fly-out-badge= number_with_delimiter(merge_requests_count)
= nav_link(path: 'group_members#index') do
= link_to group_group_members_path(@group) do
.nav-icon-container
= sprite_icon('users')
%span.nav-item-name
Members
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(path: 'group_members#index', html_options: { class: "fly-out-top-item" } ) do
= link_to group_group_members_path(@group) do
%strong.fly-out-top-item-name
#{ _('Members') }
- if current_user && can?(current_user, :admin_group, @group)
- if group_sidebar_link?(:settings)
= nav_link(path: group_nav_link_paths) do
= link_to edit_group_path(@group) do
.nav-icon-container
Loading
Loading
Loading
Loading
@@ -6,7 +6,7 @@
- user = local_assigns[:user]
- access = user&.max_member_access_for_project(project.id) unless user.nil?
- css_class = '' unless local_assigns[:css_class]
- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true && project.commit
- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true && can_show_last_commit_in_list?(project)
- css_class += " no-description" if project.description.blank? && !show_last_commit_as_description
- cache_key = project_list_cache_key(project)
- updated_tooltip = time_ago_with_tooltip(project.last_activity_date)
Loading
Loading
@@ -47,7 +47,7 @@
.prepend-top-0
- if project.archived
%span.prepend-left-10.label.label-warning archived
- if project.pipeline_status.has_status?
- if can?(current_user, :read_cross_project) && project.pipeline_status.has_status?
%span.prepend-left-10
= render_project_pipeline_status(project.pipeline_status)
- if forks
Loading
Loading
Loading
Loading
@@ -82,47 +82,58 @@
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
%ul.nav-links.user-profile-nav.scrolling-tabs
%li.js-activity-tab
= link_to user_path, data: { target: 'div#activity', action: 'activity', toggle: 'tab' } do
Activity
%li.js-groups-tab
= link_to user_groups_path, data: { target: 'div#groups', action: 'groups', toggle: 'tab', endpoint: user_groups_path(format: :json) } do
Groups
%li.js-contributed-tab
= link_to user_contributed_projects_path, data: { target: 'div#contributed', action: 'contributed', toggle: 'tab', endpoint: user_contributed_projects_path(format: :json) } do
Contributed projects
%li.js-projects-tab
= link_to user_projects_path, data: { target: 'div#projects', action: 'projects', toggle: 'tab', endpoint: user_projects_path(format: :json) } do
Personal projects
%li.js-snippets-tab
= link_to user_snippets_path, data: { target: 'div#snippets', action: 'snippets', toggle: 'tab', endpoint: user_snippets_path(format: :json) } do
Snippets
- if profile_tab?(:activity)
%li.js-activity-tab
= link_to user_path, data: { target: 'div#activity', action: 'activity', toggle: 'tab' } do
Activity
- if profile_tab?(:groups)
%li.js-groups-tab
= link_to user_groups_path, data: { target: 'div#groups', action: 'groups', toggle: 'tab', endpoint: user_groups_path(format: :json) } do
Groups
- if profile_tab?(:contributed)
%li.js-contributed-tab
= link_to user_contributed_projects_path, data: { target: 'div#contributed', action: 'contributed', toggle: 'tab', endpoint: user_contributed_projects_path(format: :json) } do
Contributed projects
- if profile_tab?(:projects)
%li.js-projects-tab
= link_to user_projects_path, data: { target: 'div#projects', action: 'projects', toggle: 'tab', endpoint: user_projects_path(format: :json) } do
Personal projects
- if profile_tab?(:snippets)
%li.js-snippets-tab
= link_to user_snippets_path, data: { target: 'div#snippets', action: 'snippets', toggle: 'tab', endpoint: user_snippets_path(format: :json) } do
Snippets
 
%div{ class: container_class }
.tab-content
#activity.tab-pane
.row-content-block.calender-block.white.second-block.hidden-xs
.user-calendar{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
%h4.center.light
%i.fa.fa-spinner.fa-spin
.user-calendar-activities
- if profile_tab?(:activity)
#activity.tab-pane
.row-content-block.calender-block.white.second-block.hidden-xs
.user-calendar{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
%h4.center.light
%i.fa.fa-spinner.fa-spin
.user-calendar-activities
 
%h4.prepend-top-20
Most Recent Activity
.content_list{ data: { href: user_path } }
= spinner
- if can?(current_user, :read_cross_project)
%h4.prepend-top-20
Most Recent Activity
.content_list{ data: { href: user_path } }
= spinner
 
#groups.tab-pane
-# This tab is always loaded via AJAX
- if profile_tab?(:groups)
#groups.tab-pane
-# This tab is always loaded via AJAX
 
#contributed.tab-pane
-# This tab is always loaded via AJAX
- if profile_tab?(:contributed)
#contributed.tab-pane
-# This tab is always loaded via AJAX
 
#projects.tab-pane
-# This tab is always loaded via AJAX
- if profile_tab?(:projects)
#projects.tab-pane
-# This tab is always loaded via AJAX
 
#snippets.tab-pane
-# This tab is always loaded via AJAX
- if profile_tab?(:snippets)
#snippets.tab-pane
-# This tab is always loaded via AJAX
 
.loading-status
= spinner
---
title: Authorize project access with an external service
merge_request: 4675
author:
type: added
# This module is based on: https://gist.github.com/bcardarella/5735987
module Prependable
def prepend_features(base)
if base.instance_variable_defined?(:@_dependencies)
base.instance_variable_get(:@_dependencies) << self
false
else
return false if base < self
super
base.singleton_class.send(:prepend, const_get('ClassMethods')) if const_defined?(:ClassMethods)
@_dependencies.each { |dep| base.send(:prepend, dep) } # rubocop:disable Gitlab/ModuleWithInstanceVariables
base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block) # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
end
end
module ActiveSupport
module Concern
prepend Prependable
alias_method :prepended, :included
end
end
Loading
Loading
@@ -172,7 +172,7 @@ module API
 
def find_project_snippet(id)
finder_params = { project: user_project }
SnippetsFinder.new(current_user, finder_params).execute.find(id)
SnippetsFinder.new(current_user, finder_params).find(id)
end
 
def find_merge_request_with_access(iid, access_level = :read_merge_request)
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment