Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Tatuya Kamada
gitlab-ce
Commits
cac77234
Commit
cac77234
authored
Jan 02, 2013
by
Dmitriy Zaporozhets
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Get rid of roles
parent
1b25a8f4
Changes
20
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
744 additions
and
821 deletions
+744
-821
app/models/event.rb
app/models/event.rb
+135
-0
app/models/project.rb
app/models/project.rb
+511
-5
app/models/user.rb
app/models/user.rb
+88
-2
app/roles/account.rb
app/roles/account.rb
+0
-95
app/roles/authority.rb
app/roles/authority.rb
+0
-68
app/roles/namespaced_project.rb
app/roles/namespaced_project.rb
+0
-60
app/roles/note_event.rb
app/roles/note_event.rb
+0
-43
app/roles/push_event.rb
app/roles/push_event.rb
+0
-106
app/roles/push_observer.rb
app/roles/push_observer.rb
+0
-149
app/roles/repository.rb
app/roles/repository.rb
+0
-216
app/roles/team.rb
app/roles/team.rb
+0
-63
lib/git_host.rb
lib/git_host.rb
+0
-0
lib/issue_commonality.rb
lib/issue_commonality.rb
+0
-1
lib/static_model.rb
lib/static_model.rb
+0
-0
lib/votes.rb
lib/votes.rb
+0
-0
spec/lib/issue_commonality_spec.rb
spec/lib/issue_commonality_spec.rb
+0
-0
spec/lib/votes_spec.rb
spec/lib/votes_spec.rb
+0
-0
spec/models/project_repository_spec.rb
spec/models/project_repository_spec.rb
+0
-0
spec/models/user_spec.rb
spec/models/user_spec.rb
+10
-0
spec/roles/account_role_spec.rb
spec/roles/account_role_spec.rb
+0
-13
No files found.
app/models/event.rb
View file @
cac77234
...
...
@@ -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
app/models/project.rb
View file @
cac77234
...
...
@@ -21,11 +21,7 @@
require
"grit"
class
Project
<
ActiveRecord
::
Base
include
Repository
include
PushObserver
include
Authority
include
Team
include
NamespacedProject
include
GitHost
class
TransferError
<
StandardError
;
end
...
...
@@ -277,4 +273,514 @@ class Project < ActiveRecord::Base
creator
end
end
def
team_member_by_name_or_email
(
name
=
nil
,
email
=
nil
)
user
=
users
.
where
(
"name like ? or email like ?"
,
name
,
email
).
first
users_projects
.
where
(
user:
user
)
if
user
end
# Get Team Member record by user id
def
team_member_by_id
(
user_id
)
users_projects
.
find_by_user_id
(
user_id
)
end
# Add user to project
# with passed access role
def
add_user_to_team
(
user
,
access_role
)
add_user_id_to_team
(
user
.
id
,
access_role
)
end
# Add multiple users to project
# with same access role
def
add_users_to_team
(
users
,
access_role
)
add_users_ids_to_team
(
users
.
map
(
&
:id
),
access_role
)
end
# Add user to project
# with passed access role by user id
def
add_user_id_to_team
(
user_id
,
access_role
)
users_projects
.
create
(
user_id:
user_id
,
project_access:
access_role
)
end
# Add multiple users to project
# with same access role by user ids
def
add_users_ids_to_team
(
users_ids
,
access_role
)
UsersProject
.
bulk_import
(
self
,
users_ids
,
access_role
)
end
# Update multiple project users
# to same access role by user ids
def
update_users_ids_to_role
(
users_ids
,
access_role
)
UsersProject
.
bulk_update
(
self
,
users_ids
,
access_role
)
end
# Delete multiple users from project by user ids
def
delete_users_ids_from_team
(
users_ids
)
UsersProject
.
bulk_delete
(
self
,
users_ids
)
end
# Remove all users from project team
def
truncate_team
UsersProject
.
truncate_team
(
self
)
end
# 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
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
# 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
]
<<
{
id:
commit
.
id
,
message:
commit
.
safe_message
,
timestamp:
commit
.
date
.
xmlschema
,
url:
"
#{
Gitlab
.
config
.
gitlab
.
url
}
/
#{
path_with_namespace
}
/commit/
#{
commit
.
id
}
"
,
author:
{
name:
commit
.
author_name
,
email:
commit
.
author_email
}
}
end
data
end
def
update_merge_requests
(
oldrev
,
newrev
,
ref
,
user
)
return
true
unless
ref
=~
/heads/
branch_name
=
ref
.
gsub
(
"refs/heads/"
,
""
)
c_ids
=
self
.
commits_between
(
oldrev
,
newrev
).
map
(
&
:id
)
# Update code for merge requests
mrs
=
self
.
merge_requests
.
opened
.
find_all_by_branch
(
branch_name
).
all
mrs
.
each
{
|
merge_request
|
merge_request
.
reload_code
;
merge_request
.
mark_as_unchecked
}
# Close merge requests
mrs
=
self
.
merge_requests
.
opened
.
where
(
target_branch:
branch_name
).
all
mrs
=
mrs
.
select
(
&
:last_commit
).
select
{
|
mr
|
c_ids
.
include?
(
mr
.
last_commit
.
id
)
}
mrs
.
each
{
|
merge_request
|
merge_request
.
merge!
(
user
.
id
)
}
true
end
def
valid_repo?
repo
rescue
errors
.
add
(
:path
,
"Invalid repository path"
)
false
end
def
empty_repo?
!
repo_exists?
||
!
has_commits?
end
def
commit
(
commit_id
=
nil
)
Commit
.
find_or_first
(
repo
,
commit_id
,
root_ref
)
end
def
fresh_commits
(
n
=
10
)
Commit
.
fresh_commits
(
repo
,
n
)
end
def
commits_with_refs
(
n
=
20
)
Commit
.
commits_with_refs
(
repo
,
n
)
end
def
commits_since
(
date
)
Commit
.
commits_since
(
repo
,
date
)
end
def
commits
(
ref
,
path
=
nil
,
limit
=
nil
,
offset
=
nil
)
Commit
.
commits
(
repo
,
ref
,
path
,
limit
,
offset
)
end
def
last_commit_for
(
ref
,
path
=
nil
)
commits
(
ref
,
path
,
1
).
first
end
def
commits_between
(
from
,
to
)
Commit
.
commits_between
(
repo
,
from
,
to
)
end
def
satellite
@satellite
||=
Gitlab
::
Satellite
::
Satellite
.
new
(
self
)
end
def
has_post_receive_file?
!!
hook_file
end
def
valid_post_receive_file?
valid_hook_file
==
hook_file
end
def
valid_hook_file
@valid_hook_file
||=
File
.
read
(
Rails
.
root
.
join
(
'lib'
,
'hooks'
,
'post-receive'
))
end
def
hook_file
@hook_file
||=
begin
hook_path
=
File
.
join
(
path_to_repo
,
'hooks'
,
'post-receive'
)
File
.
read
(
hook_path
)
if
File
.
exists?
(
hook_path
)
end
end
# Returns an Array of branch names
def
branch_names
repo
.
branches
.
collect
(
&
:name
).
sort
end
# Returns an Array of Branches
def
branches
repo
.
branches
.
sort_by
(
&
:name
)
end
# Returns an Array of tag names
def
tag_names
repo
.
tags
.
collect
(
&
:name
).
sort
.
reverse
end
# Returns an Array of Tags
def
tags
repo
.
tags
.
sort_by
(
&
:name
).
reverse
end
# Returns an Array of branch and tag names
def
ref_names
[
branch_names
+
tag_names
].
flatten
end
def
repo
@repo
||=
Grit
::
Repo
.
new
(
path_to_repo
)
end
def
url_to_repo
git_host
.
url_to_repo
(
path_with_namespace
)
end
def
path_to_repo
File
.
join
(
Gitlab
.
config
.
gitolite
.
repos_path
,
"
#{
path_with_namespace
}
.git"
)
end
def
namespace_dir
namespace
.
try
(
:path
)
||
''
end
def
update_repository
git_host
.
update_repository
(
self
)
end
def
destroy_repository
git_host
.
remove_repository
(
self
)
end
def
repo_exists?
@repo_exists
||=
(
repo
&&
!
repo
.
branches
.
empty?
)
rescue
@repo_exists
=
false
end
def
heads
@heads
||=
repo
.
heads
end
def
tree
(
fcommit
,
path
=
nil
)
fcommit
=
commit
if
fcommit
==
:head
tree
=
fcommit
.
tree
path
?
(
tree
/
path
)
:
tree
end
def
open_branches
if
protected_branches
.
empty?
self
.
repo
.
heads
else
pnames
=
protected_branches
.
map
(
&
:name
)
self
.
repo
.
heads
.
reject
{
|
h
|
pnames
.
include?
(
h
.
name
)
}
end
.
sort_by
(
&
:name
)
end
# Discovers the default branch based on the repository's available branches
#
# - If no branches are present, returns nil
# - If one branch is present, returns its name
# - If two or more branches are present, returns the one that has a name
# matching root_ref (default_branch or 'master' if default_branch is nil)
def
discover_default_branch
if
branch_names
.
length
==
0
nil
elsif
branch_names
.
length
==
1
branch_names
.
first
else
branch_names
.
select
{
|
v
|
v
==
root_ref
}.
first
end
end
def
has_commits?
!!
commit
rescue
Grit
::
NoSuchPathError
false
end
def
root_ref
default_branch
||
"master"
end
def
root_ref?
(
branch
)
root_ref
==
branch
end
# Archive Project to .tar.gz
#
# Already packed repo archives stored at
# app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
#
def
archive_repo
(
ref
)
ref
=
ref
||
self
.
root_ref
commit
=
self
.
commit
(
ref
)
return
nil
unless
commit
# Build file path
file_name
=
self
.
path
+
"-"
+
commit
.
id
.
to_s
+
".tar.gz"
storage_path
=
Rails
.
root
.
join
(
"tmp"
,
"repositories"
,
self
.
path_with_namespace
)
file_path
=
File
.
join
(
storage_path
,
file_name
)
# Put files into a directory before archiving
prefix
=
self
.
path
+
"/"
# Create file if not exists
unless
File
.
exists?
(
file_path
)
FileUtils
.
mkdir_p
storage_path
file
=
self
.
repo
.
archive_to_file
(
ref
,
prefix
,
file_path
)
end
file_path
end
def
ssh_url_to_repo
url_to_repo
end
def
http_url_to_repo
http_url
=
[
Gitlab
.
config
.
gitlab
.
url
,
"/"
,
path_with_namespace
,
".git"
].
join
(
''
)
end
# Check if current branch name is marked as protected in the system
def
protected_branch?
branch_name
protected_branches
.
map
(
&
:name
).
include?
(
branch_name
)
end
end
app/models/user.rb
View file @
cac77234
...
...
@@ -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
app/roles/account.rb
deleted
100644 → 0
View file @
1b25a8f4
# == 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
app/roles/authority.rb
deleted
100644 → 0
View file @
1b25a8f4
# == 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
app/roles/namespaced_project.rb
deleted
100644 → 0
View file @
1b25a8f4
# == 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
app/roles/note_event.rb
deleted
100644 → 0
View file @
1b25a8f4
# == 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
app/roles/push_event.rb
deleted
100644 → 0
View file @
1b25a8f4
# == 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
app/roles/push_observer.rb
deleted
100644 → 0
View file @
1b25a8f4
# == 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
]
<<
{
id:
commit
.
id
,
message:
commit
.
safe_message
,
timestamp:
commit
.
date
.
xmlschema
,
url:
"
#{
Gitlab
.
config
.
gitlab
.
url
}
/
#{
path_with_namespace
}
/commit/
#{
commit
.
id
}
"
,
author:
{
name:
commit
.
author_name
,
email:
commit
.
author_email
}
}
end
data
end
def
update_merge_requests
(
oldrev
,
newrev
,
ref
,
user
)
return
true
unless
ref
=~
/heads/
branch_name
=
ref
.
gsub
(
"refs/heads/"
,
""
)
c_ids
=
self
.
commits_between
(
oldrev
,
newrev
).
map
(
&
:id
)
# Update code for merge requests
mrs
=
self
.
merge_requests
.
opened
.
find_all_by_branch
(
branch_name
).
all
mrs
.
each
{
|
merge_request
|
merge_request
.
reload_code
;
merge_request
.
mark_as_unchecked
}
# Close merge requests
mrs
=
self
.
merge_requests
.
opened
.
where
(
target_branch:
branch_name
).
all
mrs
=
mrs
.
select
(
&
:last_commit
).
select
{
|
mr
|
c_ids
.
include?
(
mr
.
last_commit
.
id
)
}
mrs
.
each
{
|
merge_request
|
merge_request
.
merge!
(
user
.
id
)
}
true
end
end
app/roles/repository.rb
deleted
100644 → 0
View file @
1b25a8f4
# == Repository role
#
# Provides access to git repository resources like commits, branches etc..
# Allows you to manage repository via gitolite interface(git_host)
#
# Used by Project
#
module
Repository
include
GitHost
def
valid_repo?
repo
rescue
errors
.
add
(
:path
,
"Invalid repository path"
)
false
end
def
empty_repo?
!
repo_exists?
||
!
has_commits?
end
def
commit
(
commit_id
=
nil
)
Commit
.
find_or_first
(
repo
,
commit_id
,
root_ref
)
end
def
fresh_commits
(
n
=
10
)
Commit
.
fresh_commits
(
repo
,
n
)
end
def
commits_with_refs
(
n
=
20
)
Commit
.
commits_with_refs
(
repo
,
n
)
end
def
commits_since
(
date
)
Commit
.
commits_since
(
repo
,
date
)
end
def
commits
(
ref
,
path
=
nil
,
limit
=
nil
,
offset
=
nil
)
Commit
.
commits
(
repo
,
ref
,
path
,
limit
,
offset
)
end
def
last_commit_for
(
ref
,
path
=
nil
)
commits
(
ref
,
path
,
1
).
first
end
def
commits_between
(
from
,
to
)
Commit
.
commits_between
(
repo
,
from
,
to
)
end
def
satellite
@satellite
||=
Gitlab
::
Satellite
::
Satellite
.
new
(
self
)
end
def
has_post_receive_file?
!!
hook_file
end
def
valid_post_receive_file?
valid_hook_file
==
hook_file
end
def
valid_hook_file
@valid_hook_file
||=
File
.
read
(
Rails
.
root
.
join
(
'lib'
,
'hooks'
,
'post-receive'
))
end
def
hook_file
@hook_file
||=
begin
hook_path
=
File
.
join
(
path_to_repo
,
'hooks'
,
'post-receive'
)
File
.
read
(
hook_path
)
if
File
.
exists?
(
hook_path
)
end
end
# Returns an Array of branch names
def
branch_names
repo
.
branches
.
collect
(
&
:name
).
sort
end
# Returns an Array of Branches
def
branches
repo
.
branches
.
sort_by
(
&
:name
)
end
# Returns an Array of tag names
def
tag_names
repo
.
tags
.
collect
(
&
:name
).
sort
.
reverse
end
# Returns an Array of Tags
def
tags
repo
.
tags
.
sort_by
(
&
:name
).
reverse
end
# Returns an Array of branch and tag names
def
ref_names
[
branch_names
+
tag_names
].
flatten
end
def
repo
@repo
||=
Grit
::
Repo
.
new
(
path_to_repo
)
end
def
url_to_repo
git_host
.
url_to_repo
(
path_with_namespace
)
end
def
path_to_repo
File
.
join
(
Gitlab
.
config
.
gitolite
.
repos_path
,
"
#{
path_with_namespace
}
.git"
)
end
def
namespace_dir
namespace
.
try
(
:path
)
||
''
end
def
update_repository
git_host
.
update_repository
(
self
)
end
def
destroy_repository
git_host
.
remove_repository
(
self
)
end
def
repo_exists?
@repo_exists
||=
(
repo
&&
!
repo
.
branches
.
empty?
)
rescue
@repo_exists
=
false
end
def
heads
@heads
||=
repo
.
heads
end
def
tree
(
fcommit
,
path
=
nil
)
fcommit
=
commit
if
fcommit
==
:head
tree
=
fcommit
.
tree
path
?
(
tree
/
path
)
:
tree
end
def
open_branches
if
protected_branches
.
empty?
self
.
repo
.
heads
else
pnames
=
protected_branches
.
map
(
&
:name
)
self
.
repo
.
heads
.
reject
{
|
h
|
pnames
.
include?
(
h
.
name
)
}
end
.
sort_by
(
&
:name
)
end
# Discovers the default branch based on the repository's available branches
#
# - If no branches are present, returns nil
# - If one branch is present, returns its name
# - If two or more branches are present, returns the one that has a name
# matching root_ref (default_branch or 'master' if default_branch is nil)
def
discover_default_branch
if
branch_names
.
length
==
0
nil
elsif
branch_names
.
length
==
1
branch_names
.
first
else
branch_names
.
select
{
|
v
|
v
==
root_ref
}.
first
end
end
def
has_commits?
!!
commit
rescue
Grit
::
NoSuchPathError
false
end
def
root_ref
default_branch
||
"master"
end
def
root_ref?
(
branch
)
root_ref
==
branch
end
# Archive Project to .tar.gz
#
# Already packed repo archives stored at
# app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
#
def
archive_repo
(
ref
)
ref
=
ref
||
self
.
root_ref
commit
=
self
.
commit
(
ref
)
return
nil
unless
commit
# Build file path
file_name
=
self
.
path
+
"-"
+
commit
.
id
.
to_s
+
".tar.gz"
storage_path
=
Rails
.
root
.
join
(
"tmp"
,
"repositories"
,
self
.
path_with_namespace
)
file_path
=
File
.
join
(
storage_path
,
file_name
)
# Put files into a directory before archiving
prefix
=
self
.
path
+
"/"
# Create file if not exists
unless
File
.
exists?
(
file_path
)
FileUtils
.
mkdir_p
storage_path
file
=
self
.
repo
.
archive_to_file
(
ref
,
prefix
,
file_path
)
end
file_path
end
def
ssh_url_to_repo
url_to_repo
end
def
http_url_to_repo
http_url
=
[
Gitlab
.
config
.
gitlab
.
url
,
"/"
,
path_with_namespace
,
".git"
].
join
(
''
)
end
# Check if current branch name is marked as protected in the system
def
protected_branch?
branch_name
protected_branches
.
map
(
&
:name
).
include?
(
branch_name
)
end
end
app/roles/team.rb
deleted
100644 → 0
View file @
1b25a8f4
# == Team role
#
# Provides functionality to manage project team
# - add user/users to project
# - update existing membership
# - remove users from project team
#
# Used by Project
#
module
Team
def
team_member_by_name_or_email
(
name
=
nil
,
email
=
nil
)
user
=
users
.
where
(
"name like ? or email like ?"
,
name
,
email
).
first
users_projects
.
where
(
user:
user
)
if
user
end
# Get Team Member record by user id
def
team_member_by_id
(
user_id
)
users_projects
.
find_by_user_id
(
user_id
)
end
# Add user to project
# with passed access role
def
add_user_to_team
(
user
,
access_role
)
add_user_id_to_team
(
user
.
id
,
access_role
)
end
# Add multiple users to project
# with same access role
def
add_users_to_team
(
users
,
access_role
)
add_users_ids_to_team
(
users
.
map
(
&
:id
),
access_role
)
end
# Add user to project
# with passed access role by user id
def
add_user_id_to_team
(
user_id
,
access_role
)
users_projects
.
create
(
user_id:
user_id
,
project_access:
access_role
)
end
# Add multiple users to project
# with same access role by user ids
def
add_users_ids_to_team
(
users_ids
,
access_role
)
UsersProject
.
bulk_import
(
self
,
users_ids
,
access_role
)
end
# Update multiple project users
# to same access role by user ids
def
update_users_ids_to_role
(
users_ids
,
access_role
)
UsersProject
.
bulk_update
(
self
,
users_ids
,
access_role
)
end
# Delete multiple users from project by user ids
def
delete_users_ids_from_team
(
users_ids
)
UsersProject
.
bulk_delete
(
self
,
users_ids
)
end
# Remove all users from project team
def
truncate_team
UsersProject
.
truncate_team
(
self
)
end
end
app/roles
/git_host.rb
→
lib
/git_host.rb
View file @
cac77234
File moved
app/roles
/issue_commonality.rb
→
lib
/issue_commonality.rb
View file @
cac77234
...
...
@@ -68,5 +68,4 @@ module IssueCommonality
def
is_being_reopened?
closed_changed?
&&
!
closed
end
end
app/roles
/static_model.rb
→
lib
/static_model.rb
View file @
cac77234
File moved
app/roles
/votes.rb
→
lib
/votes.rb
View file @
cac77234
File moved
spec/
roles
/issue_commonality_spec.rb
→
spec/
lib
/issue_commonality_spec.rb
View file @
cac77234
File moved
spec/
roles
/votes_spec.rb
→
spec/
lib
/votes_spec.rb
View file @
cac77234
File moved
spec/
roles/
repository_spec.rb
→
spec/
models/project_
repository_spec.rb
View file @
cac77234
File moved
spec/models/user_spec.rb
View file @
cac77234
...
...
@@ -185,4 +185,14 @@ describe User do
it
{
User
.
not_in_project
(
@project
).
should
==
[
@user
,
@project
.
owner
]
}
end
describe
'normal user'
do
let
(
:user
)
{
create
(
:user
,
name:
'John Smith'
)
}
it
{
user
.
is_admin?
.
should
be_false
}
it
{
user
.
require_ssh_key?
.
should
be_true
}
it
{
user
.
can_create_group?
.
should
be_false
}
it
{
user
.
can_create_project?
.
should
be_true
}
it
{
user
.
first_name
.
should
==
'John'
}
end
end
spec/roles/account_role_spec.rb
deleted
100644 → 0
View file @
1b25a8f4
require
'spec_helper'
describe
User
,
"Account"
do
describe
'normal user'
do
let
(
:user
)
{
create
(
:user
,
name:
'John Smith'
)
}
it
{
user
.
is_admin?
.
should
be_false
}
it
{
user
.
require_ssh_key?
.
should
be_true
}
it
{
user
.
can_create_group?
.
should
be_false
}
it
{
user
.
can_create_project?
.
should
be_true
}
it
{
user
.
first_name
.
should
==
'John'
}
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment