Skip to content
Snippets Groups Projects
Commit 515205d3 authored by Rémy Coutable's avatar Rémy Coutable
Browse files

UI and copywriting improvements


+ Move 'Edit Project/Group' out of membership-related partial
+ Show the access request buttons only to logged-in users
+ Put the request access buttons out of in a more visible button
+ Improve the copy in the #remove_member_message helper

Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent 6d103a2f
No related branches found
No related tags found
No related merge requests found
Showing
with 282 additions and 350 deletions
Loading
Loading
@@ -39,3 +39,20 @@
}
}
}
.groups-cover-block {
.container-fluid {
position: relative;
}
.access-request-button {
@include btn-gray;
position: absolute;
right: 16px;
bottom: 32px;
padding: 3px 10px;
text-transform: none;
background-color: $background-color;
}
}
Loading
Loading
@@ -229,13 +229,20 @@
right: 16px;
bottom: 0;
 
.btn {
padding: 3px 10px;
background-color: $background-color;
@media (max-width: $screen-lg-min) {
top: 0;
}
 
@media (max-width: 1304px) {
top: 0;
.access-request-button {
position: absolute;
right: 0;
bottom: 61px;
@media (max-width: $screen-lg-min) {
position: relative;
bottom: 0;
margin-right: 10px;
}
}
}
 
Loading
Loading
module AccessRequestActions
extend ActiveSupport::Concern
def request_access
access_requestable_resource.request_access(current_user)
redirect_to access_requestable_resource_path,
notice: 'Your request for access has been queued for review.'
end
def approve_access_request
@member = access_requestable_resource.public_send(member_entity_name.pluralize).request.find(params[:id])
return render_403 unless can?(current_user, :"update_#{member_entity_name}", @member)
@member.accept_request
redirect_to access_requestable_resource_members_path
end
protected
def access_requestable_resource
raise NotImplementedError
end
def access_requestable_resource_path
access_requestable_resource
end
def access_requestable_resource_members_path
[access_requestable_resource, 'members']
end
def member_entity_name
"#{access_requestable_resource.class.to_s.underscore}_member"
end
end
module MembershipActions
extend ActiveSupport::Concern
include MembersHelper
def request_access
membershipable.request_access(current_user)
redirect_to polymorphic_path(membershipable),
notice: 'Your request for access has been queued for review.'
end
def approve_access_request
@member = membershipable.members.request.find(params[:id])
return render_403 unless can?(current_user, action_member_permission(:update, @member), @member)
@member.accept_request
redirect_to polymorphic_url([membershipable, :members])
end
def leave
@member = membershipable.members.find_by(user_id: current_user)
return render_403 unless @member
source_type = @member.real_source_type.humanize(capitalize: false)
if can?(current_user, action_member_permission(:destroy, @member), @member)
notice =
if @member.request?
"Your access request to the #{source_type} has been withdrawn."
else
"You left the \"#{@member.source.human_name}\" #{source_type}."
end
@member.destroy
redirect_to [:dashboard, @member.real_source_type.tableize], notice: notice
else
if cannot_leave?
alert = "You can not leave the \"#{@member.source.human_name}\" #{source_type}."
alert << " Transfer or delete the #{source_type}."
redirect_to polymorphic_url(membershipable), alert: alert
else
render_403
end
end
end
protected
def membershipable
raise NotImplementedError
end
def cannot_leave?
raise NotImplementedError
end
end
class Groups::GroupMembersController < Groups::ApplicationController
include AccessRequestActions
include MembershipActions
 
# Authorize
before_action :authorize_admin_group_member!, except: [:index, :leave, :request_access]
Loading
Loading
@@ -38,7 +38,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
 
return render_403 unless can?(current_user, :destroy_group_member, @group_member)
 
@group_member.request? ? @group_member.decline_request : @group_member.destroy
@group_member.destroy
 
respond_to do |format|
format.html { redirect_to group_group_members_path(@group), notice: 'User was successfully removed from group.' }
Loading
Loading
@@ -60,46 +60,16 @@ class Groups::GroupMembersController < Groups::ApplicationController
end
end
 
def leave
@group_member =
@group.group_members.find_by(user_id: current_user.id) ||
@group.group_members.find_by(created_by_id: current_user.id)
if can?(current_user, :destroy_group_member, @group_member)
notice =
if @group_member.request?
'You withdrawn your access request to the group.'
else
"You left #{@group.name} group."
end
@group_member.destroy
redirect_to dashboard_groups_path, notice: notice
else
if @group.last_owner?(current_user)
redirect_to(dashboard_groups_path, alert: "You can not leave #{group.name} group because you're the last owner. Transfer or delete the group.")
else
return render_403
end
end
end
protected
 
def member_params
params.require(:group_member).permit(:access_level, :user_id)
end
 
# AccessRequestActions concern
def access_requestable_resource
@group
end
def access_requestable_resource_path
group_path(@group)
end
# MembershipActions concern
alias_method :membershipable, :group
 
def access_requestable_resource_members_path
group_group_members_path(@group)
def cannot_leave?
@group.last_owner?(current_user)
end
end
class Projects::ProjectMembersController < Projects::ApplicationController
include AccessRequestActions
include MembershipActions
 
# Authorize
before_action :authorize_admin_project_member!, except: [:index, :leave, :request_access]
Loading
Loading
@@ -52,7 +52,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
 
return render_403 unless can?(current_user, :destroy_project_member, @project_member)
 
@project_member.request? ? @project_member.decline_request : @project_member.destroy
@project_member.destroy
 
respond_to do |format|
format.html do
Loading
Loading
@@ -76,31 +76,6 @@ class Projects::ProjectMembersController < Projects::ApplicationController
end
end
 
def leave
@project_member =
@project.project_members.find_by(user_id: current_user.id) ||
@project.project_members.find_by(created_by_id: current_user.id)
if can?(current_user, :destroy_project_member, @project_member)
notice =
if @project_member.request?
'You withdrawn your access request to the project.'
else
'You left the project.'
end
@project_member.destroy
redirect_to dashboard_projects_path, notice: notice
else
if current_user == @project.owner
message = 'You can not leave your own project. Transfer or delete the project.'
redirect_back_or_default(default: { action: 'index' }, options: { alert: message })
else
render_403
end
end
end
def apply_import
source_project = Project.find(params[:source_project_id])
 
Loading
Loading
@@ -121,16 +96,10 @@ class Projects::ProjectMembersController < Projects::ApplicationController
params.require(:project_member).permit(:user_id, :access_level)
end
 
# AccessRequestActions concern
def access_requestable_resource
@project
end
def access_requestable_resource_path
namespace_project_path(@project.namespace, @project)
end
# MembershipActions concern
alias_method :membershipable, :project
 
def access_requestable_resource_members_path
namespace_project_project_members_path(@project.namespace, @project)
def cannot_leave?
current_user == @project.owner
end
end
Loading
Loading
@@ -13,10 +13,23 @@
# merge_request_path(merge_request)
#
module GitlabRoutingHelper
# Project
def project_path(project, *args)
namespace_project_path(project.namespace, project, *args)
end
 
def project_url(project, *args)
namespace_project_url(project.namespace, project, *args)
end
def edit_project_path(project, *args)
edit_namespace_project_path(project.namespace, project, *args)
end
def edit_project_url(project, *args)
edit_namespace_project_url(project.namespace, project, *args)
end
def project_files_path(project, *args)
namespace_project_tree_path(project.namespace, project, @ref || project.repository.root_ref)
end
Loading
Loading
@@ -41,10 +54,6 @@ module GitlabRoutingHelper
activity_namespace_project_path(project.namespace, project, *args)
end
 
def edit_project_path(project, *args)
edit_namespace_project_path(project.namespace, project, *args)
end
def runners_path(project, *args)
namespace_project_runners_path(project.namespace, project, *args)
end
Loading
Loading
@@ -65,14 +74,6 @@ module GitlabRoutingHelper
namespace_project_milestone_path(entity.project.namespace, entity.project, entity, *args)
end
 
def project_url(project, *args)
namespace_project_url(project.namespace, project, *args)
end
def edit_project_url(project, *args)
edit_namespace_project_url(project.namespace, project, *args)
end
def issue_url(entity, *args)
namespace_project_issue_url(entity.project.namespace, entity.project, entity, *args)
end
Loading
Loading
@@ -92,4 +93,56 @@ module GitlabRoutingHelper
toggle_subscription_namespace_project_merge_request_path(entity.project.namespace, entity.project, entity)
end
end
## Members
def project_members_url(project, *args)
namespace_project_project_members_url(project.namespace, project)
end
def project_member_path(project_member, *args)
namespace_project_project_member_path(project_member.source.namespace, project_member.source, project_member)
end
def request_access_project_members_path(project, *args)
request_access_namespace_project_project_members_path(project.namespace, project)
end
def leave_project_members_path(project, *args)
leave_namespace_project_project_members_path(project.namespace, project)
end
def approve_access_request_project_member_path(project_member, *args)
approve_access_request_namespace_project_project_member_path(project_member.source.namespace, project_member.source, project_member)
end
def resend_invite_project_member_path(project_member, *args)
resend_invite_namespace_project_project_member_path(project_member.source.namespace, project_member.source, project_member)
end
# Groups
## Members
def group_members_url(group, *args)
group_group_members_url(group, *args)
end
def group_member_path(group_member, *args)
group_group_member_path(group_member.source, group_member)
end
def request_access_group_members_path(group, *args)
request_access_group_group_members_path(group)
end
def leave_group_members_path(group, *args)
leave_group_group_members_path(group)
end
def approve_access_request_group_member_path(group_member, *args)
approve_access_request_group_group_member_path(group_member.source, group_member)
end
def resend_invite_group_member_path(group_member, *args)
resend_invite_group_group_member_path(group_member.source, group_member)
end
end
module MembersHelper
def member_class(member)
"#{member.source.class.to_s}Member".constantize
end
def members_association(entity)
"#{entity.class.to_s.underscore}_members".to_sym
end
# Returns a `<action>_<source>_member` association, e.g.:
# - admin_project_member, update_project_member, destroy_project_member
# - admin_group_member, update_group_member, destroy_group_member
def action_member_permission(action, member)
"#{action}_#{member.source.class.to_s.underscore}_member".to_sym
"#{action}_#{member.type.underscore}".to_sym
end
 
def can_see_entity_roles?(user, entity)
def can_see_member_roles?(source:, user: nil)
return false unless user
 
user.is_admin? || entity.send(members_association(entity)).exists?(user_id: user.id)
end
def member_path(member)
case member.source
when Project
namespace_project_project_member_path(member.source.namespace, member.source, member)
when Group
group_group_member_path(member.source, member)
else
raise ArgumentError.new('Unknown object class')
end
user.is_admin? || source.members.exists?(user_id: user.id)
end
 
def resend_invite_member_path(member)
case member.source
when Project
resend_invite_namespace_project_project_member_path(member.source.namespace, member.source, member)
when Group
resend_invite_group_group_member_path(member.source, member)
else
raise ArgumentError.new('Unknown object class')
end
end
def remove_member_message(member, user: nil)
user = current_user if defined?(current_user)
 
def request_access_path(entity)
case entity
when Project
request_access_namespace_project_project_members_path(entity.namespace, entity)
when Group
request_access_group_group_members_path(entity)
else
raise ArgumentError.new('Unknown object class')
end
end
def approve_request_member_path(member)
case member.source
when Project
approve_access_request_namespace_project_project_member_path(member.source.namespace, member.source, member)
when Group
approve_access_request_group_group_member_path(member.source, member)
else
raise ArgumentError.new('Unknown object class')
end
end
text = 'Are you sure you want to '
action =
if member.request?
if member.user == user
'withdraw your access request for'
else
"deny #{member.user.name}'s request to join"
end
elsif member.invite?
"revoke the invitation for #{member.invite_email} to join"
else
"remove #{member.user.name} from"
end
 
def leave_path(entity)
case entity
when Project
leave_namespace_project_project_members_path(entity.namespace, entity)
when Group
leave_group_group_members_path(entity)
else
raise ArgumentError.new('Unknown object class')
end
end
def withdraw_request_message(entity)
"Are you sure you want to withdraw your access request for the \"#{entity_name(entity)}\" #{entity_type(entity)}?"
end
def remove_member_message(member)
entity = member.source
entity_type = entity_type(entity)
entity_name = entity_name(entity)
if member.request?
"You are going to deny #{member.created_by.name}'s request to join the #{entity_name} #{entity_type}. Are you sure?"
elsif member.invite?
"You are going to revoke the invitation for #{member.invite_email} to join the #{entity_name} #{entity_type}. Are you sure?"
else
"You are going to remove #{member.user.name} from the #{entity_name} #{entity_type}. Are you sure?"
end
text << action << " the #{member.source.human_name} #{member.real_source_type.humanize(capitalize: false)}?"
end
 
def remove_member_title(member)
member.request? ? 'Deny access request' : 'Remove user'
end
def leave_confirmation_message(entity)
"Are you sure you want to leave \"#{entity_name(entity)}\" #{entity_type(entity)}?"
end
private
text = " from #{member.real_source_type.humanize(capitalize: false)}"
 
def entity_type(entity)
entity.class.to_s.underscore
text.prepend(member.request? ? 'Deny access request' : 'Remove user')
end
 
def entity_name(entity)
case entity
when Project
entity.name_with_namespace
when Group
entity.name
else
raise ArgumentError.new('Unknown object class')
end
def leave_confirmation_message(member_source)
"Are you sure you want to leave the " \
"\"#{member_source.human_name}\" #{member_source.class.to_s.humanize(capitalize: false)}?"
end
end
module ProjectsHelper
def max_access_level(project, user)
Gitlab::Access.options_with_owner.key(project.team.max_member_access(user.id))
end
def link_to_project(project)
link_to [project.namespace.becomes(Namespace), project], title: h(project.name) do
title = content_tag(:span, project.name, class: 'project-name')
Loading
Loading
module Emails
module Members
extend ActiveSupport::Concern
include MembersHelper
 
included do
attr_reader :member_target_type
helper_method :member, :access_requester, :member_target_type, :member_target_name, :member_target_url
helper_method :member_source, :member
end
 
def member_access_requested_email(member_target_type, member_id)
@member_target_type = member_target_type
def member_access_requested_email(member_source_type, member_id)
@member_source_type = member_source_type
@member_id = member_id
 
admins = User.where(id: target.public_send(members_association).admins.pluck(:user_id)).pluck(:notification_email)
admins = member_source.members.owners_and_masters.includes(:user).pluck(:notification_email)
 
mail(to: admins,
subject: subject("Request to join the #{member_target_name} #{member_target_type}"))
subject: subject("Request to join the #{member_source.human_name} #{member_source.model_name.singular}"))
end
 
def member_access_granted_email(member_target_type, member_id)
@member_target_type = member_target_type
def member_access_granted_email(member_source_type, member_id)
@member_source_type = member_source_type
@member_id = member_id
 
mail(to: member.user.notification_email,
subject: subject("Access to the #{member_target_name} #{member_target_type} was granted"))
subject: subject("Access to the #{member_source.human_name} #{member_source.model_name.singular} was granted"))
end
 
def member_access_denied_email(member_target_type, target_id, user_id)
@member_target_type = member_target_type
@target = target_class.find(target_id)
def member_access_denied_email(member_source_type, source_id, user_id)
@member_source_type = member_source_type
@member_source = member_source_class.find(source_id)
requester = User.find(user_id)
 
mail(to: User.find(user_id).notification_email,
subject: subject("Access to the #{member_target_name} #{member_target_type} was denied"))
mail(to: requester.notification_email,
subject: subject("Access to the #{member_source.human_name} #{member_source.model_name.singular} was denied"))
end
 
def member_invited_email(member_target_type, member_id, token)
@member_target_type = member_target_type
def member_invited_email(member_source_type, member_id, token)
@member_source_type = member_source_type
@member_id = member_id
@token = token
 
mail(to: member.invite_email,
subject: "Invitation to join the #{member_target_name} #{member_target_type}")
subject: "Invitation to join the #{member_source.human_name} #{member_source.model_name.singular}")
end
 
def member_invite_accepted_email(member_target_type, member_id)
@member_target_type = member_target_type
def member_invite_accepted_email(member_source_type, member_id)
@member_source_type = member_source_type
@member_id = member_id
return if access_requester.nil?
return unless member.created_by
 
mail(to: access_requester.notification_email,
mail(to: member.created_by.notification_email,
subject: subject('Invitation accepted'))
end
 
def member_invite_declined_email(member_target_type, target_id, invite_email, created_by_id)
return if created_by_id.nil?
def member_invite_declined_email(member_source_type, source_id, invite_email, created_by_id)
return unless created_by_id
 
@member_target_type = member_target_type
@target = target_class.find(target_id)
@member_source_type = member_source_type
@member_source = member_source_class.find(source_id)
@invite_email = invite_email
inviter = User.find(created_by_id)
 
mail(to: User.find(created_by_id).notification_email,
mail(to: inviter.notification_email,
subject: subject('Invitation declined'))
end
 
def member
@member ||= member_class.find(@member_id)
@member ||= Member.find(@member_id)
end
 
def access_requester
@access_requester ||= member.created_by
end
def member_target_name
case member_target_type
when 'project'
target.name_with_namespace
else
target.name
end
end
def member_target_url
@member_target_url ||= target.web_url
def member_source
@member_source ||= member.source
end
 
private
 
def target
@target ||= member.public_send(member_target_type)
end
def target_class
@target_class ||= member_target_type.classify.constantize
end
def member_class
@member_class ||= "#{member_target_type.classify}Member".constantize
end
def members_association
@members_association ||= member_class.to_s.tableize
def member_source_class
@member_source_type.classify.constantize
end
end
end
Loading
Loading
@@ -13,6 +13,8 @@ class Notify < BaseMailer
add_template_helper DiffHelper
add_template_helper BlobHelper
add_template_helper EmailsHelper
add_template_helper MembersHelper
add_template_helper GitlabRoutingHelper
 
def test_email(recipient_email, subject, body)
mail(to: recipient_email,
Loading
Loading
Loading
Loading
@@ -460,8 +460,6 @@ class Ability
rules << :destroy_group_member
elsif user == target_user
rules << :destroy_group_member
elsif subject.request? && user == subject.created_by
rules << :destroy_group_member
end
end
 
Loading
Loading
@@ -481,8 +479,6 @@ class Ability
rules << :destroy_project_member
elsif user == target_user
rules << :destroy_project_member
elsif subject.request? && user == subject.created_by
rules << :destroy_project_member
end
end
 
Loading
Loading
Loading
Loading
@@ -10,18 +10,7 @@ module AccessRequestable
def request_access(user)
members.create(
access_level: Gitlab::Access::DEVELOPER,
created_by: user,
user: user,
requested_at: Time.now.utc)
end
def access_requested?(user)
members.where(created_by_id: user.id).where.not(requested_at: nil).any?
end
private
# Returns a `<entities>_members` association, e.g.: project_members, group_members
def members
@members ||= send("#{self.class.to_s.underscore}_members".to_sym)
end
end
Loading
Loading
@@ -8,7 +8,7 @@ class Group < Namespace
 
has_many :group_members, dependent: :destroy, as: :source, class_name: 'GroupMember'
alias_method :members, :group_members
has_many :users, through: :group_members
has_many :users, -> { where(members: { requested_at: nil }) }, through: :group_members
has_many :project_group_links, dependent: :destroy
has_many :shared_projects, through: :project_group_links, source: :project
has_many :notification_settings, dependent: :destroy, as: :source
Loading
Loading
Loading
Loading
@@ -8,7 +8,7 @@ class Member < ActiveRecord::Base
belongs_to :user
belongs_to :source, polymorphic: true
 
validates :user, presence: true, unless: :pending?
validates :user, presence: true, unless: :invite?
validates :source, presence: true
validates :user_id, uniqueness: { scope: [:source_type, :source_id],
message: "already exists in source",
Loading
Loading
@@ -27,16 +27,17 @@ class Member < ActiveRecord::Base
}
 
scope :invite, -> { where.not(invite_token: nil) }
scope :non_invite, -> { where(invite_token: nil) }
scope :request, -> { where.not(requested_at: nil) }
scope :non_request, -> { where(requested_at: nil) }
scope :non_pending, -> { where.not(user_id: nil) }
scope :non_pending, -> { non_request.non_invite }
 
scope :guests, -> { where(access_level: GUEST) }
scope :reporters, -> { where(access_level: REPORTER) }
scope :developers, -> { where(access_level: DEVELOPER) }
scope :masters, -> { where(access_level: MASTER) }
scope :owners, -> { where(access_level: OWNER) }
scope :admins, -> { where(access_level: [OWNER, MASTER]) }
scope :owners_and_masters, -> { where(access_level: [OWNER, MASTER]) }
 
before_validation :generate_invite_token, on: :create, if: -> (member) { member.invite_email.present? }
 
Loading
Loading
@@ -46,6 +47,7 @@ class Member < ActiveRecord::Base
after_create :post_create_hook, unless: :pending?
after_update :post_update_hook, unless: :pending?
after_destroy :post_destroy_hook, unless: :pending?
after_destroy :post_decline_request, if: :request?
 
delegate :name, :username, :email, to: :user, prefix: true
 
Loading
Loading
@@ -102,36 +104,31 @@ class Member < ActiveRecord::Base
end
end
 
def pending?
request? || invite?
def real_source_type
source_type
end
def invite?
self.invite_token.present?
end
 
def request?
user.nil? && created_by.present? && requested_at.present?
requested_at.present?
end
 
def invite?
self.invite_token.present?
def pending?
invite? || request?
end
 
def accept_request
return false unless request?
 
updated = self.update(user: created_by, requested_at: nil)
updated = self.update(requested_at: nil)
after_accept_request if updated
 
updated
end
 
def decline_request
return false unless request?
self.destroy
after_decline_request if destroyed?
destroyed?
end
def accept_invite!(new_user)
return false unless invite?
 
Loading
Loading
@@ -217,7 +214,7 @@ class Member < ActiveRecord::Base
post_create_hook
end
 
def after_decline_request
def post_decline_request
# override in subclass
end
 
Loading
Loading
Loading
Loading
@@ -20,6 +20,11 @@ class GroupMember < Member
access_level
end
 
# Because source_type is `Namespace`...
def real_source_type
'Group'
end
private
 
def send_invite
Loading
Loading
@@ -60,8 +65,8 @@ class GroupMember < Member
super
end
 
def after_decline_request
notification_service.decline_group_access_request(group, created_by)
def post_decline_request
notification_service.decline_group_access_request(self)
 
super
end
Loading
Loading
Loading
Loading
@@ -152,8 +152,8 @@ class ProjectMember < Member
super
end
 
def after_decline_request
notification_service.decline_project_access_request(project, created_by)
def post_decline_request
notification_service.decline_project_access_request(self)
 
super
end
Loading
Loading
Loading
Loading
@@ -104,7 +104,8 @@ class Project < ActiveRecord::Base
has_many :hooks, dependent: :destroy, class_name: 'ProjectHook'
has_many :protected_branches, dependent: :destroy
has_many :project_members, dependent: :destroy, as: :source, class_name: 'ProjectMember'
has_many :users, through: :project_members
alias_method :members, :project_members
has_many :users, -> { where(members: { requested_at: nil }) }, through: :project_members
has_many :deploy_keys_projects, dependent: :destroy
has_many :deploy_keys, through: :deploy_keys_projects
has_many :users_star_projects, dependent: :destroy
Loading
Loading
@@ -690,6 +691,7 @@ class Project < ActiveRecord::Base
end
end
end
alias_method :human_name, :name_with_namespace
 
def path_with_namespace
if namespace
Loading
Loading
Loading
Loading
@@ -22,12 +22,12 @@ class ProjectTeam
end
 
def find_member(user_id)
member = project.project_members.find_by(user_id: user_id)
member = project.members.non_request.find_by(user_id: user_id)
 
# If user is not in project members
# we should check for group membership
if group && !member
member = group.group_members.find_by(user_id: user_id)
member = group.members.non_request.find_by(user_id: user_id)
end
 
member
Loading
Loading
@@ -128,12 +128,16 @@ class ProjectTeam
end
end
 
def human_max_access(user_id)
Gitlab::Access.options_with_owner.key(max_member_access(user_id))
end
# This method assumes project and group members are eager loaded for optimal
# performance.
def max_member_access(user_id)
access = []
 
project.project_members.each do |member|
project.members.non_request.each do |member|
if member.user_id == user_id
access << member.access_field if member.access_field
break
Loading
Loading
@@ -141,7 +145,7 @@ class ProjectTeam
end
 
if group
group.group_members.each do |member|
group.members.non_request.each do |member|
if member.user_id == user_id
access << member.access_field if member.access_field
break
Loading
Loading
@@ -174,14 +178,14 @@ class ProjectTeam
end
 
def fetch_members(level = nil)
project_members = project.project_members
group_members = group ? group.group_members : []
project_members = project.members.non_request
group_members = group ? group.members.non_request : []
invited_members = []
 
if project.invited_groups.any? && project.allowed_to_share_with_group?
project.project_group_links.each do |group_link|
invited_group = group_link.group
im = invited_group.group_members
im = invited_group.members.non_request
 
if level
int_level = GroupMember.access_level_roles[level.to_s.singularize.titleize]
Loading
Loading
Loading
Loading
@@ -175,24 +175,24 @@ class NotificationService
 
# Project access request
def new_project_access_request(project_member)
mailer.member_access_requested_email('project', project_member.id).deliver_later
mailer.member_access_requested_email(project_member.real_source_type, project_member.id).deliver_later
end
 
def decline_project_access_request(project, user)
mailer.member_access_denied_email('project', project.id, user.id).deliver_later
def decline_project_access_request(project_member)
mailer.member_access_denied_email(project_member.real_source_type, project_member.project.id, project_member.user.id).deliver_later
end
 
def invite_project_member(project_member, token)
mailer.member_invited_email('project', project_member.id, token).deliver_later
mailer.member_invited_email(project_member.real_source_type, project_member.id, token).deliver_later
end
 
def accept_project_invite(project_member)
mailer.member_invite_accepted_email('project', project_member.id).deliver_later
mailer.member_invite_accepted_email(project_member.real_source_type, project_member.id).deliver_later
end
 
def decline_project_invite(project_member)
mailer.member_invite_declined_email(
'project',
project_member.real_source_type,
project_member.project.id,
project_member.invite_email,
project_member.access_level,
Loading
Loading
@@ -201,24 +201,24 @@ class NotificationService
end
 
def new_project_member(project_member)
mailer.member_access_granted_email('project', project_member.id).deliver_later
mailer.member_access_granted_email(project_member.real_source_type, project_member.id).deliver_later
end
 
def update_project_member(project_member)
mailer.member_access_granted_email('project', project_member.id).deliver_later
mailer.member_access_granted_email(project_member.real_source_type, project_member.id).deliver_later
end
 
# Group access request
def new_group_access_request(group_member)
mailer.member_access_requested_email('group', group_member.id).deliver_later
mailer.member_access_requested_email(group_member.real_source_type, group_member.id).deliver_later
end
 
def decline_group_access_request(group, user)
mailer.member_access_denied_email('group', group.id, user.id).deliver_later
def decline_group_access_request(group_member)
mailer.member_access_denied_email(group_member.real_source_type, group_member.group.id, group_member.user.id).deliver_later
end
 
def invite_group_member(group_member, token)
mailer.member_invited_email('group', group_member.id, token).deliver_later
mailer.member_invited_email(group_member.real_source_type, group_member.id, token).deliver_later
end
 
def accept_group_invite(group_member)
Loading
Loading
@@ -227,7 +227,7 @@ class NotificationService
 
def decline_group_invite(group_member)
mailer.member_invite_declined_email(
'group',
group_member.real_source_type,
group_member.group.id,
group_member.invite_email,
group_member.access_level,
Loading
Loading
@@ -236,11 +236,11 @@ class NotificationService
end
 
def new_group_member(group_member)
mailer.member_access_granted_email('group', group_member.id).deliver_later
mailer.member_access_granted_email(group_member.real_source_type, group_member.id).deliver_later
end
 
def update_group_member(group_member)
mailer.member_access_granted_email('group', group_member.id).deliver_later
mailer.member_access_granted_email(group_member.real_source_type, group_member.id).deliver_later
end
 
def project_was_moved(project, old_path_with_namespace)
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