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
1
Merge Requests
1
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
nexedi
gitlab-ce
Commits
43c8788e
Commit
43c8788e
authored
Nov 30, 2016
by
Rémy Coutable
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'grapify-projects-api' into 'master'
Grapify the projects API Related to #22928 See merge request !7456
parents
2706550a
7c607a55
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
288 additions
and
358 deletions
+288
-358
doc/api/projects.md
doc/api/projects.md
+1
-0
lib/api/helpers.rb
lib/api/helpers.rb
+2
-24
lib/api/projects.rb
lib/api/projects.rb
+265
-313
spec/requests/api/projects_spec.rb
spec/requests/api/projects_spec.rb
+20
-21
No files found.
doc/api/projects.md
View file @
43c8788e
...
...
@@ -626,6 +626,7 @@ Parameters:
|
`path`
| string | no | Custom repository name for new project. By default generated based on name |
|
`default_branch`
| string | no |
`master`
by default |
|
`namespace_id`
| integer | no | Namespace for the new project (defaults to the current user's namespace) |
|
`default_branch`
| string | no |
`master`
by default |
|
`description`
| string | no | Short project description |
|
`issues_enabled`
| boolean | no | Enable issues for this project |
|
`merge_requests_enabled`
| boolean | no | Enable merge requests for this project |
...
...
lib/api/helpers.rb
View file @
43c8788e
...
...
@@ -308,11 +308,6 @@ module API
# Projects helpers
def
filter_projects
(
projects
)
# If the archived parameter is passed, limit results accordingly
if
params
[
:archived
].
present?
projects
=
projects
.
where
(
archived:
to_boolean
(
params
[
:archived
]))
end
if
params
[
:search
].
present?
projects
=
projects
.
search
(
params
[
:search
])
end
...
...
@@ -321,25 +316,8 @@ module API
projects
=
projects
.
search_by_visibility
(
params
[
:visibility
])
end
projects
.
reorder
(
project_order_by
=>
project_sort
)
end
def
project_order_by
order_fields
=
%w(id name path created_at updated_at last_activity_at)
if
order_fields
.
include?
(
params
[
'order_by'
])
params
[
'order_by'
]
else
'created_at'
end
end
def
project_sort
if
params
[
"sort"
]
==
'asc'
:asc
else
:desc
end
projects
=
projects
.
where
(
archived:
params
[
:archived
])
projects
.
reorder
(
params
[
:order_by
]
=>
params
[
:sort
])
end
# file helpers
...
...
lib/api/projects.rb
View file @
43c8788e
module
API
# Projects API
class
Projects
<
Grape
::
API
include
PaginationParams
before
{
authenticate!
}
resource
:projects
,
requirements:
{
id:
/[^\/]+/
}
do
helpers
do
params
:optional_params
do
optional
:description
,
type:
String
,
desc:
'The description of the project'
optional
:issues_enabled
,
type:
Boolean
,
desc:
'Flag indication if the issue tracker is enabled'
optional
:merge_requests_enabled
,
type:
Boolean
,
desc:
'Flag indication if merge requests are enabled'
optional
:wiki_enabled
,
type:
Boolean
,
desc:
'Flag indication if the wiki is enabled'
optional
:builds_enabled
,
type:
Boolean
,
desc:
'Flag indication if builds are enabled'
optional
:snippets_enabled
,
type:
Boolean
,
desc:
'Flag indication if snippets are enabled'
optional
:shared_runners_enabled
,
type:
Boolean
,
desc:
'Flag indication if shared runners are enabled for that project'
optional
:container_registry_enabled
,
type:
Boolean
,
desc:
'Flag indication if the container registry is enabled for that project'
optional
:lfs_enabled
,
type:
Boolean
,
desc:
'Flag indication if Git LFS is enabled for that project'
optional
:public
,
type:
Boolean
,
desc:
'Create a public project. The same as visibility_level = 20.'
optional
:visibility_level
,
type:
Integer
,
values:
[
Gitlab
::
VisibilityLevel
::
PRIVATE
,
Gitlab
::
VisibilityLevel
::
INTERNAL
,
Gitlab
::
VisibilityLevel
::
PUBLIC
],
desc:
'Create a public project. The same as visibility_level = 20.'
optional
:public_builds
,
type:
Boolean
,
desc:
'Perform public builds'
optional
:request_access_enabled
,
type:
Boolean
,
desc:
'Allow users to request member access'
optional
:only_allow_merge_if_build_succeeds
,
type:
Boolean
,
desc:
'Only allow to merge if builds succeed'
optional
:only_allow_merge_if_all_discussions_are_resolved
,
type:
Boolean
,
desc:
'Only allow to merge if all discussions are resolved'
end
def
map_public_to_visibility_level
(
attrs
)
publik
=
attrs
.
delete
(
:public
)
if
!
publik
.
nil?
&&
!
attrs
[
:visibility_level
].
present?
# Since setting the public attribute to private could mean either
# private or internal, use the more conservative option, private.
attrs
[
:visibility_level
]
=
(
publik
==
true
)
?
Gitlab
::
VisibilityLevel
::
PUBLIC
:
Gitlab
::
VisibilityLevel
::
PRIVATE
end
attrs
end
end
resource
:projects
do
helpers
do
def
map_public_to_visibility_level
(
attrs
)
publik
=
attrs
.
delete
(
:public
)
if
publik
.
present?
&&
!
attrs
[
:visibility_level
].
present?
publik
=
to_boolean
(
publik
)
# Since setting the public attribute to private could mean either
# private or internal, use the more conservative option, private.
attrs
[
:visibility_level
]
=
(
publik
==
true
)
?
Gitlab
::
VisibilityLevel
::
PUBLIC
:
Gitlab
::
VisibilityLevel
::
PRIVATE
end
attrs
params
:sort_params
do
optional
:order_by
,
type:
String
,
values:
%w[id name path created_at updated_at last_activity_at]
,
default:
'created_at'
,
desc:
'Return projects ordered by field'
optional
:sort
,
type:
String
,
values:
%w[asc desc]
,
default:
'desc'
,
desc:
'Return projects sorted in ascending and descending order'
end
params
:filter_params
do
optional
:archived
,
type:
Boolean
,
default:
false
,
desc:
'Limit by archived status'
optional
:visibility
,
type:
String
,
values:
%w[public internal private]
,
desc:
'Limit by visibility'
optional
:search
,
type:
String
,
desc:
'Return list of authorized projects matching the search criteria'
use
:sort_params
end
params
:create_params
do
optional
:namespace_id
,
type:
Integer
,
desc:
'Namespace ID for the new project. Default to the user namespace.'
optional
:import_url
,
type:
String
,
desc:
'URL from which the project is imported'
end
end
# Get a projects list for authenticated user
#
# Example Request:
# GET /projects
desc
'Get a projects list for authenticated user'
do
success
Entities
::
BasicProjectDetails
end
params
do
optional
:simple
,
type:
Boolean
,
default:
false
,
desc:
'Return only the ID, URL, name, and path of each project'
use
:filter_params
use
:pagination
end
get
do
projects
=
current_user
.
authorized_projects
projects
=
filter_projects
(
projects
)
projects
=
paginate
projects
entity
=
params
[
:simple
]
?
Entities
::
BasicProjectDetails
:
Entities
::
ProjectWithAccess
present
p
rojects
,
with:
entity
,
user:
current_user
present
p
aginate
(
projects
)
,
with:
entity
,
user:
current_user
end
# Get a list of visible projects for authenticated user
#
# Example Request:
# GET /projects/visible
desc
'Get a list of visible projects for authenticated user'
do
success
Entities
::
BasicProjectDetails
end
params
do
optional
:simple
,
type:
Boolean
,
default:
false
,
desc:
'Return only the ID, URL, name, and path of each project'
use
:filter_params
use
:pagination
end
get
'/visible'
do
projects
=
ProjectsFinder
.
new
.
execute
(
current_user
)
projects
=
filter_projects
(
projects
)
projects
=
paginate
projects
entity
=
params
[
:simple
]
?
Entities
::
BasicProjectDetails
:
Entities
::
ProjectWithAccess
present
p
rojects
,
with:
entity
,
user:
current_user
present
p
aginate
(
projects
)
,
with:
entity
,
user:
current_user
end
# Get an owned projects list for authenticated user
#
# Example Request:
# GET /projects/owned
desc
'Get an owned projects list for authenticated user'
do
success
Entities
::
BasicProjectDetails
end
params
do
use
:filter_params
use
:pagination
end
get
'/owned'
do
projects
=
current_user
.
owned_projects
projects
=
filter_projects
(
projects
)
projects
=
paginate
projects
present
p
rojects
,
with:
Entities
::
ProjectWithAccess
,
user:
current_user
present
p
aginate
(
projects
)
,
with:
Entities
::
ProjectWithAccess
,
user:
current_user
end
# Gets starred project for the authenticated user
#
# Example Request:
# GET /projects/starred
desc
'Gets starred project for the authenticated user'
do
success
Entities
::
BasicProjectDetails
end
params
do
use
:filter_params
use
:pagination
end
get
'/starred'
do
projects
=
current_user
.
viewable_starred_projects
projects
=
filter_projects
(
projects
)
projects
=
paginate
projects
present
p
rojects
,
with:
Entities
::
Project
,
user:
current_user
present
p
aginate
(
projects
)
,
with:
Entities
::
Project
,
user:
current_user
end
# Get all projects for admin user
#
# Example Request:
# GET /projects/all
desc
'Get all projects for admin user'
do
success
Entities
::
BasicProjectDetails
end
params
do
use
:filter_params
use
:pagination
end
get
'/all'
do
authenticated_as_admin!
projects
=
Project
.
all
projects
=
filter_projects
(
projects
)
projects
=
paginate
projects
present
p
rojects
,
with:
Entities
::
ProjectWithAccess
,
user:
current_user
present
p
aginate
(
projects
)
,
with:
Entities
::
ProjectWithAccess
,
user:
current_user
end
# Get a single project
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# GET /projects/:id
get
":id"
do
present
user_project
,
with:
Entities
::
ProjectWithAccess
,
user:
current_user
,
user_can_admin_project:
can?
(
current_user
,
:admin_project
,
user_project
)
desc
'Search for projects the current user has access to'
do
success
Entities
::
Project
end
params
do
requires
:query
,
type:
String
,
desc:
'The project name to be searched'
use
:sort_params
use
:pagination
end
get
"/search/:query"
do
search_service
=
Search
::
GlobalService
.
new
(
current_user
,
search:
params
[
:query
]).
execute
projects
=
search_service
.
objects
(
'projects'
,
params
[
:page
])
projects
=
projects
.
reorder
(
params
[
:order_by
]
=>
params
[
:sort
])
# Get events for a single project
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# GET /projects/:id/events
get
":id/events"
do
events
=
paginate
user_project
.
events
.
recent
present
events
,
with:
Entities
::
Event
end
# Create new project
#
# Parameters:
# name (required) - name for new project
# description (optional) - short project description
# issues_enabled (optional)
# merge_requests_enabled (optional)
# builds_enabled (optional)
# wiki_enabled (optional)
# snippets_enabled (optional)
# container_registry_enabled (optional)
# shared_runners_enabled (optional)
# namespace_id (optional) - defaults to user namespace
# public (optional) - if true same as setting visibility_level = 20
# visibility_level (optional) - 0 by default
# import_url (optional)
# public_builds (optional)
# lfs_enabled (optional)
# request_access_enabled (optional) - Allow users to request member access
# Example Request
# POST /projects
present
paginate
(
projects
),
with:
Entities
::
Project
end
desc
'Create new project'
do
success
Entities
::
Project
end
params
do
requires
:name
,
type:
String
,
desc:
'The name of the project'
optional
:path
,
type:
String
,
desc:
'The path of the repository'
use
:optional_params
use
:create_params
end
post
do
required_attributes!
[
:name
]
attrs
=
attributes_for_keys
[
:builds_enabled
,
:container_registry_enabled
,
:description
,
:import_url
,
:issues_enabled
,
:lfs_enabled
,
:merge_requests_enabled
,
:name
,
:namespace_id
,
:only_allow_merge_if_build_succeeds
,
:path
,
:public
,
:public_builds
,
:request_access_enabled
,
:shared_runners_enabled
,
:snippets_enabled
,
:visibility_level
,
:wiki_enabled
,
:only_allow_merge_if_all_discussions_are_resolved
]
attrs
=
map_public_to_visibility_level
(
attrs
)
@project
=
::
Projects
::
CreateService
.
new
(
current_user
,
attrs
).
execute
if
@project
.
saved?
present
@project
,
with:
Entities
::
Project
,
user_can_admin_project:
can?
(
current_user
,
:admin_project
,
@project
)
attrs
=
map_public_to_visibility_level
(
declared_params
(
include_missing:
false
))
project
=
::
Projects
::
CreateService
.
new
(
current_user
,
attrs
).
execute
if
project
.
saved?
present
project
,
with:
Entities
::
Project
,
user_can_admin_project:
can?
(
current_user
,
:admin_project
,
project
)
else
if
@
project
.
errors
[
:limit_reached
].
present?
error!
(
@
project
.
errors
[
:limit_reached
],
403
)
if
project
.
errors
[
:limit_reached
].
present?
error!
(
project
.
errors
[
:limit_reached
],
403
)
end
render_validation_error!
(
@
project
)
render_validation_error!
(
project
)
end
end
# Create new project for a specified user. Only available to admin users.
#
# Parameters:
# user_id (required) - The ID of a user
# name (required) - name for new project
# description (optional) - short project description
# default_branch (optional) - 'master' by default
# issues_enabled (optional)
# merge_requests_enabled (optional)
# builds_enabled (optional)
# wiki_enabled (optional)
# snippets_enabled (optional)
# container_registry_enabled (optional)
# shared_runners_enabled (optional)
# public (optional) - if true same as setting visibility_level = 20
# visibility_level (optional)
# import_url (optional)
# public_builds (optional)
# lfs_enabled (optional)
# request_access_enabled (optional) - Allow users to request member access
# Example Request
# POST /projects/user/:user_id
desc
'Create new project for a specified user. Only available to admin users.'
do
success
Entities
::
Project
end
params
do
requires
:name
,
type:
String
,
desc:
'The name of the project'
requires
:user_id
,
type:
Integer
,
desc:
'The ID of a user'
optional
:default_branch
,
type:
String
,
desc:
'The default branch of the project'
use
:optional_params
use
:create_params
end
post
"user/:user_id"
do
authenticated_as_admin!
user
=
User
.
find
(
params
[
:user_id
])
attrs
=
attributes_for_keys
[
:builds_enabled
,
:default_branch
,
:description
,
:import_url
,
:issues_enabled
,
:lfs_enabled
,
:merge_requests_enabled
,
:name
,
:only_allow_merge_if_build_succeeds
,
:public
,
:public_builds
,
:request_access_enabled
,
:shared_runners_enabled
,
:snippets_enabled
,
:visibility_level
,
:wiki_enabled
,
:only_allow_merge_if_all_discussions_are_resolved
]
attrs
=
map_public_to_visibility_level
(
attrs
)
@project
=
::
Projects
::
CreateService
.
new
(
user
,
attrs
).
execute
if
@project
.
saved?
present
@project
,
with:
Entities
::
Project
,
user_can_admin_project:
can?
(
current_user
,
:admin_project
,
@project
)
user
=
User
.
find_by
(
id:
params
.
delete
(
:user_id
))
not_found!
(
'User'
)
unless
user
attrs
=
map_public_to_visibility_level
(
declared_params
(
include_missing:
false
))
project
=
::
Projects
::
CreateService
.
new
(
user
,
attrs
).
execute
if
project
.
saved?
present
project
,
with:
Entities
::
Project
,
user_can_admin_project:
can?
(
current_user
,
:admin_project
,
project
)
else
render_validation_error!
(
@
project
)
render_validation_error!
(
project
)
end
end
end
params
do
requires
:id
,
type:
String
,
desc:
'The ID of a project'
end
resource
:projects
,
requirements:
{
id:
/[^\/]+/
}
do
desc
'Get a single project'
do
success
Entities
::
ProjectWithAccess
end
get
":id"
do
present
user_project
,
with:
Entities
::
ProjectWithAccess
,
user:
current_user
,
user_can_admin_project:
can?
(
current_user
,
:admin_project
,
user_project
)
end
desc
'Get events for a single project'
do
success
Entities
::
Event
end
params
do
use
:pagination
end
get
":id/events"
do
present
paginate
(
user_project
.
events
.
recent
),
with:
Entities
::
Event
end
# Fork new project for the current user or provided namespace.
#
# Parameters:
# id (required) - The ID of a project
# namespace (optional) - The ID or name of the namespace that the project will be forked into.
# Example Request
# POST /projects/fork/:id
desc
'Fork new project for the current user or provided namespace.'
do
success
Entities
::
Project
end
params
do
optional
:namespace
,
type:
String
,
desc:
'The ID or name of the namespace that the project will be forked into'
end
post
'fork/:id'
do
attrs
=
{}
namespace_id
=
params
[
:namespace
]
fork_params
=
declared_params
(
include_missing:
false
)
namespace_id
=
fork_
params
[
:namespace
]
if
namespace_id
.
present?
namespace
=
Namespace
.
find_by
(
id:
namespace_id
)
||
Namespace
.
find_by_path_or_name
(
namespace_id
)
fork_params
[
:namespace
]
=
if
namespace_id
=~
/^\d+$/
Namespace
.
find_by
(
id:
namespace_id
)
else
Namespace
.
find_by_path_or_name
(
namespace_id
)
end
unless
namespace
&&
can?
(
current_user
,
:create_projects
,
namespace
)
unless
fork_params
[
:namespace
]
&&
can?
(
current_user
,
:create_projects
,
fork_params
[
:namespace
]
)
not_found!
(
'Target Namespace'
)
end
attrs
[
:namespace
]
=
namespace
end
@forked_project
=
::
Projects
::
ForkService
.
new
(
user_project
,
current_user
,
attrs
).
execute
forked_project
=
::
Projects
::
ForkService
.
new
(
user_project
,
current_user
,
fork_params
).
execute
if
@
forked_project
.
errors
.
any?
conflict!
(
@
forked_project
.
errors
.
messages
)
if
forked_project
.
errors
.
any?
conflict!
(
forked_project
.
errors
.
messages
)
else
present
@
forked_project
,
with:
Entities
::
Project
,
user_can_admin_project:
can?
(
current_user
,
:admin_project
,
@
forked_project
)
present
forked_project
,
with:
Entities
::
Project
,
user_can_admin_project:
can?
(
current_user
,
:admin_project
,
forked_project
)
end
end
# Update an existing project
#
# Parameters:
# id (required) - the id of a project
# name (optional) - name of a project
# path (optional) - path of a project
# description (optional) - short project description
# issues_enabled (optional)
# merge_requests_enabled (optional)
# builds_enabled (optional)
# wiki_enabled (optional)
# snippets_enabled (optional)
# container_registry_enabled (optional)
# shared_runners_enabled (optional)
# public (optional) - if true same as setting visibility_level = 20
# visibility_level (optional) - visibility level of a project
# public_builds (optional)
# lfs_enabled (optional)
# Example Request
# PUT /projects/:id
desc
'Update an existing project'
do
success
Entities
::
Project
end
params
do
optional
:name
,
type:
String
,
desc:
'The name of the project'
optional
:default_branch
,
type:
String
,
desc:
'The default branch of the project'
optional
:path
,
type:
String
,
desc:
'The path of the repository'
use
:optional_params
at_least_one_of
:name
,
:description
,
:issues_enabled
,
:merge_requests_enabled
,
:wiki_enabled
,
:builds_enabled
,
:snippets_enabled
,
:shared_runners_enabled
,
:container_registry_enabled
,
:lfs_enabled
,
:public
,
:visibility_level
,
:public_builds
,
:request_access_enabled
,
:only_allow_merge_if_build_succeeds
,
:only_allow_merge_if_all_discussions_are_resolved
,
:path
,
:default_branch
end
put
':id'
do
attrs
=
attributes_for_keys
[
:builds_enabled
,
:container_registry_enabled
,
:default_branch
,
:description
,
:issues_enabled
,
:lfs_enabled
,
:merge_requests_enabled
,
:name
,
:only_allow_merge_if_build_succeeds
,
:path
,
:public
,
:public_builds
,
:request_access_enabled
,
:shared_runners_enabled
,
:snippets_enabled
,
:visibility_level
,
:wiki_enabled
,
:only_allow_merge_if_all_discussions_are_resolved
]
attrs
=
map_public_to_visibility_level
(
attrs
)
authorize_admin_project
attrs
=
map_public_to_visibility_level
(
declared_params
(
include_missing:
false
))
authorize!
:rename_project
,
user_project
if
attrs
[
:name
].
present?
if
attrs
[
:visibility_level
].
present?
authorize!
:change_visibility_level
,
user_project
end
authorize!
:change_visibility_level
,
user_project
if
attrs
[
:visibility_level
].
present?
::
Projects
::
UpdateService
.
new
(
user_project
,
current_user
,
attrs
).
execute
::
Projects
::
UpdateService
.
new
(
user_project
,
current_user
,
attrs
).
execute
if
user_project
.
errors
.
any?
render_validation_error!
(
user_project
)
...
...
@@ -297,12 +291,9 @@ module API
end
end
# Archive project
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# PUT /projects/:id/archive
desc
'Archive a project'
do
success
Entities
::
Project
end
post
':id/archive'
do
authorize!
(
:archive_project
,
user_project
)
...
...
@@ -311,12 +302,9 @@ module API
present
user_project
,
with:
Entities
::
Project
end
# Unarchive project
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# PUT /projects/:id/unarchive
desc
'Unarchive a project'
do
success
Entities
::
Project
end
post
':id/unarchive'
do
authorize!
(
:archive_project
,
user_project
)
...
...
@@ -325,12 +313,9 @@ module API
present
user_project
,
with:
Entities
::
Project
end
# Star project
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# POST /projects/:id/star
desc
'Star a project'
do
success
Entities
::
Project
end
post
':id/star'
do
if
current_user
.
starred?
(
user_project
)
not_modified!
...
...
@@ -342,12 +327,9 @@ module API
end
end
# Unstar project
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# DELETE /projects/:id/star
desc
'Unstar a project'
do
success
Entities
::
Project
end
delete
':id/star'
do
if
current_user
.
starred?
(
user_project
)
current_user
.
toggle_star
(
user_project
)
...
...
@@ -359,67 +341,51 @@ module API
end
end
# Remove project
#
# Parameters:
# id (required) - The ID of a project
# Example Request:
# DELETE /projects/:id
desc
'Remove a project'
delete
":id"
do
authorize!
:remove_project
,
user_project
::
Projects
::
DestroyService
.
new
(
user_project
,
current_user
,
{}).
async_execute
end
# Mark this project as forked from another
#
# Parameters:
# id: (required) - The ID of the project being marked as a fork
# forked_from_id: (required) - The ID of the project it was forked from
# Example Request:
# POST /projects/:id/fork/:forked_from_id
desc
'Mark this project as forked from another'
params
do
requires
:forked_from_id
,
type:
String
,
desc:
'The ID of the project it was forked from'
end
post
":id/fork/:forked_from_id"
do
authenticated_as_admin!
forked_from_project
=
find_project!
(
params
[
:forked_from_id
])
unless
forked_from_project
.
nil?
if
user_project
.
forked_from_project
.
nil?
user_project
.
create_forked_project_link
(
forked_to_project_id:
user_project
.
id
,
forked_from_project_id:
forked_from_project
.
id
)
else
render_api_error!
(
"Project already forked"
,
409
)
end
not_found!
(
"Source Project"
)
unless
forked_from_project
if
user_project
.
forked_from_project
.
nil?
user_project
.
create_forked_project_link
(
forked_to_project_id:
user_project
.
id
,
forked_from_project_id:
forked_from_project
.
id
)
else
not_found!
(
"Source Project"
)
render_api_error!
(
"Project already forked"
,
409
)
end
end
# Remove a forked_from relationship
#
# Parameters:
# id: (required) - The ID of the project being marked as a fork
# Example Request:
# DELETE /projects/:id/fork
desc
'Remove a forked_from relationship'
delete
":id/fork"
do
authorize!
:remove_fork_project
,
user_project
if
user_project
.
forked?
user_project
.
forked_project_link
.
destroy
else
not_modified!
end
end
# Share project with group
#
# Parameters:
# id (required) - The ID of a project
# group_id (required) - The ID of a group
# group_access (required) - Level of permissions for sharing
# expires_at (optional) - Share expiration date
#
# Example Request:
# POST /projects/:id/share
desc
'Share the project with a group'
do
success
Entities
::
ProjectGroupLink
end
params
do
requires
:group_id
,
type:
Integer
,
desc:
'The ID of a group'
requires
:group_access
,
type:
Integer
,
values:
Gitlab
::
Access
.
values
,
desc:
'The group access level'
optional
:expires_at
,
type:
Date
,
desc:
'Share expiration date'
end
post
":id/share"
do
authorize!
:admin_project
,
user_project
required_attributes!
[
:group_id
,
:group_access
]
attrs
=
attributes_for_keys
[
:group_id
,
:group_access
,
:expires_at
]
group
=
Group
.
find_by_id
(
attrs
[
:group_id
])
group
=
Group
.
find_by_id
(
params
[
:group_id
])
unless
group
&&
can?
(
current_user
,
:read_group
,
group
)
not_found!
(
'Group'
)
...
...
@@ -429,7 +395,7 @@ module API
return
render_api_error!
(
"The project sharing with group is disabled"
,
400
)
end
link
=
user_project
.
project_group_links
.
new
(
attrs
)
link
=
user_project
.
project_group_links
.
new
(
declared_params
(
include_missing:
false
)
)
if
link
.
save
present
link
,
with:
Entities
::
ProjectGroupLink
...
...
@@ -451,40 +417,26 @@ module API
no_content!
end
# Upload a file
#
# Parameters:
# id: (required) - The ID of the project
# file: (required) - The file to be uploaded
desc
'Upload a file'
params
do
requires
:file
,
type:
File
,
desc:
'The file to be uploaded'
end
post
":id/uploads"
do
::
Projects
::
UploadService
.
new
(
user_project
,
params
[
:file
]).
execute
end
# search for projects current_user has access to
#
# Parameters:
# query (required) - A string contained in the project name
# per_page (optional) - number of projects to return per page
# page (optional) - the page to retrieve
# Example Request:
# GET /projects/search/:query
get
"/search/:query"
do
search_service
=
Search
::
GlobalService
.
new
(
current_user
,
search:
params
[
:query
]).
execute
projects
=
search_service
.
objects
(
'projects'
,
params
[
:page
])
projects
=
projects
.
reorder
(
project_order_by
=>
project_sort
)
present
paginate
(
projects
),
with:
Entities
::
Project
desc
'Get the users list of a project'
do
success
Entities
::
UserBasic
end
params
do
optional
:search
,
type:
String
,
desc:
'Return list of users matching the search criteria'
use
:pagination
end
# Get a users list
#
# Example Request:
# GET /users
get
':id/users'
do
@
users
=
User
.
where
(
id:
user_project
.
team
.
users
.
map
(
&
:id
))
@users
=
@
users
.
search
(
params
[
:search
])
if
params
[
:search
].
present?
@users
=
paginate
@users
present
@users
,
with:
Entities
::
UserBasic
users
=
User
.
where
(
id:
user_project
.
team
.
users
.
map
(
&
:id
))
users
=
users
.
search
(
params
[
:search
])
if
params
[
:search
].
present?
present
paginate
(
users
)
,
with:
Entities
::
UserBasic
end
end
end
...
...
spec/requests/api/projects_spec.rb
View file @
43c8788e
...
...
@@ -415,16 +415,7 @@ describe API::API, api: true do
not_to
change
{
Project
.
count
}
expect
(
response
).
to
have_http_status
(
400
)
expect
(
json_response
[
'message'
][
'name'
]).
to
eq
([
'can\'t be blank'
,
'is too short (minimum is 0 characters)'
,
Gitlab
::
Regex
.
project_name_regex_message
])
expect
(
json_response
[
'message'
][
'path'
]).
to
eq
([
'can\'t be blank'
,
'is too short (minimum is 0 characters)'
,
Gitlab
::
Regex
.
send
(
:project_path_regex_message
)
])
expect
(
json_response
[
'error'
]).
to
eq
(
'name is missing'
)
end
it
'assigns attributes to project'
do
...
...
@@ -438,6 +429,7 @@ describe API::API, api: true do
post
api
(
"/projects/user/
#{
user
.
id
}
"
,
admin
),
project
expect
(
response
).
to
have_http_status
(
201
)
project
.
each_pair
do
|
k
,
v
|
next
if
%i[has_external_issue_tracker path]
.
include?
(
k
)
expect
(
json_response
[
k
.
to_s
]).
to
eq
(
v
)
...
...
@@ -447,6 +439,8 @@ describe API::API, api: true do
it
'sets a project as public'
do
project
=
attributes_for
(
:project
,
:public
)
post
api
(
"/projects/user/
#{
user
.
id
}
"
,
admin
),
project
expect
(
response
).
to
have_http_status
(
201
)
expect
(
json_response
[
'public'
]).
to
be_truthy
expect
(
json_response
[
'visibility_level'
]).
to
eq
(
Gitlab
::
VisibilityLevel
::
PUBLIC
)
end
...
...
@@ -454,6 +448,8 @@ describe API::API, api: true do
it
'sets a project as public using :public'
do
project
=
attributes_for
(
:project
,
{
public:
true
})
post
api
(
"/projects/user/
#{
user
.
id
}
"
,
admin
),
project
expect
(
response
).
to
have_http_status
(
201
)
expect
(
json_response
[
'public'
]).
to
be_truthy
expect
(
json_response
[
'visibility_level'
]).
to
eq
(
Gitlab
::
VisibilityLevel
::
PUBLIC
)
end
...
...
@@ -461,6 +457,8 @@ describe API::API, api: true do
it
'sets a project as internal'
do
project
=
attributes_for
(
:project
,
:internal
)
post
api
(
"/projects/user/
#{
user
.
id
}
"
,
admin
),
project
expect
(
response
).
to
have_http_status
(
201
)
expect
(
json_response
[
'public'
]).
to
be_falsey
expect
(
json_response
[
'visibility_level'
]).
to
eq
(
Gitlab
::
VisibilityLevel
::
INTERNAL
)
end
...
...
@@ -468,6 +466,7 @@ describe API::API, api: true do
it
'sets a project as internal overriding :public'
do
project
=
attributes_for
(
:project
,
:internal
,
{
public:
true
})
post
api
(
"/projects/user/
#{
user
.
id
}
"
,
admin
),
project
expect
(
response
).
to
have_http_status
(
201
)
expect
(
json_response
[
'public'
]).
to
be_falsey
expect
(
json_response
[
'visibility_level'
]).
to
eq
(
Gitlab
::
VisibilityLevel
::
INTERNAL
)
end
...
...
@@ -848,7 +847,7 @@ describe API::API, api: true do
it
'is idempotent if not forked'
do
expect
(
project_fork_target
.
forked_from_project
).
to
be_nil
delete
api
(
"/projects/
#{
project_fork_target
.
id
}
/fork"
,
admin
)
expect
(
response
).
to
have_http_status
(
200
)
expect
(
response
).
to
have_http_status
(
304
)
expect
(
project_fork_target
.
reload
.
forked_from_project
).
to
be_nil
end
end
...
...
@@ -865,7 +864,7 @@ describe API::API, api: true do
post
api
(
"/projects/
#{
project
.
id
}
/share"
,
user
),
group_id:
group
.
id
,
group_access:
Gitlab
::
Access
::
DEVELOPER
,
expires_at:
expires_at
end
.
to
change
{
ProjectGroupLink
.
count
}.
by
(
1
)
expect
(
response
.
status
).
to
eq
201
expect
(
response
).
to
have_http_status
(
201
)
expect
(
json_response
[
'group_id'
]).
to
eq
(
group
.
id
)
expect
(
json_response
[
'group_access'
]).
to
eq
(
Gitlab
::
Access
::
DEVELOPER
)
expect
(
json_response
[
'expires_at'
]).
to
eq
(
expires_at
.
to_s
)
...
...
@@ -873,18 +872,18 @@ describe API::API, api: true do
it
"returns a 400 error when group id is not given"
do
post
api
(
"/projects/
#{
project
.
id
}
/share"
,
user
),
group_access:
Gitlab
::
Access
::
DEVELOPER
expect
(
response
.
status
).
to
eq
400
expect
(
response
).
to
have_http_status
(
400
)
end
it
"returns a 400 error when access level is not given"
do
post
api
(
"/projects/
#{
project
.
id
}
/share"
,
user
),
group_id:
group
.
id
expect
(
response
.
status
).
to
eq
400
expect
(
response
).
to
have_http_status
(
400
)
end
it
"returns a 400 error when sharing is disabled"
do
project
.
namespace
.
update
(
share_with_group_lock:
true
)
post
api
(
"/projects/
#{
project
.
id
}
/share"
,
user
),
group_id:
group
.
id
,
group_access:
Gitlab
::
Access
::
DEVELOPER
expect
(
response
.
status
).
to
eq
400
expect
(
response
).
to
have_http_status
(
400
)
end
it
'returns a 404 error when user cannot read group'
do
...
...
@@ -892,19 +891,20 @@ describe API::API, api: true do
post
api
(
"/projects/
#{
project
.
id
}
/share"
,
user
),
group_id:
private_group
.
id
,
group_access:
Gitlab
::
Access
::
DEVELOPER
expect
(
response
.
status
).
to
eq
404
expect
(
response
).
to
have_http_status
(
404
)
end
it
'returns a 404 error when group does not exist'
do
post
api
(
"/projects/
#{
project
.
id
}
/share"
,
user
),
group_id:
1234
,
group_access:
Gitlab
::
Access
::
DEVELOPER
expect
(
response
.
status
).
to
eq
404
expect
(
response
).
to
have_http_status
(
404
)
end
it
"returns a 40
9
error when wrong params passed"
do
it
"returns a 40
0
error when wrong params passed"
do
post
api
(
"/projects/
#{
project
.
id
}
/share"
,
user
),
group_id:
group
.
id
,
group_access:
1234
expect
(
response
.
status
).
to
eq
409
expect
(
json_response
[
'message'
]).
to
eq
'Group access is not included in the list'
expect
(
response
).
to
have_http_status
(
400
)
expect
(
json_response
[
'error'
]).
to
eq
'group_access does not have a valid value'
end
end
...
...
@@ -1017,7 +1017,6 @@ describe API::API, api: true do
it
'updates visibility_level from public to private'
do
project3
.
update_attributes
({
visibility_level:
Gitlab
::
VisibilityLevel
::
PUBLIC
})
project_param
=
{
public:
false
}
put
api
(
"/projects/
#{
project3
.
id
}
"
,
user
),
project_param
expect
(
response
).
to
have_http_status
(
200
)
...
...
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