Commit 0a70aca3b177cffccd2e04579712665d10b8fd69

Authored by Dmitriy Zaporozhets
1 parent 98b84166

Models Refactoring: Move methods to roles

app/models/event.rb
1 1 class Event < ActiveRecord::Base
  2 + include PushEvent
  3 +
2 4 default_scope where("author_id IS NOT NULL")
3 5  
4 6 Created = 1
... ... @@ -9,8 +11,6 @@ class Event &lt; ActiveRecord::Base
9 11 Commented = 6
10 12 Merged = 7
11 13  
12   - does "event/push"
13   -
14 14 belongs_to :project
15 15 belongs_to :target, :polymorphic => true
16 16  
... ...
app/models/event/push_trait.rb
... ... @@ -1,92 +0,0 @@
1   -module Event::PushTrait
2   - as_trait do
3   - def valid_push?
4   - data[:ref]
5   - rescue => ex
6   - false
7   - end
8   -
9   - def tag?
10   - data[:ref]["refs/tags"]
11   - end
12   -
13   - def new_branch?
14   - commit_from =~ /^00000/
15   - end
16   -
17   - def new_ref?
18   - commit_from =~ /^00000/
19   - end
20   -
21   - def rm_ref?
22   - commit_to =~ /^00000/
23   - end
24   -
25   - def md_ref?
26   - !(rm_ref? || new_ref?)
27   - end
28   -
29   - def commit_from
30   - data[:before]
31   - end
32   -
33   - def commit_to
34   - data[:after]
35   - end
36   -
37   - def ref_name
38   - if tag?
39   - tag_name
40   - else
41   - branch_name
42   - end
43   - end
44   -
45   - def branch_name
46   - @branch_name ||= data[:ref].gsub("refs/heads/", "")
47   - end
48   -
49   - def tag_name
50   - @tag_name ||= data[:ref].gsub("refs/tags/", "")
51   - end
52   -
53   - # Max 20 commits from push DESC
54   - def commits
55   - @commits ||= data[:commits].map { |commit| project.commit(commit[:id]) }.reverse
56   - end
57   -
58   - def commits_count
59   - data[:total_commits_count] || commits.count || 0
60   - end
61   -
62   - def ref_type
63   - tag? ? "tag" : "branch"
64   - end
65   -
66   - def push_action_name
67   - if new_ref?
68   - "pushed new"
69   - elsif rm_ref?
70   - "removed #{ref_type}"
71   - else
72   - "pushed to"
73   - end
74   - end
75   -
76   - def parent_commit
77   - project.commit(commit_from)
78   - rescue => ex
79   - nil
80   - end
81   -
82   - def last_commit
83   - project.commit(commit_to)
84   - rescue => ex
85   - nil
86   - end
87   -
88   - def push_with_commits?
89   - md_ref? && commits.any? && parent_commit && last_commit
90   - end
91   - end
92   -end
app/models/issue.rb
1 1 class Issue < ActiveRecord::Base
  2 + include Upvote
  3 +
2 4 belongs_to :project
3 5 belongs_to :milestone
4 6 belongs_to :author, :class_name => "User"
... ... @@ -53,11 +55,6 @@ class Issue &lt; ActiveRecord::Base
53 55 def new?
54 56 today? && created_at == updated_at
55 57 end
56   -
57   - # Return the number of +1 comments (upvotes)
58   - def upvotes
59   - notes.select(&:upvote?).size
60   - end
61 58 end
62 59 # == Schema Information
63 60 #
... ...
app/models/key.rb
1 1 require 'digest/md5'
2 2  
3 3 class Key < ActiveRecord::Base
  4 + include SshKey
4 5 belongs_to :user
5 6 belongs_to :project
6 7  
... ... @@ -37,28 +38,11 @@ class Key &lt; ActiveRecord::Base
37 38 end
38 39 end
39 40  
40   - def update_repository
41   - Gitlab::GitHost.system.new.configure do |c|
42   - c.update_keys(identifier, key)
43   - c.update_projects(projects)
44   - end
45   - end
46   -
47   - def repository_delete_key
48   - Gitlab::GitHost.system.new.configure do |c|
49   - #delete key file is there is no identically deploy keys
50   - if !is_deploy_key || Key.where(:identifier => identifier).count() == 0
51   - c.delete_key(identifier)
52   - end
53   - c.update_projects(projects)
54   - end
55   - end
56   -
57 41 def is_deploy_key
58 42 true if project_id
59 43 end
60 44  
61   - #projects that has this key
  45 + # projects that has this key
62 46 def projects
63 47 if is_deploy_key
64 48 [project]
... ...
app/models/merge_request.rb
1 1 require File.join(Rails.root, "app/models/commit")
2 2  
3 3 class MergeRequest < ActiveRecord::Base
  4 + include Upvote
  5 +
4 6 UNCHECKED = 1
5 7 CAN_BE_MERGED = 2
6 8 CANNOT_BE_MERGED = 3
... ... @@ -128,12 +130,6 @@ class MergeRequest &lt; ActiveRecord::Base
128 130 self.project.events.where(:target_id => self.id, :target_type => "MergeRequest", :action => Event::Closed).last
129 131 end
130 132  
131   -
132   - # Return the number of +1 comments (upvotes)
133   - def upvotes
134   - notes.select(&:upvote?).size
135   - end
136   -
137 133 def commits
138 134 st_commits || []
139 135 end
... ...
app/models/project.rb
1 1 require "grit"
2 2  
3 3 class Project < ActiveRecord::Base
  4 + include Repository
  5 + include GitPush
  6 + include Authority
  7 + include Team
  8 +
  9 + #
  10 + # Relations
  11 + #
4 12 belongs_to :owner, :class_name => "User"
5   -
6   - does "project/validations"
7   - does "project/repository"
8   - does "project/permissions"
9   - does "project/hooks"
10   -
11 13 has_many :users, :through => :users_projects
12 14 has_many :events, :dependent => :destroy
13 15 has_many :merge_requests, :dependent => :destroy
... ... @@ -21,8 +23,14 @@ class Project &lt; ActiveRecord::Base
21 23 has_many :wikis, :dependent => :destroy
22 24 has_many :protected_branches, :dependent => :destroy
23 25  
  26 + #
  27 + # Protected attributes
  28 + #
24 29 attr_protected :private_flag, :owner_id
25 30  
  31 + #
  32 + # Scopes
  33 + #
26 34 scope :public_only, where(:private_flag => false)
27 35 scope :without_user, lambda { |user| where("id not in (:ids)", :ids => user.projects.map(&:id) ) }
28 36  
... ... @@ -30,29 +38,63 @@ class Project &lt; ActiveRecord::Base
30 38 joins(:issues, :notes, :merge_requests).order("issues.created_at, notes.created_at, merge_requests.created_at DESC")
31 39 end
32 40  
33   - def self.access_options
34   - UsersProject.access_roles
35   - end
36   -
37 41 def self.search query
38 42 where("name like :query or code like :query or path like :query", :query => "%#{query}%")
39 43 end
40 44  
41   - def to_param
42   - code
  45 + #
  46 + # Validations
  47 + #
  48 + validates :name,
  49 + :uniqueness => true,
  50 + :presence => true,
  51 + :length => { :within => 0..255 }
  52 +
  53 + validates :path,
  54 + :uniqueness => true,
  55 + :presence => true,
  56 + :format => { :with => /^[a-zA-Z0-9_\-\.]*$/,
  57 + :message => "only letters, digits & '_' '-' '.' allowed" },
  58 + :length => { :within => 0..255 }
  59 +
  60 + validates :description,
  61 + :length => { :within => 0..2000 }
  62 +
  63 + validates :code,
  64 + :presence => true,
  65 + :uniqueness => true,
  66 + :format => { :with => /^[a-zA-Z0-9_\-\.]*$/,
  67 + :message => "only letters, digits & '_' '-' '.' allowed" },
  68 + :length => { :within => 1..255 }
  69 +
  70 + validates :owner, :presence => true
  71 + validate :check_limit
  72 + validate :repo_name
  73 +
  74 + def check_limit
  75 + unless owner.can_create_project?
  76 + errors[:base] << ("Your own projects limit is #{owner.projects_limit}! Please contact administrator to increase it")
  77 + end
  78 + rescue
  79 + errors[:base] << ("Cant check your ability to create project")
43 80 end
44 81  
45   - def web_url
46   - [GIT_HOST['host'], code].join("/")
  82 + def repo_name
  83 + if path == "gitolite-admin"
  84 + errors.add(:path, " like 'gitolite-admin' is not allowed")
  85 + end
  86 + end
  87 +
  88 + def self.access_options
  89 + UsersProject.access_roles
47 90 end
48 91  
49   - def team_member_by_name_or_email(email = nil, name = nil)
50   - user = users.where("email like ? or name like ?", email, name).first
51   - users_projects.find_by_user_id(user.id) if user
  92 + def to_param
  93 + code
52 94 end
53 95  
54   - def team_member_by_id(user_id)
55   - users_projects.find_by_user_id(user_id)
  96 + def web_url
  97 + [GIT_HOST['host'], code].join("/")
56 98 end
57 99  
58 100 def common_notes
... ...
app/models/project/hooks_trait.rb
... ... @@ -1,109 +0,0 @@
1   -module Project::HooksTrait
2   - as_trait do
3   - def observe_push(oldrev, newrev, ref, user)
4   - data = post_receive_data(oldrev, newrev, ref, user)
5   -
6   - Event.create(
7   - :project => self,
8   - :action => Event::Pushed,
9   - :data => data,
10   - :author_id => data[:user_id]
11   - )
12   - end
13   -
14   - def update_merge_requests(oldrev, newrev, ref, user)
15   - return true unless ref =~ /heads/
16   - branch_name = ref.gsub("refs/heads/", "")
17   - c_ids = self.commits_between(oldrev, newrev).map(&:id)
18   -
19   - # Update code for merge requests
20   - mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all
21   - mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }
22   -
23   - # Close merge requests
24   - mrs = self.merge_requests.opened.where(:target_branch => branch_name).all
25   - mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) }
26   - mrs.each { |merge_request| merge_request.merge!(user.id) }
27   -
28   - true
29   - end
30   -
31   - def execute_web_hooks(oldrev, newrev, ref, user)
32   - ref_parts = ref.split('/')
33   -
34   - # Return if this is not a push to a branch (e.g. new commits)
35   - return if ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000"
36   -
37   - data = post_receive_data(oldrev, newrev, ref, user)
38   -
39   - web_hooks.each { |web_hook| web_hook.execute(data) }
40   - end
41   -
42   - def post_receive_data(oldrev, newrev, ref, user)
43   -
44   - push_commits = commits_between(oldrev, newrev)
45   -
46   - # Total commits count
47   - push_commits_count = push_commits.size
48   -
49   - # Get latest 20 commits ASC
50   - push_commits_limited = push_commits.last(20)
51   -
52   - # Hash to be passed as post_receive_data
53   - data = {
54   - before: oldrev,
55   - after: newrev,
56   - ref: ref,
57   - user_id: user.id,
58   - user_name: user.name,
59   - repository: {
60   - name: name,
61   - url: web_url,
62   - description: description,
63   - homepage: web_url,
64   - },
65   - commits: [],
66   - total_commits_count: push_commits_count
67   - }
68   -
69   - # For perfomance purposes maximum 20 latest commits
70   - # will be passed as post receive hook data.
71   - #
72   - push_commits_limited.each do |commit|
73   - data[:commits] << {
74   - id: commit.id,
75   - message: commit.safe_message,
76   - timestamp: commit.date.xmlschema,
77   - url: "http://#{GIT_HOST['host']}/#{code}/commits/#{commit.id}",
78   - author: {
79   - name: commit.author_name,
80   - email: commit.author_email
81   - }
82   - }
83   - end
84   -
85   - data
86   - end
87   -
88   -
89   - # This method will be called after each post receive
90   - # and only if autor_key_id present in gitlab.
91   - # All callbacks for post receive should be placed here
92   - #
93   - def trigger_post_receive(oldrev, newrev, ref, author_key_id)
94   - user = Key.find_by_identifier(author_key_id).user
95   -
96   - # Create push event
97   - self.observe_push(oldrev, newrev, ref, user)
98   -
99   - # Close merged MR
100   - self.update_merge_requests(oldrev, newrev, ref, user)
101   -
102   - # Execute web hooks
103   - self.execute_web_hooks(oldrev, newrev, ref, user)
104   -
105   - # Create satellite
106   - self.satellite.create unless self.satellite.exists?
107   - end
108   - end
109   -end
app/models/project/permissions_trait.rb
... ... @@ -1,60 +0,0 @@
1   -module Project::PermissionsTrait
2   - as_trait do
3   - # Compatible with all access rights
4   - # Should be rewrited for new access rights
5   - def add_access(user, *access)
6   - access = if access.include?(:admin)
7   - { :project_access => UsersProject::MASTER }
8   - elsif access.include?(:write)
9   - { :project_access => UsersProject::DEVELOPER }
10   - else
11   - { :project_access => UsersProject::REPORTER }
12   - end
13   - opts = { :user => user }
14   - opts.merge!(access)
15   - users_projects.create(opts)
16   - end
17   -
18   - def reset_access(user)
19   - users_projects.where(:project_id => self.id, :user_id => user.id).destroy if self.id
20   - end
21   -
22   - def repository_readers
23   - keys = Key.joins({:user => :users_projects}).
24   - where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::REPORTER)
25   - keys.map(&:identifier) + deploy_keys.map(&:identifier)
26   - end
27   -
28   - def repository_writers
29   - keys = Key.joins({:user => :users_projects}).
30   - where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::DEVELOPER)
31   - keys.map(&:identifier)
32   - end
33   -
34   - def repository_masters
35   - keys = Key.joins({:user => :users_projects}).
36   - where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::MASTER)
37   - keys.map(&:identifier)
38   - end
39   -
40   - def allow_read_for?(user)
41   - !users_projects.where(:user_id => user.id).empty?
42   - end
43   -
44   - def guest_access_for?(user)
45   - !users_projects.where(:user_id => user.id).empty?
46   - end
47   -
48   - def report_access_for?(user)
49   - !users_projects.where(:user_id => user.id, :project_access => [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
50   - end
51   -
52   - def dev_access_for?(user)
53   - !users_projects.where(:user_id => user.id, :project_access => [UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
54   - end
55   -
56   - def master_access_for?(user)
57   - !users_projects.where(:user_id => user.id, :project_access => [UsersProject::MASTER]).empty? || owner_id == user.id
58   - end
59   - end
60   -end
app/models/project/repository_trait.rb
... ... @@ -1,122 +0,0 @@
1   -module Project::RepositoryTrait
2   - as_trait do
3   - def valid_repo?
4   - repo
5   - rescue
6   - errors.add(:path, "Invalid repository path")
7   - false
8   - end
9   -
10   - def commit(commit_id = nil)
11   - Commit.find_or_first(repo, commit_id, root_ref)
12   - end
13   -
14   - def fresh_commits(n = 10)
15   - Commit.fresh_commits(repo, n)
16   - end
17   -
18   - def commits_with_refs(n = 20)
19   - Commit.commits_with_refs(repo, n)
20   - end
21   -
22   - def commits_since(date)
23   - Commit.commits_since(repo, date)
24   - end
25   -
26   - def commits(ref, path = nil, limit = nil, offset = nil)
27   - Commit.commits(repo, ref, path, limit, offset)
28   - end
29   -
30   - def commits_between(from, to)
31   - Commit.commits_between(repo, from, to)
32   - end
33   -
34   - def write_hooks
35   - %w(post-receive).each do |hook|
36   - write_hook(hook, File.read(File.join(Rails.root, 'lib', "#{hook}-hook")))
37   - end
38   - end
39   -
40   - def satellite
41   - @satellite ||= Gitlab::Satellite.new(self)
42   - end
43   -
44   - def write_hook(name, content)
45   - hook_file = File.join(path_to_repo, 'hooks', name)
46   -
47   - File.open(hook_file, 'w') do |f|
48   - f.write(content)
49   - end
50   -
51   - File.chmod(0775, hook_file)
52   - end
53   -
54   - def has_post_receive_file?
55   - hook_file = File.join(path_to_repo, 'hooks', 'post-receive')
56   - File.exists?(hook_file)
57   - end
58   -
59   - def tags
60   - repo.tags.map(&:name).sort.reverse
61   - end
62   -
63   - def repo
64   - @repo ||= Grit::Repo.new(path_to_repo)
65   - end
66   -
67   - def url_to_repo
68   - Gitlab::GitHost.url_to_repo(path)
69   - end
70   -
71   - def path_to_repo
72   - File.join(GIT_HOST["base_path"], "#{path}.git")
73   - end
74   -
75   - def update_repository
76   - Gitlab::GitHost.system.update_project(path, self)
77   -
78   - write_hooks if File.exists?(path_to_repo)
79   - end
80   -
81   - def destroy_repository
82   - Gitlab::GitHost.system.destroy_project(self)
83   - end
84   -
85   - def repo_exists?
86   - @repo_exists ||= (repo && !repo.branches.empty?)
87   - rescue
88   - @repo_exists = false
89   - end
90   -
91   - def heads
92   - @heads ||= repo.heads
93   - end
94   -
95   - def tree(fcommit, path = nil)
96   - fcommit = commit if fcommit == :head
97   - tree = fcommit.tree
98   - path ? (tree / path) : tree
99   - end
100   -
101   - def open_branches
102   - if protected_branches.empty?
103   - self.repo.heads
104   - else
105   - pnames = protected_branches.map(&:name)
106   - self.repo.heads.reject { |h| pnames.include?(h.name) }
107   - end.sort_by(&:name)
108   - end
109   -
110   - def has_commits?
111   - !!commit
112   - end
113   -
114   - def root_ref
115   - default_branch || "master"
116   - end
117   -
118   - def root_ref? branch
119   - root_ref == branch
120   - end
121   - end
122   -end
app/models/project/validations_trait.rb
... ... @@ -1,43 +0,0 @@
1   -module Project::ValidationsTrait
2   - as_trait do
3   - validates :name,
4   - :uniqueness => true,
5   - :presence => true,
6   - :length => { :within => 0..255 }
7   -
8   - validates :path,
9   - :uniqueness => true,
10   - :presence => true,
11   - :format => { :with => /^[a-zA-Z0-9_\-\.]*$/,
12   - :message => "only letters, digits & '_' '-' '.' allowed" },
13   - :length => { :within => 0..255 }
14   -
15   - validates :description,
16   - :length => { :within => 0..2000 }
17   -
18   - validates :code,
19   - :presence => true,
20   - :uniqueness => true,
21   - :format => { :with => /^[a-zA-Z0-9_\-\.]*$/,
22   - :message => "only letters, digits & '_' '-' '.' allowed" },
23   - :length => { :within => 1..255 }
24   -
25   - validates :owner, :presence => true
26   - validate :check_limit
27   - validate :repo_name
28   -
29   - def check_limit
30   - unless owner.can_create_project?
31   - errors[:base] << ("Your own projects limit is #{owner.projects_limit}! Please contact administrator to increase it")
32   - end
33   - rescue
34   - errors[:base] << ("Cant check your ability to create project")
35   - end
36   -
37   - def repo_name
38   - if path == "gitolite-admin"
39   - errors.add(:path, " like 'gitolite-admin' is not allowed")
40   - end
41   - end
42   - end
43   -end
app/models/user.rb
1 1 class User < ActiveRecord::Base
  2 + include Account
  3 +
2 4 devise :database_authenticatable, :token_authenticatable,
3 5 :recoverable, :rememberable, :trackable, :validatable, :omniauthable
4 6  
... ... @@ -65,30 +67,6 @@ class User &lt; ActiveRecord::Base
65 67 where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)')
66 68 end
67 69  
68   - def identifier
69   - email.gsub /[@.]/, "_"
70   - end
71   -
72   - def is_admin?
73   - admin
74   - end
75   -
76   - def require_ssh_key?
77   - keys.count == 0
78   - end
79   -
80   - def can_create_project?
81   - projects_limit > my_own_projects.count
82   - end
83   -
84   - def last_activity_project
85   - projects.first
86   - end
87   -
88   - def first_name
89   - name.split.first unless name.blank?
90   - end
91   -
92 70 def self.find_for_ldap_auth(omniauth_info)
93 71 name = omniauth_info.name.force_encoding("utf-8")
94 72 email = omniauth_info.email.downcase
... ... @@ -105,30 +83,6 @@ class User &lt; ActiveRecord::Base
105 83 )
106 84 end
107 85 end
108   -
109   - def cared_merge_requests
110   - MergeRequest.where("author_id = :id or assignee_id = :id", :id => self.id).opened
111   - end
112   -
113   - def project_ids
114   - projects.map(&:id)
115   - end
116   -
117   - # Remove user from all projects and
118   - # set blocked attribute to true
119   - def block
120   - users_projects.all.each do |membership|
121   - return false unless membership.destroy
122   - end
123   -
124   - self.blocked = true
125   - save
126   - end
127   -
128   - def projects_limit_percent
129   - return 100 if projects_limit.zero?
130   - (my_own_projects.count.to_f / projects_limit) * 100
131   - end
132 86 end
133 87 # == Schema Information
134 88 #
... ...
app/roles/account.rb 0 → 100644
... ... @@ -0,0 +1,49 @@
  1 +module Account
  2 + def identifier
  3 + email.gsub /[@.]/, "_"
  4 + end
  5 +
  6 + def is_admin?
  7 + admin
  8 + end
  9 +
  10 + def require_ssh_key?
  11 + keys.count == 0
  12 + end
  13 +
  14 + def can_create_project?
  15 + projects_limit > my_own_projects.count
  16 + end
  17 +
  18 + def last_activity_project
  19 + projects.first
  20 + end
  21 +
  22 + def first_name
  23 + name.split.first unless name.blank?
  24 + end
  25 +
  26 + def cared_merge_requests
  27 + MergeRequest.where("author_id = :id or assignee_id = :id", :id => self.id).opened
  28 + end
  29 +
  30 + def project_ids
  31 + projects.map(&:id)
  32 + end
  33 +
  34 + # Remove user from all projects and
  35 + # set blocked attribute to true
  36 + def block
  37 + users_projects.all.each do |membership|
  38 + return false unless membership.destroy
  39 + end
  40 +
  41 + self.blocked = true
  42 + save
  43 + end
  44 +
  45 + def projects_limit_percent
  46 + return 100 if projects_limit.zero?
  47 + (my_own_projects.count.to_f / projects_limit) * 100
  48 + end
  49 +end
... ...
app/roles/authority.rb 0 → 100644
... ... @@ -0,0 +1,58 @@
  1 +module Authority
  2 + # Compatible with all access rights
  3 + # Should be rewrited for new access rights
  4 + def add_access(user, *access)
  5 + access = if access.include?(:admin)
  6 + { :project_access => UsersProject::MASTER }
  7 + elsif access.include?(:write)
  8 + { :project_access => UsersProject::DEVELOPER }
  9 + else
  10 + { :project_access => UsersProject::REPORTER }
  11 + end
  12 + opts = { :user => user }
  13 + opts.merge!(access)
  14 + users_projects.create(opts)
  15 + end
  16 +
  17 + def reset_access(user)
  18 + users_projects.where(:project_id => self.id, :user_id => user.id).destroy if self.id
  19 + end
  20 +
  21 + def repository_readers
  22 + keys = Key.joins({:user => :users_projects}).
  23 + where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::REPORTER)
  24 + keys.map(&:identifier) + deploy_keys.map(&:identifier)
  25 + end
  26 +
  27 + def repository_writers
  28 + keys = Key.joins({:user => :users_projects}).
  29 + where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::DEVELOPER)
  30 + keys.map(&:identifier)
  31 + end
  32 +
  33 + def repository_masters
  34 + keys = Key.joins({:user => :users_projects}).
  35 + where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::MASTER)
  36 + keys.map(&:identifier)
  37 + end
  38 +
  39 + def allow_read_for?(user)
  40 + !users_projects.where(:user_id => user.id).empty?
  41 + end
  42 +
  43 + def guest_access_for?(user)
  44 + !users_projects.where(:user_id => user.id).empty?
  45 + end
  46 +
  47 + def report_access_for?(user)
  48 + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
  49 + end
  50 +
  51 + def dev_access_for?(user)
  52 + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
  53 + end
  54 +
  55 + def master_access_for?(user)
  56 + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::MASTER]).empty? || owner_id == user.id
  57 + end
  58 +end
... ...
app/roles/git_merge.rb 0 → 100644
... ... @@ -0,0 +1,2 @@
  1 +module GitMerge
  2 +end
... ...
app/roles/git_push.rb 0 → 100644
... ... @@ -0,0 +1,107 @@
  1 +module GitPush
  2 + def observe_push(oldrev, newrev, ref, user)
  3 + data = post_receive_data(oldrev, newrev, ref, user)
  4 +
  5 + Event.create(
  6 + :project => self,
  7 + :action => Event::Pushed,
  8 + :data => data,
  9 + :author_id => data[:user_id]
  10 + )
  11 + end
  12 +
  13 + def update_merge_requests(oldrev, newrev, ref, user)
  14 + return true unless ref =~ /heads/
  15 + branch_name = ref.gsub("refs/heads/", "")
  16 + c_ids = self.commits_between(oldrev, newrev).map(&:id)
  17 +
  18 + # Update code for merge requests
  19 + mrs = self.merge_requests.opened.find_all_by_branch(branch_name).all
  20 + mrs.each { |merge_request| merge_request.reload_code; merge_request.mark_as_unchecked }
  21 +
  22 + # Close merge requests
  23 + mrs = self.merge_requests.opened.where(:target_branch => branch_name).all
  24 + mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) }
  25 + mrs.each { |merge_request| merge_request.merge!(user.id) }
  26 +
  27 + true
  28 + end
  29 +
  30 + def execute_web_hooks(oldrev, newrev, ref, user)
  31 + ref_parts = ref.split('/')
  32 +
  33 + # Return if this is not a push to a branch (e.g. new commits)
  34 + return if ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000"
  35 +
  36 + data = post_receive_data(oldrev, newrev, ref, user)
  37 +
  38 + web_hooks.each { |web_hook| web_hook.execute(data) }
  39 + end
  40 +
  41 + def post_receive_data(oldrev, newrev, ref, user)
  42 +
  43 + push_commits = commits_between(oldrev, newrev)
  44 +
  45 + # Total commits count
  46 + push_commits_count = push_commits.size
  47 +
  48 + # Get latest 20 commits ASC
  49 + push_commits_limited = push_commits.last(20)
  50 +
  51 + # Hash to be passed as post_receive_data
  52 + data = {
  53 + before: oldrev,
  54 + after: newrev,
  55 + ref: ref,
  56 + user_id: user.id,
  57 + user_name: user.name,
  58 + repository: {
  59 + name: name,
  60 + url: web_url,
  61 + description: description,
  62 + homepage: web_url,
  63 + },
  64 + commits: [],
  65 + total_commits_count: push_commits_count
  66 + }
  67 +
  68 + # For perfomance purposes maximum 20 latest commits
  69 + # will be passed as post receive hook data.
  70 + #
  71 + push_commits_limited.each do |commit|
  72 + data[:commits] << {
  73 + id: commit.id,
  74 + message: commit.safe_message,
  75 + timestamp: commit.date.xmlschema,
  76 + url: "http://#{GIT_HOST['host']}/#{code}/commits/#{commit.id}",
  77 + author: {
  78 + name: commit.author_name,
  79 + email: commit.author_email
  80 + }
  81 + }
  82 + end
  83 +
  84 + data
  85 + end
  86 +
  87 +
  88 + # This method will be called after each post receive
  89 + # and only if autor_key_id present in gitlab.
  90 + # All callbacks for post receive should be placed here
  91 + #
  92 + def trigger_post_receive(oldrev, newrev, ref, author_key_id)
  93 + user = Key.find_by_identifier(author_key_id).user
  94 +
  95 + # Create push event
  96 + self.observe_push(oldrev, newrev, ref, user)
  97 +
  98 + # Close merged MR
  99 + self.update_merge_requests(oldrev, newrev, ref, user)
  100 +
  101 + # Execute web hooks
  102 + self.execute_web_hooks(oldrev, newrev, ref, user)
  103 +
  104 + # Create satellite
  105 + self.satellite.create unless self.satellite.exists?
  106 + end
  107 +end
... ...
app/roles/push_event.rb 0 → 100644
... ... @@ -0,0 +1,90 @@
  1 +module PushEvent
  2 + def valid_push?
  3 + data[:ref]
  4 + rescue => ex
  5 + false
  6 + end
  7 +
  8 + def tag?
  9 + data[:ref]["refs/tags"]
  10 + end
  11 +
  12 + def new_branch?
  13 + commit_from =~ /^00000/
  14 + end
  15 +
  16 + def new_ref?
  17 + commit_from =~ /^00000/
  18 + end
  19 +
  20 + def rm_ref?
  21 + commit_to =~ /^00000/
  22 + end
  23 +
  24 + def md_ref?
  25 + !(rm_ref? || new_ref?)
  26 + end
  27 +
  28 + def commit_from
  29 + data[:before]
  30 + end
  31 +
  32 + def commit_to
  33 + data[:after]
  34 + end
  35 +
  36 + def ref_name
  37 + if tag?
  38 + tag_name
  39 + else
  40 + branch_name
  41 + end
  42 + end
  43 +
  44 + def branch_name
  45 + @branch_name ||= data[:ref].gsub("refs/heads/", "")
  46 + end
  47 +
  48 + def tag_name
  49 + @tag_name ||= data[:ref].gsub("refs/tags/", "")
  50 + end
  51 +
  52 + # Max 20 commits from push DESC
  53 + def commits
  54 + @commits ||= data[:commits].map { |commit| project.commit(commit[:id]) }.reverse
  55 + end
  56 +
  57 + def commits_count
  58 + data[:total_commits_count] || commits.count || 0
  59 + end
  60 +
  61 + def ref_type
  62 + tag? ? "tag" : "branch"
  63 + end
  64 +
  65 + def push_action_name
  66 + if new_ref?
  67 + "pushed new"
  68 + elsif rm_ref?
  69 + "removed #{ref_type}"
  70 + else
  71 + "pushed to"
  72 + end
  73 + end
  74 +
  75 + def parent_commit
  76 + project.commit(commit_from)
  77 + rescue => ex
  78 + nil
  79 + end
  80 +
  81 + def last_commit
  82 + project.commit(commit_to)
  83 + rescue => ex
  84 + nil
  85 + end
  86 +
  87 + def push_with_commits?
  88 + md_ref? && commits.any? && parent_commit && last_commit
  89 + end
  90 +end
... ...
app/roles/repository.rb 0 → 100644
... ... @@ -0,0 +1,120 @@
  1 +module Repository
  2 + def valid_repo?
  3 + repo
  4 + rescue
  5 + errors.add(:path, "Invalid repository path")
  6 + false
  7 + end
  8 +
  9 + def commit(commit_id = nil)
  10 + Commit.find_or_first(repo, commit_id, root_ref)
  11 + end
  12 +
  13 + def fresh_commits(n = 10)
  14 + Commit.fresh_commits(repo, n)
  15 + end
  16 +
  17 + def commits_with_refs(n = 20)
  18 + Commit.commits_with_refs(repo, n)
  19 + end
  20 +
  21 + def commits_since(date)
  22 + Commit.commits_since(repo, date)
  23 + end
  24 +
  25 + def commits(ref, path = nil, limit = nil, offset = nil)
  26 + Commit.commits(repo, ref, path, limit, offset)
  27 + end
  28 +
  29 + def commits_between(from, to)
  30 + Commit.commits_between(repo, from, to)
  31 + end
  32 +
  33 + def write_hooks
  34 + %w(post-receive).each do |hook|
  35 + write_hook(hook, File.read(File.join(Rails.root, 'lib', "#{hook}-hook")))
  36 + end
  37 + end
  38 +
  39 + def satellite
  40 + @satellite ||= Gitlab::Satellite.new(self)
  41 + end
  42 +
  43 + def write_hook(name, content)
  44 + hook_file = File.join(path_to_repo, 'hooks', name)
  45 +
  46 + File.open(hook_file, 'w') do |f|
  47 + f.write(content)
  48 + end
  49 +
  50 + File.chmod(0775, hook_file)
  51 + end
  52 +
  53 + def has_post_receive_file?
  54 + hook_file = File.join(path_to_repo, 'hooks', 'post-receive')
  55 + File.exists?(hook_file)
  56 + end
  57 +
  58 + def tags
  59 + repo.tags.map(&:name).sort.reverse
  60 + end
  61 +
  62 + def repo
  63 + @repo ||= Grit::Repo.new(path_to_repo)
  64 + end
  65 +
  66 + def url_to_repo
  67 + Gitlab::GitHost.url_to_repo(path)
  68 + end
  69 +
  70 + def path_to_repo
  71 + File.join(GIT_HOST["base_path"], "#{path}.git")
  72 + end
  73 +
  74 + def update_repository
  75 + Gitlab::GitHost.system.update_project(path, self)
  76 +
  77 + write_hooks if File.exists?(path_to_repo)
  78 + end
  79 +
  80 + def destroy_repository
  81 + Gitlab::GitHost.system.destroy_project(self)
  82 + end
  83 +
  84 + def repo_exists?
  85 + @repo_exists ||= (repo && !repo.branches.empty?)
  86 + rescue
  87 + @repo_exists = false
  88 + end
  89 +
  90 + def heads
  91 + @heads ||= repo.heads
  92 + end
  93 +
  94 + def tree(fcommit, path = nil)
  95 + fcommit = commit if fcommit == :head
  96 + tree = fcommit.tree
  97 + path ? (tree / path) : tree
  98 + end
  99 +
  100 + def open_branches
  101 + if protected_branches.empty?
  102 + self.repo.heads
  103 + else
  104 + pnames = protected_branches.map(&:name)
  105 + self.repo.heads.reject { |h| pnames.include?(h.name) }
  106 + end.sort_by(&:name)
  107 + end
  108 +
  109 + def has_commits?
  110 + !!commit
  111 + end
  112 +
  113 + def root_ref
  114 + default_branch || "master"
  115 + end
  116 +
  117 + def root_ref? branch
  118 + root_ref == branch
  119 + end
  120 +end
... ...
app/roles/ssh_key.rb 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +module SshKey
  2 + def update_repository
  3 + Gitlab::GitHost.system.new.configure do |c|
  4 + c.update_keys(identifier, key)
  5 + c.update_projects(projects)
  6 + end
  7 + end
  8 +
  9 + def repository_delete_key
  10 + Gitlab::GitHost.system.new.configure do |c|
  11 + #delete key file is there is no identically deploy keys
  12 + if !is_deploy_key || Key.where(:identifier => identifier).count() == 0
  13 + c.delete_key(identifier)
  14 + end
  15 + c.update_projects(projects)
  16 + end
  17 + end
  18 +end
... ...
app/roles/team.rb 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +module Team
  2 + def team_member_by_name_or_email(email = nil, name = nil)
  3 + user = users.where("email like ? or name like ?", email, name).first
  4 + users_projects.find_by_user_id(user.id) if user
  5 + end
  6 +
  7 + def team_member_by_id(user_id)
  8 + users_projects.find_by_user_id(user_id)
  9 + end
  10 +end
... ...
app/roles/upvote.rb 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +module Upvote
  2 + # Return the number of +1 comments (upvotes)
  3 + def upvotes
  4 + notes.select(&:upvote?).size
  5 + end
  6 +end
... ...