Commit cac77234 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Get rid of roles

parent 1b25a8f4
......@@ -170,4 +170,139 @@ class Event < ActiveRecord::Base
"opened"
end
end
def valid_push?
data[:ref]
rescue => ex
false
end
def tag?
data[:ref]["refs/tags"]
end
def branch?
data[:ref]["refs/heads"]
end
def new_branch?
commit_from =~ /^00000/
end
def new_ref?
commit_from =~ /^00000/
end
def rm_ref?
commit_to =~ /^00000/
end
def md_ref?
!(rm_ref? || new_ref?)
end
def commit_from
data[:before]
end
def commit_to
data[:after]
end
def ref_name
if tag?
tag_name
else
branch_name
end
end
def branch_name
@branch_name ||= data[:ref].gsub("refs/heads/", "")
end
def tag_name
@tag_name ||= data[:ref].gsub("refs/tags/", "")
end
# Max 20 commits from push DESC
def commits
@commits ||= data[:commits].map { |commit| project.commit(commit[:id]) }.reverse
end
def commits_count
data[:total_commits_count] || commits.count || 0
end
def ref_type
tag? ? "tag" : "branch"
end
def push_action_name
if new_ref?
"pushed new"
elsif rm_ref?
"deleted"
else
"pushed to"
end
end
def parent_commit
project.commit(commit_from)
rescue => ex
nil
end
def last_commit
project.commit(commit_to)
rescue => ex
nil
end
def push_with_commits?
md_ref? && commits.any? && parent_commit && last_commit
rescue Grit::NoSuchPathError
false
end
def last_push_to_non_root?
branch? && project.default_branch != branch_name
end
def note_commit_id
target.commit_id
end
def note_short_commit_id
note_commit_id[0..8]
end
def note_commit?
target.noteable_type == "Commit"
end
def note_target
target.noteable
end
def note_target_id
if note_commit?
target.commit_id
else
target.noteable_id.to_s
end
end
def wall_note?
target.noteable_type.blank?
end
def note_target_type
if target.noteable_type.present?
target.noteable_type.titleize
else
"Wall"
end.downcase
end
end
This diff is collapsed.
......@@ -34,8 +34,6 @@
#
class User < ActiveRecord::Base
include Account
devise :database_authenticatable, :token_authenticatable, :lockable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
......@@ -192,4 +190,92 @@ class User < ActiveRecord::Base
def tm_in_personal_projects
personal_projects.users_projects.where(user_id: self.id)
end
# Returns a string for use as a Gitolite user identifier
#
# Note that Gitolite 2.x requires the following pattern for users:
#
# ^@?[0-9a-zA-Z][0-9a-zA-Z._\@+-]*$
def identifier
# Replace non-word chars with underscores, then make sure it starts with
# valid chars
email.gsub(/\W/, '_').gsub(/\A([\W\_])+/, '')
end
def is_admin?
admin
end
def require_ssh_key?
keys.count == 0
end
def can_create_project?
projects_limit > personal_projects.count
end
def can_create_group?
is_admin?
end
def abilities
@abilities ||= begin
abilities = Six.new
abilities << Ability
abilities
end
end
def can? action, subject
abilities.allowed?(self, action, subject)
end
def last_activity_project
projects.first
end
def first_name
name.split.first unless name.blank?
end
def cared_merge_requests
MergeRequest.where("author_id = :id or assignee_id = :id", id: self.id)
end
# Remove user from all projects and
# set blocked attribute to true
def block
users_projects.find_each do |membership|
return false unless membership.destroy
end
self.blocked = true
save
end
def projects_limit_percent
return 100 if projects_limit.zero?
(personal_projects.count.to_f / projects_limit) * 100
end
def recent_push project_id = nil
# Get push events not earlier than 2 hours ago
events = recent_events.code_push.where("created_at > ?", Time.now - 2.hours)
events = events.where(project_id: project_id) if project_id
# Take only latest one
events = events.recent.limit(1).first
end
def projects_sorted_by_activity
authorized_projects.sorted_by_activity
end
def several_namespaces?
namespaces.size > 1
end
def namespace_id
namespace.try :id
end
end
# == Account role
#
# Describe behaviour of User in application
#
# Used by User
#
module Account
# Returns a string for use as a Gitolite user identifier
#
# Note that Gitolite 2.x requires the following pattern for users:
#
# ^@?[0-9a-zA-Z][0-9a-zA-Z._\@+-]*$
def identifier
# Replace non-word chars with underscores, then make sure it starts with
# valid chars
email.gsub(/\W/, '_').gsub(/\A([\W\_])+/, '')
end
def is_admin?
admin
end
def require_ssh_key?
keys.count == 0
end
def can_create_project?
projects_limit > personal_projects.count
end
def can_create_group?
is_admin?
end
def abilities
@abilities ||= begin
abilities = Six.new
abilities << Ability
abilities
end
end
def can? action, subject
abilities.allowed?(self, action, subject)
end
def last_activity_project
projects.first
end
def first_name
name.split.first unless name.blank?
end
def cared_merge_requests
MergeRequest.where("author_id = :id or assignee_id = :id", id: self.id)
end
# Remove user from all projects and
# set blocked attribute to true
def block
users_projects.find_each do |membership|
return false unless membership.destroy
end
self.blocked = true
save
end
def projects_limit_percent
return 100 if projects_limit.zero?
(personal_projects.count.to_f / projects_limit) * 100
end
def recent_push project_id = nil
# Get push events not earlier than 2 hours ago
events = recent_events.code_push.where("created_at > ?", Time.now - 2.hours)
events = events.where(project_id: project_id) if project_id
# Take only latest one
events = events.recent.limit(1).first
end
def projects_sorted_by_activity
authorized_projects.sorted_by_activity
end
def several_namespaces?
namespaces.size > 1
end
def namespace_id
namespace.try :id
end
end
# == Authority role
#
# Control access to project repository based on users role in team
#
# Used by Project
#
module Authority
# Compatible with all access rights
# Should be rewrited for new access rights
def add_access(user, *access)
access = if access.include?(:admin)
{ project_access: UsersProject::MASTER }
elsif access.include?(:write)
{ project_access: UsersProject::DEVELOPER }
else
{ project_access: UsersProject::REPORTER }
end
opts = { user: user }
opts.merge!(access)
users_projects.create(opts)
end
def reset_access(user)
users_projects.where(project_id: self.id, user_id: user.id).destroy if self.id
end
def repository_readers
repository_members[UsersProject::REPORTER]
end
def repository_writers
repository_members[UsersProject::DEVELOPER]
end
def repository_masters
repository_members[UsersProject::MASTER]
end
def repository_members
keys = Hash.new {|h,k| h[k] = [] }
UsersProject.select("keys.identifier, project_access").
joins(user: :keys).where(project_id: id).
each {|row| keys[row.project_access] << [row.identifier] }
keys[UsersProject::REPORTER] += deploy_keys.pluck(:identifier)
keys
end
def allow_read_for?(user)
!users_projects.where(user_id: user.id).empty?
end
def guest_access_for?(user)
!users_projects.where(user_id: user.id).empty?
end
def report_access_for?(user)
!users_projects.where(user_id: user.id, project_access: [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
end
def dev_access_for?(user)
!users_projects.where(user_id: user.id, project_access: [UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
end
def master_access_for?(user)
!users_projects.where(user_id: user.id, project_access: [UsersProject::MASTER]).empty?
end
end
# == NamespacedProject role
#
# Provides extra functionality for Project related to namespaces like:
# - transfer project between namespaces
# - name, path including namespece
# - project owner based on namespace
#
# Used by Project
#
module NamespacedProject
def transfer(new_namespace)
Project.transaction do
old_namespace = namespace
self.namespace = new_namespace
old_dir = old_namespace.try(:path) || ''
new_dir = new_namespace.try(:path) || ''
old_repo = if old_dir.present?
File.join(old_dir, self.path)
else
self.path
end
if Project.where(path: self.path, namespace_id: new_namespace.try(:id)).present?
raise TransferError.new("Project with same path in target namespace already exists")
end
Gitlab::ProjectMover.new(self, old_dir, new_dir).execute
git_host.move_repository(old_repo, self)
save!
end
rescue Gitlab::ProjectMover::ProjectMoveError => ex
raise Project::TransferError.new(ex.message)
end
def name_with_namespace
@name_with_namespace ||= begin
if namespace
namespace.human_name + " / " + name
else
name
end
end
end
def namespace_owner
namespace.try(:owner)
end
def path_with_namespace
if namespace
namespace.path + '/' + path
else
path
end
end
end
# == NoteEvent role
#
# Extends Event model functionality by providing extra methods related to comment events
#
# Used by Event
#
module NoteEvent
def note_commit_id
target.commit_id
end
def note_short_commit_id
note_commit_id[0..8]
end
def note_commit?
target.noteable_type == "Commit"
end
def note_target
target.noteable
end
def note_target_id
if note_commit?
target.commit_id
else
target.noteable_id.to_s
end
end
def wall_note?
target.noteable_type.blank?
end
def note_target_type
if target.noteable_type.present?
target.noteable_type.titleize
else
"Wall"
end.downcase
end
end
# == PushEvent role
#
# Extends Event model functionality by providing extra methods related to push events
#
# Used by Event
#
module PushEvent
def valid_push?
data[:ref]
rescue => ex
false
end
def tag?
data[:ref]["refs/tags"]
end
def branch?
data[:ref]["refs/heads"]
end
def new_branch?
commit_from =~ /^00000/
end
def new_ref?
commit_from =~ /^00000/
end
def rm_ref?
commit_to =~ /^00000/
end
def md_ref?
!(rm_ref? || new_ref?)
end
def commit_from
data[:before]
end
def commit_to
data[:after]
end
def ref_name
if tag?
tag_name
else
branch_name
end
end
def branch_name
@branch_name ||= data[:ref].gsub("refs/heads/", "")
end
def tag_name
@tag_name ||= data[:ref].gsub("refs/tags/", "")
end
# Max 20 commits from push DESC
def commits
@commits ||= data[:commits].map { |commit| project.commit(commit[:id]) }.reverse
end
def commits_count
data[:total_commits_count] || commits.count || 0
end
def ref_type
tag? ? "tag" : "branch"
end
def push_action_name
if new_ref?
"pushed new"
elsif rm_ref?
"deleted"
else
"pushed to"
end
end
def parent_commit
project.commit(commit_from)
rescue => ex
nil
end
def last_commit
project.commit(commit_to)
rescue => ex
nil
end
def push_with_commits?
md_ref? && commits.any? && parent_commit && last_commit
rescue Grit::NoSuchPathError
false
end
def last_push_to_non_root?
branch? && project.default_branch != branch_name
end
end
# == PushObserver role
#
# Includes methods to be triggered on push to project repository.
#
#
# Used by Project
# Triggered by PostReceive job
#
module PushObserver
# This method will be called after each post receive and only if the provided
# user is present in GitLab.
#
# All callbacks for post receive should be placed here.
def trigger_post_receive(oldrev, newrev, ref, user)
data = post_receive_data(oldrev, newrev, ref, user)
# Create push event
self.observe_push(data)
if push_to_branch? ref, oldrev
# Close merged MR
self.update_merge_requests(oldrev, newrev, ref, user)
# Execute web hooks
self.execute_hooks(data.dup)
# Execute project services
self.execute_services(data.dup)
end
# Create satellite
self.satellite.create unless self.satellite.exists?
# Discover the default branch, but only if it hasn't already been set to
# something else
if default_branch.nil?
update_attributes(default_branch: discover_default_branch)
end
end
def push_to_branch? ref, oldrev
ref_parts = ref.split('/')
# Return if this is not a push to a branch (e.g. new commits)
!(ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000")
end
def observe_push(data)
Event.create(
project: self,
action: Event::Pushed,
data: data,
author_id: data[:user_id]
)
end
def execute_hooks(data)
hooks.each { |hook| hook.execute(data) }
end
def execute_services(data)
services.each do |service|
# Call service hook only if it is active
service.execute(data) if service.active
end
end
# Produce a hash of post-receive data
#
# data = {
# before: String,
# after: String,
# ref: String,
# user_id: String,
# user_name: String,
# repository: {
# name: String,
# url: String,
# description: String,
# homepage: String,
# },
# commits: Array,
# total_commits_count: Fixnum
# }
#
def post_receive_data(oldrev, newrev, ref, user)
push_commits = commits_between(oldrev, newrev)
# Total commits count
push_commits_count = push_commits.size
# Get latest 20 commits ASC
push_commits_limited = push_commits.last(20)
# Hash to be passed as post_receive_data
data = {
before: oldrev,
after: newrev,
ref: ref,
user_id: user.id,
user_name: user.name,
repository: {
name: name,
url: url_to_repo,
description: description,
homepage: web_url,
},
commits: [],
total_commits_count: push_commits_count
}
# For perfomance purposes maximum 20 latest commits
# will be passed as post receive hook data.
#
push_commits_limited.each do |commit|
data[:commits] << {