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
iv
gitlab-ce
Commits
cd44d16a
Commit
cd44d16a
authored
Nov 20, 2015
by
Yorick Peterse
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'merge-1790-to-8-2-stable' into '8-2-stable'
See merge request !1851
parents
5ac2c3f0
1cdee35f
Changes
31
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
700 additions
and
215 deletions
+700
-215
CHANGELOG
CHANGELOG
+2
-0
app/controllers/users_controller.rb
app/controllers/users_controller.rb
+11
-18
app/finders/contributed_projects_finder.rb
app/finders/contributed_projects_finder.rb
+37
-0
app/finders/groups_finder.rb
app/finders/groups_finder.rb
+37
-32
app/finders/joined_groups_finder.rb
app/finders/joined_groups_finder.rb
+49
-0
app/finders/personal_projects_finder.rb
app/finders/personal_projects_finder.rb
+41
-0
app/finders/projects_finder.rb
app/finders/projects_finder.rb
+54
-67
app/models/concerns/sortable.rb
app/models/concerns/sortable.rb
+2
-1
app/models/event.rb
app/models/event.rb
+10
-0
app/models/group.rb
app/models/group.rb
+8
-0
app/models/project.rb
app/models/project.rb
+4
-0
app/models/user.rb
app/models/user.rb
+46
-33
app/views/dashboard/projects/index.atom.builder
app/views/dashboard/projects/index.atom.builder
+1
-1
app/views/groups/show.atom.builder
app/views/groups/show.atom.builder
+1
-1
app/views/projects/show.atom.builder
app/views/projects/show.atom.builder
+1
-1
app/views/users/show.atom.builder
app/views/users/show.atom.builder
+1
-1
db/migrate/20151118162244_add_projects_public_index.rb
db/migrate/20151118162244_add_projects_public_index.rb
+5
-0
db/schema.rb
db/schema.rb
+2
-1
lib/gitlab/sql/union.rb
lib/gitlab/sql/union.rb
+34
-0
spec/controllers/users_controller_spec.rb
spec/controllers/users_controller_spec.rb
+18
-5
spec/finders/contributed_projects_finder_spec.rb
spec/finders/contributed_projects_finder_spec.rb
+35
-0
spec/finders/group_finder_spec.rb
spec/finders/group_finder_spec.rb
+0
-15
spec/finders/groups_finder_spec.rb
spec/finders/groups_finder_spec.rb
+48
-0
spec/finders/joined_groups_finder_spec.rb
spec/finders/joined_groups_finder_spec.rb
+49
-0
spec/finders/personal_projects_finder_spec.rb
spec/finders/personal_projects_finder_spec.rb
+34
-0
spec/finders/projects_finder_spec.rb
spec/finders/projects_finder_spec.rb
+40
-35
spec/lib/gitlab/sql/union_spec.rb
spec/lib/gitlab/sql/union_spec.rb
+16
-0
spec/models/event_spec.rb
spec/models/event_spec.rb
+38
-0
spec/models/group_spec.rb
spec/models/group_spec.rb
+27
-0
spec/models/project_spec.rb
spec/models/project_spec.rb
+19
-0
spec/models/user_spec.rb
spec/models/user_spec.rb
+30
-4
No files found.
CHANGELOG
View file @
cd44d16a
...
...
@@ -3,6 +3,8 @@ Please view this file on the master branch, on stable branches it's out of date.
v 8.3.0 (unreleased)
v 8.2.0
- Improved performance of finding projects and groups in various places
- Improved performance of rendering user profile pages and Atom feeds
- Fix grouping of contributors by email in graph.
- Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu)
- Fix Drone CI service template not saving properly (Stan Hu)
...
...
app/controllers/users_controller.rb
View file @
cd44d16a
...
...
@@ -3,14 +3,11 @@ class UsersController < ApplicationController
before_action
:set_user
def
show
@contributed_projects
=
contributed_projects
.
joined
(
@user
).
reject
(
&
:forked?
)
@contributed_projects
=
contributed_projects
.
joined
(
@user
).
reject
(
&
:forked?
)
@projects
=
@user
.
personal_projects
.
where
(
id:
authorized_projects_ids
).
includes
(
:namespace
)
@projects
=
PersonalProjectsFinder
.
new
(
@user
).
execute
(
current_user
)
# Collect only groups common for both users
@groups
=
@user
.
groups
&
GroupsFinder
.
new
.
execute
(
current_user
)
@groups
=
JoinedGroupsFinder
.
new
(
@user
).
execute
(
current_user
)
respond_to
do
|
format
|
format
.
html
...
...
@@ -53,16 +50,8 @@ class UsersController < ApplicationController
@user
=
User
.
find_by_username!
(
params
[
:username
])
end
def
authorized_projects_ids
# Projects user can view
@authorized_projects_ids
||=
ProjectsFinder
.
new
.
execute
(
current_user
).
pluck
(
:id
)
end
def
contributed_projects
@contributed_projects
=
Project
.
where
(
id:
authorized_projects_ids
&
@user
.
contributed_projects_ids
).
includes
(
:namespace
)
ContributedProjectsFinder
.
new
(
@user
).
execute
(
current_user
)
end
def
contributions_calendar
...
...
@@ -73,9 +62,13 @@ class UsersController < ApplicationController
def
load_events
# Get user activity feed for projects common for both users
@events
=
@user
.
recent_events
.
where
(
project_id:
authorized_projects_ids
).
with_associations
merge
(
projects_for_current_user
).
references
(
:project
).
with_associations
.
limit_recent
(
20
,
params
[
:offset
])
end
@events
=
@events
.
limit
(
20
).
offset
(
params
[
:offset
]
||
0
)
def
projects_for_current_user
ProjectsFinder
.
new
.
execute
(
current_user
)
end
end
app/finders/contributed_projects_finder.rb
0 → 100644
View file @
cd44d16a
class
ContributedProjectsFinder
def
initialize
(
user
)
@user
=
user
end
# Finds the projects "@user" contributed to, limited to either public projects
# or projects visible to the given user.
#
# current_user - When given the list of the projects is limited to those only
# visible by this user.
#
# Returns an ActiveRecord::Relation.
def
execute
(
current_user
=
nil
)
if
current_user
relation
=
projects_visible_to_user
(
current_user
)
else
relation
=
public_projects
end
relation
.
includes
(
:namespace
).
order_id_desc
end
private
def
projects_visible_to_user
(
current_user
)
authorized
=
@user
.
contributed_projects
.
visible_to_user
(
current_user
)
union
=
Gitlab
::
SQL
::
Union
.
new
([
authorized
.
select
(
:id
),
public_projects
.
select
(
:id
)])
Project
.
where
(
"projects.id IN (
#{
union
.
to_sql
}
)"
)
end
def
public_projects
@user
.
contributed_projects
.
public_only
end
end
app/finders/groups_finder.rb
View file @
cd44d16a
class
GroupsFinder
def
execute
(
current_user
,
options
=
{})
all_groups
(
current_user
)
# Finds the groups available to the given user.
#
# current_user - The user to find the groups for.
#
# Returns an ActiveRecord::Relation.
def
execute
(
current_user
=
nil
)
if
current_user
relation
=
groups_visible_to_user
(
current_user
)
else
relation
=
public_groups
end
relation
.
order_id_desc
end
private
def
all_groups
(
current_user
)
group_ids
=
if
current_user
if
current_user
.
authorized_groups
.
any?
# User has access to groups
#
# Return only:
# groups with public projects
# groups with internal projects
# groups with joined projects
#
Project
.
public_and_internal_only
.
pluck
(
:namespace_id
)
+
current_user
.
authorized_groups
.
pluck
(
:id
)
else
# User has no group membership
#
# Return only:
# groups with public projects
# groups with internal projects
#
Project
.
public_and_internal_only
.
pluck
(
:namespace_id
)
end
else
# Not authenticated
#
# Return only:
# groups with public projects
Project
.
public_only
.
pluck
(
:namespace_id
)
end
Group
.
where
(
"public IS TRUE OR id IN(?)"
,
group_ids
)
# This method returns the groups "current_user" can see.
def
groups_visible_to_user
(
current_user
)
base
=
groups_for_projects
(
public_and_internal_projects
)
union
=
Gitlab
::
SQL
::
Union
.
new
([
base
.
select
(
:id
),
current_user
.
authorized_groups
.
select
(
:id
)])
Group
.
where
(
"namespaces.id IN (
#{
union
.
to_sql
}
)"
)
end
def
public_groups
groups_for_projects
(
public_projects
)
end
def
groups_for_projects
(
projects
)
Group
.
public_and_given_groups
(
projects
.
select
(
:namespace_id
))
end
def
public_projects
Project
.
unscoped
.
public_only
end
def
public_and_internal_projects
Project
.
unscoped
.
public_and_internal_only
end
end
app/finders/joined_groups_finder.rb
0 → 100644
View file @
cd44d16a
# Class for finding the groups a user is a member of.
class
JoinedGroupsFinder
def
initialize
(
user
=
nil
)
@user
=
user
end
# Finds the groups of the source user, optionally limited to those visible to
# the current user.
#
# current_user - If given the groups of "@user" will only include the groups
# "current_user" can also see.
#
# Returns an ActiveRecord::Relation.
def
execute
(
current_user
=
nil
)
if
current_user
relation
=
groups_visible_to_user
(
current_user
)
else
relation
=
public_groups
end
relation
.
order_id_desc
end
private
# Returns the groups the user in "current_user" can see.
#
# This list includes all public/internal projects as well as the projects of
# "@user" that "current_user" also has access to.
def
groups_visible_to_user
(
current_user
)
base
=
@user
.
authorized_groups
.
visible_to_user
(
current_user
)
extra
=
public_and_internal_groups
union
=
Gitlab
::
SQL
::
Union
.
new
([
base
.
select
(
:id
),
extra
.
select
(
:id
)])
Group
.
where
(
"namespaces.id IN (
#{
union
.
to_sql
}
)"
)
end
def
public_groups
groups_for_projects
(
@user
.
authorized_projects
.
public_only
)
end
def
public_and_internal_groups
groups_for_projects
(
@user
.
authorized_projects
.
public_and_internal_only
)
end
def
groups_for_projects
(
projects
)
@user
.
groups
.
public_and_given_groups
(
projects
.
select
(
:namespace_id
))
end
end
app/finders/personal_projects_finder.rb
0 → 100644
View file @
cd44d16a
class
PersonalProjectsFinder
def
initialize
(
user
)
@user
=
user
end
# Finds the projects belonging to the user in "@user", limited to either
# public projects or projects visible to the given user.
#
# current_user - When given the list of projects is limited to those only
# visible by this user.
#
# Returns an ActiveRecord::Relation.
def
execute
(
current_user
=
nil
)
if
current_user
relation
=
projects_visible_to_user
(
current_user
)
else
relation
=
public_projects
end
relation
.
includes
(
:namespace
).
order_id_desc
end
private
def
projects_visible_to_user
(
current_user
)
authorized
=
@user
.
personal_projects
.
visible_to_user
(
current_user
)
union
=
Gitlab
::
SQL
::
Union
.
new
([
authorized
.
select
(
:id
),
public_and_internal_projects
.
select
(
:id
)])
Project
.
where
(
"projects.id IN (
#{
union
.
to_sql
}
)"
)
end
def
public_projects
@user
.
personal_projects
.
public_only
end
def
public_and_internal_projects
@user
.
personal_projects
.
public_and_internal_only
end
end
app/finders/projects_finder.rb
View file @
cd44d16a
class
ProjectsFinder
def
execute
(
current_user
,
options
=
{})
# Returns all projects, optionally including group projects a user has access
# to.
#
# ## Examples
#
# Retrieving all public projects:
#
# ProjectsFinder.new.execute
#
# Retrieving all public/internal projects and those the given user has access
# to:
#
# ProjectsFinder.new.execute(some_user)
#
# Retrieving all public/internal projects as well as the group's projects the
# user has access to:
#
# ProjectsFinder.new.execute(some_user, group: some_group)
#
# Returns an ActiveRecord::Relation.
def
execute
(
current_user
=
nil
,
options
=
{})
group
=
options
[
:group
]
if
group
group_projects
(
current_user
,
group
)
base
,
extra
=
group_projects
(
current_user
,
group
)
else
all_projects
(
current_user
)
base
,
extra
=
all_projects
(
current_user
)
end
if
base
and
extra
union
=
Gitlab
::
SQL
::
Union
.
new
([
base
.
select
(
:id
),
extra
.
select
(
:id
)])
Project
.
where
(
"projects.id IN (
#{
union
.
to_sql
}
)"
)
else
base
end
end
...
...
@@ -13,77 +41,36 @@ class ProjectsFinder
def
group_projects
(
current_user
,
group
)
if
current_user
if
group
.
users
.
include?
(
current_user
)
# User is group member
#
# Return ALL group projects
group
.
projects
else
projects_members
=
ProjectMember
.
in_projects
(
group
.
projects
).
with_user
(
current_user
)
if
projects_members
.
any?
# User is a project member
#
# Return only:
# public projects
# internal projects
# joined projects
#
group
.
projects
.
where
(
"projects.id IN (?) OR projects.visibility_level IN (?)"
,
projects_members
.
pluck
(
:source_id
),
Project
.
public_and_internal_levels
)
else
# User has no access to group or group projects
#
# Return only:
# public projects
# internal projects
#
group
.
projects
.
public_and_internal_only
end
end
[
group_projects_for_user
(
current_user
,
group
),
group
.
projects
.
public_and_internal_only
]
else
# Not authenticated
#
# Return only:
# public projects
group
.
projects
.
public_only
[
group
.
projects
.
public_only
]
end
end
def
all_projects
(
current_user
)
if
current_user
if
current_user
.
authorized_projects
.
any?
# User has access to private projects
#
# Return only:
# public projects
# internal projects
# joined projects
#
Project
.
where
(
"projects.id IN (?) OR projects.visibility_level IN (?)"
,
current_user
.
authorized_projects
.
pluck
(
:id
),
Project
.
public_and_internal_levels
)
else
# User has no access to private projects
#
# Return only:
# public projects
# internal projects
#
Project
.
public_and_internal_only
end
[
current_user
.
authorized_projects
,
public_and_internal_projects
]
else
# Not authenticated
#
# Return only:
# public projects
Project
.
public_only
[
Project
.
public_only
]
end
end
def
group_projects_for_user
(
current_user
,
group
)
if
group
.
users
.
include?
(
current_user
)
group
.
projects
else
group
.
projects
.
visible_to_user
(
current_user
)
end
end
def
public_projects
Project
.
unscoped
.
public_only
end
def
public_and_internal_projects
Project
.
unscoped
.
public_and_internal_only
end
end
app/models/concerns/sortable.rb
View file @
cd44d16a
...
...
@@ -8,8 +8,9 @@ module Sortable
included
do
# By default all models should be ordered
# by created_at field starting from newest
default_scope
{
order
(
id: :desc
)
}
default_scope
{
order
_id_desc
}
scope
:order_id_desc
,
->
{
reorder
(
id: :desc
)
}
scope
:order_created_desc
,
->
{
reorder
(
created_at: :desc
)
}
scope
:order_created_asc
,
->
{
reorder
(
created_at: :asc
)
}
scope
:order_updated_desc
,
->
{
reorder
(
updated_at: :desc
)
}
...
...
app/models/event.rb
View file @
cd44d16a
...
...
@@ -63,6 +63,16 @@ class Event < ActiveRecord::Base
Event
::
PUSHED
,
[
"MergeRequest"
,
"Issue"
],
[
Event
::
CREATED
,
Event
::
CLOSED
,
Event
::
MERGED
])
end
def
latest_update_time
row
=
select
(
:updated_at
,
:project_id
).
reorder
(
id: :desc
).
take
row
?
row
.
updated_at
:
nil
end
def
limit_recent
(
limit
=
20
,
offset
=
nil
)
recent
.
limit
(
limit
).
offset
(
offset
)
end
end
def
proper?
...
...
app/models/group.rb
View file @
cd44d16a
...
...
@@ -49,6 +49,14 @@ class Group < Namespace
def
reference_pattern
User
.
reference_pattern
end
def
public_and_given_groups
(
ids
)
where
(
'public IS TRUE OR namespaces.id IN (?)'
,
ids
)
end
def
visible_to_user
(
user
)
where
(
id:
user
.
authorized_groups
.
select
(
:id
).
reorder
(
nil
))
end
end
def
to_reference
(
_from_project
=
nil
)
...
...
app/models/project.rb
View file @
cd44d16a
...
...
@@ -286,6 +286,10 @@ class Project < ActiveRecord::Base
joins
(
join_body
).
reorder
(
'join_note_counts.amount DESC'
)
end
def
visible_to_user
(
user
)
where
(
id:
user
.
authorized_projects
.
select
(
:id
).
reorder
(
nil
))
end
end
def
team
...
...
app/models/user.rb
View file @
cd44d16a
...
...
@@ -389,42 +389,23 @@ class User < ActiveRecord::Base
end
end
#
Groups
user has access to
#
Returns the groups a
user has access to
def
authorized_groups
@authorized_groups
||=
begin
group_ids
=
(
groups
.
pluck
(
:id
)
+
authorized_projects
.
pluck
(
:namespace_id
))
Group
.
where
(
id:
group_ids
)
end
end
union
=
Gitlab
::
SQL
::
Union
.
new
([
groups
.
select
(
:id
),
authorized_projects
.
select
(
:namespace_id
)])
def
authorized_projects_id
@authorized_projects_id
||=
begin
project_ids
=
personal_projects
.
pluck
(
:id
)
project_ids
.
push
(
*
groups_projects
.
pluck
(
:id
))
project_ids
.
push
(
*
projects
.
pluck
(
:id
).
uniq
)
end
end
def
master_or_owner_projects_id
@master_or_owner_projects_id
||=
begin
scope
=
{
access_level:
[
Gitlab
::
Access
::
MASTER
,
Gitlab
::
Access
::
OWNER
]
}
project_ids
=
personal_projects
.
pluck
(
:id
)
project_ids
.
push
(
*
groups_projects
.
where
(
members:
scope
).
pluck
(
:id
))
project_ids
.
push
(
*
projects
.
where
(
members:
scope
).
pluck
(
:id
).
uniq
)
end
Group
.
where
(
"namespaces.id IN (
#{
union
.
to_sql
}
)"
)
end
#
Projects user has access to
#
Returns the groups a user is authorized to access.
def
authorized_projects
@authorized_projects
||=
Project
.
where
(
id:
authorized_projects_id
)
Project
.
where
(
"projects.id IN (
#{
projects_union
.
to_sql
}
)"
)
end
def
owned_projects
@owned_projects
||=
begin
namespace_ids
=
owned_groups
.
pluck
(
:id
).
push
(
namespace
.
id
)
Project
.
in_namespace
(
namespace_ids
).
joins
(
:namespace
)
end
Project
.
where
(
'namespace_id IN (?) OR namespace_id = ?'
,
owned_groups
.
select
(
:id
),
namespace
.
id
).
joins
(
:namespace
)
end
# Team membership in authorized projects
...
...
@@ -739,12 +720,25 @@ class User < ActiveRecord::Base
Doorkeeper
::
AccessToken
.
where
(
resource_owner_id:
self
.
id
,
revoked_at:
nil
)
end
def
contributed_projects_ids
Event
.
contributions
.
where
(
author_id:
self
).
# Returns the projects a user contributed to in the last year.
#
# This method relies on a subquery as this performs significantly better
# compared to a JOIN when coupled with, for example,
# `Project.visible_to_user`. That is, consider the following code:
#
# some_user.contributed_projects.visible_to_user(other_user)
#
# If this method were to use a JOIN the resulting query would take roughly 200
# ms on a database with a similar size to GitLab.com's database. On the other
# hand, using a subquery means we can get the exact same data in about 40 ms.
def
contributed_projects
events
=
Event
.
select
(
:project_id
).
contributions
.
where
(
author_id:
self
).
where
(
"created_at > ?"
,
Time
.
now
-
1
.
year
).
reorder
(
project_id: :desc
).
select
(
:project_id
).
uniq
.
map
(
&
:project_id
)
uniq
.
reorder
(
nil
)
Project
.
where
(
id:
events
)
end
def
restricted_signup_domains
...
...
@@ -777,8 +771,27 @@ class User < ActiveRecord::Base
def
ci_authorized_runners
@ci_authorized_runners
||=
begin
runner_ids
=
Ci
::
RunnerProject
.
joins
(
:project
).
where
(
ci_projects:
{
gitlab_id:
master_or_owner_projects_id
}).
select
(
:runner_id
)
where
(
"ci_projects.gitlab_id IN (
#{
ci_projects_union
.
to_sql
}
)"
).
select
(
:runner_id
)
Ci
::
Runner
.
specific
.
where
(
id:
runner_ids
)
end
end
private
def
projects_union
Gitlab
::
SQL
::
Union
.
new
([
personal_projects
.
select
(
:id
),
groups_projects
.
select
(
:id
),
projects
.
select
(
:id
)])
end
def
ci_projects_union
scope
=
{
access_level:
[
Gitlab
::
Access
::
MASTER
,
Gitlab
::
Access
::
OWNER
]
}
groups
=
groups_projects
.
where
(
members:
scope
)
other
=
projects
.
where
(
members:
scope
)
Gitlab
::
SQL
::
Union
.
new
([
personal_projects
.
select
(
:id
),
groups
.
select
(
:id
),
other
.
select
(
:id
)])
end
end
app/views/dashboard/projects/index.atom.builder
View file @
cd44d16a
...
...
@@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.link href: dashboard_projects_url(format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml"
xml.link href: dashboard_projects_url, rel: "alternate", type: "text/html"
xml.id dashboard_projects_url
xml.updated @events.
maximum(:updated_at)
.strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
xml.updated @events.
latest_update_time
.strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
@events.each do |event|
event_to_atom(xml, event)
...
...
app/views/groups/show.atom.builder
View file @
cd44d16a
...
...
@@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.link href: group_url(@group, format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml"
xml.link href: group_url(@group), rel: "alternate", type: "text/html"
xml.id group_url(@group)
xml.updated @events.
maximum(:updated_at)
.strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
xml.updated @events.
latest_update_time
.strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
@events.each do |event|
event_to_atom(xml, event)
...
...
app/views/projects/show.atom.builder
View file @
cd44d16a
...
...
@@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.link href: namespace_project_url(@project.namespace, @project, format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml"
xml.link href: namespace_project_url(@project.namespace, @project), rel: "alternate", type: "text/html"
xml.id namespace_project_url(@project.namespace, @project)
xml.updated @events.
maximum(:updated_at)
.strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
xml.updated @events.
latest_update_time
.strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
@events.each do |event|
event_to_atom(xml, event)
...
...
app/views/users/show.atom.builder
View file @
cd44d16a
...
...
@@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.link href: user_url(@user, :atom), rel: "self", type: "application/atom+xml"
xml.link href: user_url(@user), rel: "alternate", type: "text/html"
xml.id user_url(@user)
xml.updated @events.
maximum(:updated_at)
.strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
xml.updated @events.
latest_update_time
.strftime("%Y-%m-%dT%H:%M:%SZ") if @events.any?
@events.each do |event|
event_to_atom(xml, event)
...
...
db/migrate/20151118162244_add_projects_public_index.rb
0 → 100644
View file @
cd44d16a
class
AddProjectsPublicIndex
<
ActiveRecord
::
Migration
def
change
add_index
:namespaces
,
:public
end
end
db/schema.rb
View file @
cd44d16a
...
...
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
version:
2015111
6144118
)
do
ActiveRecord
::
Schema
.
define
(
version:
2015111
8162244
)
do
# These are extensions that must be enabled in order to support this database
enable_extension
"plpgsql"
...
...
@@ -538,6 +538,7 @@ ActiveRecord::Schema.define(version: 20151116144118) do
add_index
"namespaces"
,
[
"name"
],
name:
"index_namespaces_on_name"
,
unique:
true
,
using: :btree
add_index
"namespaces"
,
[
"owner_id"
],
name:
"index_namespaces_on_owner_id"
,
using: :btree
add_index
"namespaces"
,
[
"path"
],
name:
"index_namespaces_on_path"
,
unique:
true
,
using: :btree
add_index
"namespaces"
,
[
"public"
],
name:
"index_namespaces_on_public"
,
using: :btree
add_index
"namespaces"
,
[
"type"
],
name:
"index_namespaces_on_type"
,
using: :btree
create_table
"notes"
,
force:
true
do
|
t
|
...
...
lib/gitlab/sql/union.rb
0 → 100644
View file @
cd44d16a
module
Gitlab
module
SQL
# Class for building SQL UNION statements.
#
# ORDER BYs are dropped from the relations as the final sort order is not
# guaranteed any way.
#
# Example usage:
#
# union = Gitlab::SQL::Union.new(user.personal_projects, user.projects)
# sql = union.to_sql
#
# Project.where("id IN (#{sql})")
class
Union
def
initialize
(
relations
)
@relations
=
relations
end
def
to_sql
# Some relations may include placeholders for prepared statements, these
# aren't incremented properly when joining relations together this way.
# By using "unprepared_statements" we remove the usage of placeholders
# (thus fixing this problem), at a slight performance cost.
fragments
=
ActiveRecord
::
Base
.
connection
.
unprepared_statement
do
@relations
.
map
do
|
rel
|
rel
.
reorder
(
nil
).
to_sql
end
end
fragments
.
join
(
"
\n
UNION
\n
"
)
end
end
end
end
spec/controllers/users_controller_spec.rb
View file @
cd44d16a
...
...
@@ -16,13 +16,26 @@ describe UsersController do
context
'with rendered views'
do
render_views
it
'renders the show template'
do
sign_in
(
user
)
describe
'when logged in'
do
before
do
sign_in
(
user
)
end
get
:show
,
username:
user
.
username
it
'renders the show template'
do
get
:show
,
username:
user
.
username
expect
(
response
).
to
be_success
expect
(
response
).
to
render_template
(
'show'
)
expect
(
response
).
to
be_success
expect
(
response
).
to
render_template
(
'show'
)
end
end
describe
'when logged out'
do
it
'renders the show template'
do
get
:show
,
username:
user
.
username
expect
(
response
).
to
be_success
expect
(
response
).
to
render_template
(
'show'
)
end
end
end
end
...
...
spec/finders/contributed_projects_finder_spec.rb
0 → 100644
View file @
cd44d16a
require
'spec_helper'
describe
ContributedProjectsFinder
do
let
(
:source_user
)
{
create
(
:user
)
}
let
(
:current_user
)
{
create
(
:user
)
}
let
(
:finder
)
{
described_class
.
new
(
source_user
)
}
let!
(
:public_project
)
{
create
(
:project
,
:public
)
}
let!
(
:private_project
)
{
create
(
:project
,
:private
)
}
before
do
private_project
.
team
<<
[
source_user
,
Gitlab
::
Access
::
MASTER
]
private_project
.
team
<<
[
current_user
,
Gitlab
::
Access
::
DEVELOPER
]
public_project
.
team
<<
[
source_user
,
Gitlab
::
Access
::
MASTER
]
create
(
:event
,
action:
Event
::
PUSHED
,
project:
public_project
,
target:
public_project
,
author:
source_user
)
create
(
:event
,
action:
Event
::
PUSHED
,
project:
private_project
,
target:
private_project
,
author:
source_user
)
end
describe
'without a current user'
do
subject
{
finder
.
execute
}
it
{
is_expected
.
to
eq
([
public_project
])
}
end
describe
'with a current user'
do
subject
{
finder
.
execute
(
current_user
)
}
it
{
is_expected
.
to
eq
([
private_project
,
public_project
])
}
end
end
spec/finders/group_finder_spec.rb
deleted
100644 → 0
View file @
5ac2c3f0
require
'spec_helper'
describe
GroupsFinder
do
let
(
:user
)
{
create
:user
}
let!
(
:group
)
{
create
:group
}
let!
(
:public_group
)
{
create
:group
,
public:
true
}
describe
:execute
do
it
'finds public group'
do
groups
=
GroupsFinder
.
new
.
execute
(
user
)
expect
(
groups
.
size
).
to
eq
(
1
)
expect
(
groups
.
first
).
to
eq
(
public_group
)
end
end
end
spec/finders/groups_finder_spec.rb
0 → 100644
View file @
cd44d16a
require
'spec_helper'
describe
GroupsFinder
do
describe
'#execute'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:group1
)
{
create
(
:group
)
}
let
(
:group2
)
{
create
(
:group
)
}
let
(
:group3
)
{
create
(
:group
)
}
let
(
:group4
)
{
create
(
:group
,
public:
true
)
}
let!
(
:public_project
)
{
create
(
:project
,
:public
,
group:
group1
)
}
let!
(
:internal_project
)
{
create
(
:project
,
:internal
,
group:
group2
)
}
let!
(
:private_project
)
{
create
(
:project
,
:private
,
group:
group3
)
}
let
(
:finder
)
{
described_class
.
new
}
describe
'with a user'
do
subject
{
finder
.
execute
(
user
)
}
describe
'when the user is not a member of any groups'
do
it
{
is_expected
.
to
eq
([
group4
,
group2
,
group1
])
}
end
describe
'when the user is a member of a group'
do
before
do
group3
.
add_user
(
user
,
Gitlab
::
Access
::
DEVELOPER
)
end
it
{
is_expected
.
to
eq
([
group4
,
group3
,
group2
,
group1
])
}
end
describe
'when the user is a member of a private project'
do
before
do
private_project
.
team
.
add_user
(
user
,
Gitlab
::
Access
::
DEVELOPER
)
end
it
{
is_expected
.
to
eq
([
group4
,
group3
,
group2
,
group1
])
}
end
end
describe
'without a user'
do
subject
{
finder
.
execute
}
it
{
is_expected
.
to
eq
([
group4
,
group1
])
}
end
end
end
spec/finders/joined_groups_finder_spec.rb
0 → 100644
View file @
cd44d16a
require
'spec_helper'
describe
JoinedGroupsFinder
do
describe
'#execute'
do
let
(
:source_user
)
{
create
(
:user
)
}
let
(
:current_user
)
{
create
(
:user
)
}
let
(
:group1
)
{
create
(
:group
)
}
let
(
:group2
)
{
create
(
:group
)
}
let
(
:group3
)
{
create
(
:group
)
}
let
(
:group4
)
{
create
(
:group
,
public:
true
)
}
let!
(
:public_project
)
{
create
(
:project
,
:public
,
group:
group1
)
}
let!
(
:internal_project
)
{
create
(
:project
,
:internal
,
group:
group2
)
}
let!
(
:private_project
)
{
create
(
:project
,
:private
,
group:
group3
)
}
let
(
:finder
)
{
described_class
.
new
(
source_user
)
}
before
do
[
group1
,
group2
,
group3
,
group4
].
each
do
|
group
|
group
.
add_user
(
source_user
,
Gitlab
::
Access
::
MASTER
)
end
end
describe
'with a current user'
do
describe
'when the current user has access to the projects of the source user'
do
before
do
private_project
.
team
.
add_user
(
current_user
,
Gitlab
::
Access
::
DEVELOPER
)
end
subject
{
finder
.
execute
(
current_user
)
}
it
{
is_expected
.
to
eq
([
group4
,
group3
,
group2
,
group1
])
}
end
describe
'when the current user does not have access to the projects of the source user'
do
subject
{
finder
.
execute
(
current_user
)
}
it
{
is_expected
.
to
eq
([
group4
,
group2
,
group1
])
}
end
end
describe
'without a current user'
do
subject
{
finder
.
execute
}
it
{
is_expected
.
to
eq
([
group4
,
group1
])
}
end
end
end
spec/finders/personal_projects_finder_spec.rb
0 → 100644
View file @
cd44d16a
require
'spec_helper'
describe
PersonalProjectsFinder
do
let
(
:source_user
)
{
create
(
:user
)
}
let
(
:current_user
)
{
create
(
:user
)
}
let
(
:finder
)
{
described_class
.
new
(
source_user
)
}
let!
(
:public_project
)
do
create
(
:project
,
:public
,
namespace:
source_user
.
namespace
,
name:
'A'
,
path:
'A'
)
end
let!
(
:private_project
)
do
create
(
:project
,
:private
,
namespace:
source_user
.
namespace
,
name:
'B'
,
path:
'B'
)
end
before
do
private_project
.
team
<<
[
current_user
,
Gitlab
::
Access
::
DEVELOPER
]
end
describe
'without a current user'
do
subject
{
finder
.
execute
}
it
{
is_expected
.
to
eq
([
public_project
])
}
end
describe
'with a current user'
do
subject
{
finder
.
execute
(
current_user
)
}
it
{
is_expected
.
to
eq
([
private_project
,
public_project
])
}
end
end
spec/finders/projects_finder_spec.rb
View file @
cd44d16a
require
'spec_helper'
describe
ProjectsFinder
do
let
(
:user
)
{
create
:user
}
let
(
:group
)
{
create
:group
}
describe
'#execute'
do
let
(
:user
)
{
create
(
:user
)
}
let
(
:project1
)
{
create
(
:empty_project
,
:public
,
group:
group
)
}
let
(
:project2
)
{
create
(
:empty_project
,
:internal
,
group:
group
)
}
let
(
:project3
)
{
create
(
:empty_project
,
:private
,
group:
group
)
}
let
(
:project4
)
{
create
(
:empty_project
,
:private
,
group:
group
)
}
let!
(
:private_project
)
{
create
(
:project
,
:private
)
}
let!
(
:internal_project
)
{
create
(
:project
,
:internal
)
}
let!
(
:public_project
)
{
create
(
:project
,
:public
)
}
context
'non authenticated'
do
subject
{
ProjectsFinder
.
new
.
execute
(
nil
,
group:
group
)
}
let
(
:finder
)
{
described_class
.
new
}
it
{
is_expected
.
to
include
(
project1
)
}
it
{
is_expected
.
not_to
include
(
project2
)
}
it
{
is_expected
.
not_to
include
(
project3
)
}
it
{
is_expected
.
not_to
include
(
project4
)
}
end
describe
'without a group'
do
describe
'without a user'
do
subject
{
finder
.
execute
}
context
'authenticated'
do
subject
{
ProjectsFinder
.
new
.
execute
(
user
,
group:
group
)
}
it
{
is_expected
.
to
eq
([
public_project
])
}
end
it
{
is_expected
.
to
include
(
project1
)
}
it
{
is_expected
.
to
include
(
project2
)
}
it
{
is_expected
.
not_to
include
(
project3
)
}
it
{
is_expected
.
not_to
include
(
project4
)
}
end
describe
'with a user'
do
subject
{
finder
.
execute
(
user
)
}
context
'authenticated, project member'
do
before
{
project3
.
team
<<
[
user
,
:developer
]
}
describe
'without private projects'
do
it
{
is_expected
.
to
eq
([
public_project
,
internal_project
])
}
end
subject
{
ProjectsFinder
.
new
.
execute
(
user
,
group:
group
)
}
describe
'with private projects'
do
before
do
private_project
.
team
.
add_user
(
user
,
Gitlab
::
Access
::
MASTER
)
end
it
{
is_expected
.
to
include
(
project1
)
}
it
{
is_expected
.
to
include
(
project2
)
}
it
{
is_expected
.
to
include
(
project3
)
}
it
{
is_expected
.
not_to
include
(
project4
)
}
end
it
do
is_expected
.
to
eq
([
public_project
,
internal_project
,
private_project
])
end
end
end
end
describe
'with a group'
do
let
(
:group
)
{
public_project
.
group
}
describe
'without a user'
do
subject
{
finder
.
execute
(
nil
,
group:
group
)
}
context
'authenticated, group member'
do
before
{
group
.
add_developer
(
user
)
}
it
{
is_expected
.
to
eq
([
public_project
])
}
end
subject
{
ProjectsFinder
.
new
.
execute
(
user
,
group:
group
)
}
describe
'with a user'
do
subject
{
finder
.
execute
(
user
,
group:
group
)
}
it
{
is_expected
.
to
include
(
project1
)
}
it
{
is_expected
.
to
include
(
project2
)
}
it
{
is_expected
.
to
include
(
project3
)
}
it
{
is_expected
.
to
include
(
project4
)
}
it
{
is_expected
.
to
eq
([
public_project
,
internal_project
])
}
end
end
end
end
spec/lib/gitlab/sql/union_spec.rb
0 → 100644
View file @
cd44d16a
require
'spec_helper'
describe
Gitlab
::
SQL
::
Union
do
describe
'#to_sql'
do
it
'returns a String joining relations together using a UNION'
do
rel1
=
User
.
where
(
email:
'alice@example.com'
)
rel2
=
User
.
where
(
email:
'bob@example.com'
)
union
=
described_class
.
new
([
rel1
,
rel2
])
sql1
=
rel1
.
reorder
(
nil
).
to_sql
sql2
=
rel2
.
reorder
(
nil
).
to_sql
expect
(
union
.
to_sql
).
to
eq
(
"
#{
sql1
}
\n
UNION
\n
#{
sql2
}
"
)
end
end
end
spec/models/event_spec.rb
View file @
cd44d16a
...
...
@@ -64,4 +64,42 @@ describe Event do
it
{
expect
(
@event
.
branch_name
).
to
eq
(
"master"
)
}
it
{
expect
(
@event
.
author
).
to
eq
(
@user
)
}
end
describe
'.latest_update_time'
do
describe
'when events are present'
do
let
(
:time
)
{
Time
.
utc
(
2015
,
1
,
1
)
}
before
do
create
(
:closed_issue_event
,
updated_at:
time
)
create
(
:closed_issue_event
,
updated_at:
time
+
5
)
end
it
'returns the latest update time'
do
expect
(
Event
.
latest_update_time
).
to
eq
(
time
+
5
)
end
end
describe
'when no events exist'
do
it
'returns nil'
do
expect
(
Event
.
latest_update_time
).
to
be_nil
end
end
end
describe
'.limit_recent'
do
let!
(
:event1
)
{
create
(
:closed_issue_event
)
}
let!
(
:event2
)
{
create
(
:closed_issue_event
)
}
describe
'without an explicit limit'
do
subject
{
Event
.
limit_recent
}
it
{
is_expected
.
to
eq
([
event2
,
event1
])
}
end
describe
'with an explicit limit'
do
subject
{
Event
.
limit_recent
(
1
)
}
it
{
is_expected
.
to
eq
([
event2
])
}
end
end
end
spec/models/group_spec.rb
View file @
cd44d16a
...
...
@@ -38,6 +38,33 @@ describe Group do
it
{
is_expected
.
not_to
validate_presence_of
:owner
}
end
describe
'.public_and_given_groups'
do
let!
(
:public_group
)
{
create
(
:group
,
public:
true
)
}
subject
{
described_class
.
public_and_given_groups
([
group
.
id
])
}
it
{
is_expected
.
to
eq
([
public_group
,
group
])
}
end
describe
'.visible_to_user'
do
let!
(
:group
)
{
create
(
:group
)
}
let!
(
:user
)
{
create
(
:user
)
}
subject
{
described_class
.
visible_to_user
(
user
)
}
describe
'when the user has access to a group'
do
before
do
group
.
add_user
(
user
,
Gitlab
::
Access
::
MASTER
)
end
it
{
is_expected
.
to
eq
([
group
])
}
end
describe
'when the user does not have access to any groups'
do
it
{
is_expected
.
to
eq
([])
}
end
end
describe
'#to_reference'
do
it
'returns a String reference to the object'
do
expect
(
group
.
to_reference
).
to
eq
"@
#{
group
.
name
}
"
...
...
spec/models/project_spec.rb
View file @
cd44d16a
...
...
@@ -453,4 +453,23 @@ describe Project do
end
end
end
describe
'.visible_to_user'
do
let!
(
:project
)
{
create
(
:project
,
:private
)
}
let!
(
:user
)
{
create
(
:user
)
}
subject
{
described_class
.
visible_to_user
(
user
)
}
describe
'when a user has access to a project'
do
before
do
project
.
team
.
add_user
(
user
,
Gitlab
::
Access
::
MASTER
)
end
it
{
is_expected
.
to
eq
([
project
])
}
end
describe
'when a user does not have access to any projects'
do
it
{
is_expected
.
to
eq
([])
}
end
end
end
spec/models/user_spec.rb
View file @
cd44d16a
...
...
@@ -686,7 +686,7 @@ describe User do
end
end
describe
"#contributed_projects
_ids
"
do
describe
"#contributed_projects"
do
subject
{
create
(
:user
)
}
let!
(
:project1
)
{
create
(
:project
)
}
let!
(
:project2
)
{
create
(
:project
,
forked_from_project:
project3
)
}
...
...
@@ -701,15 +701,15 @@ describe User do
end
it
"includes IDs for projects the user has pushed to"
do
expect
(
subject
.
contributed_projects
_ids
).
to
include
(
project1
.
id
)
expect
(
subject
.
contributed_projects
).
to
include
(
project1
)
end
it
"includes IDs for projects the user has had merge requests merged into"
do
expect
(
subject
.
contributed_projects
_ids
).
to
include
(
project3
.
id
)
expect
(
subject
.
contributed_projects
).
to
include
(
project3
)
end
it
"doesn't include IDs for unrelated projects"
do
expect
(
subject
.
contributed_projects
_ids
).
not_to
include
(
project2
.
id
)
expect
(
subject
.
contributed_projects
).
not_to
include
(
project2
)
end
end
...
...
@@ -758,4 +758,30 @@ describe User do
expect
(
subject
.
recent_push
).
to
eq
(
nil
)
end
end
describe
'#authorized_groups'
do
let!
(
:user
)
{
create
(
:user
)
}
let!
(
:private_group
)
{
create
(
:group
)
}
before
do
private_group
.
add_user
(
user
,
Gitlab
::
Access
::
MASTER
)
end
subject
{
user
.
authorized_groups
}
it
{
is_expected
.
to
eq
([
private_group
])
}
end
describe
'#authorized_projects'
do
let!
(
:user
)
{
create
(
:user
)
}
let!
(
:private_project
)
{
create
(
:project
,
:private
)
}
before
do
private_project
.
team
<<
[
user
,
Gitlab
::
Access
::
MASTER
]
end
subject
{
user
.
authorized_projects
}
it
{
is_expected
.
to
eq
([
private_project
])
}
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