projects.rb 12.4 KB
Newer Older
1
module API
N
Nihad Abbasov 已提交
2 3 4 5
  # Projects API
  class Projects < Grape::API
    before { authenticate! }

6
    resource :projects, requirements: { id: /[^\/]+/ } do
7
      helpers do
8 9
        def map_public_to_visibility_level(attrs)
          publik = attrs.delete(:public)
10 11 12 13 14 15
          if publik.present? && !attrs[:visibility_level].present?
            publik = parse_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
16 17
          attrs
        end
18 19
      end

N
Nihad Abbasov 已提交
20 21 22 23 24
      # Get a projects list for authenticated user
      #
      # Example Request:
      #   GET /projects
      get do
D
Dmitriy Zaporozhets 已提交
25
        @projects = current_user.authorized_projects
26
        @projects = filter_projects(@projects)
D
Dmitriy Zaporozhets 已提交
27
        @projects = paginate @projects
28
        present @projects, with: Entities::ProjectWithAccess, user: current_user
N
Nihad Abbasov 已提交
29 30
      end

31 32 33 34 35
      # Get an owned projects list for authenticated user
      #
      # Example Request:
      #   GET /projects/owned
      get '/owned' do
36
        @projects = current_user.owned_projects
37
        @projects = filter_projects(@projects)
38
        @projects = paginate @projects
39
        present @projects, with: Entities::ProjectWithAccess, user: current_user
40 41
      end

42 43 44 45 46 47 48 49 50 51 52
      # Gets starred project for the authenticated user
      #
      # Example Request:
      #   GET /projects/starred
      get '/starred' do
        @projects = current_user.starred_projects
        @projects = filter_projects(@projects)
        @projects = paginate @projects
        present @projects, with: Entities::Project
      end

53 54 55 56 57 58
      # Get all projects for admin user
      #
      # Example Request:
      #   GET /projects/all
      get '/all' do
        authenticated_as_admin!
59 60
        @projects = Project.all
        @projects = filter_projects(@projects)
61
        @projects = paginate @projects
62
        present @projects, with: Entities::ProjectWithAccess, user: current_user
63 64
      end

N
Nihad Abbasov 已提交
65 66 67
      # Get a single project
      #
      # Parameters:
68
      #   id (required) - The ID of a project
N
Nihad Abbasov 已提交
69 70 71
      # Example Request:
      #   GET /projects/:id
      get ":id" do
72 73
        present user_project, with: Entities::ProjectWithAccess, user: current_user,
                              user_can_admin_project: can?(current_user, :admin_project, user_project)
N
Nihad Abbasov 已提交
74 75
      end

76
      # Get events for a single project
D
Dmitriy Zaporozhets 已提交
77 78 79 80
      #
      # Parameters:
      #   id (required) - The ID of a project
      # Example Request:
C
Ciro Santilli 已提交
81
      #   GET /projects/:id/events
D
Dmitriy Zaporozhets 已提交
82
      get ":id/events" do
83
        events = paginate user_project.events.recent
D
Dmitriy Zaporozhets 已提交
84 85 86
        present events, with: Entities::Event
      end

87 88 89 90
      # Create new project
      #
      # Parameters:
      #   name (required) - name for new project
91
      #   description (optional) - short project description
92 93
      #   issues_enabled (optional)
      #   merge_requests_enabled (optional)
94
      #   builds_enabled (optional)
95
      #   wiki_enabled (optional)
96
      #   snippets_enabled (optional)
K
Kamil Trzcinski 已提交
97
      #   shared_runners_enabled (optional)
98
      #   namespace_id (optional) - defaults to user namespace
99 100
      #   public (optional) - if true same as setting visibility_level = 20
      #   visibility_level (optional) - 0 by default
101
      #   import_url (optional)
102 103 104
      # Example Request
      #   POST /projects
      post do
105
        required_attributes! [:name]
106
        attrs = attributes_for_keys [:name,
107 108 109 110
                                     :path,
                                     :description,
                                     :issues_enabled,
                                     :merge_requests_enabled,
111
                                     :builds_enabled,
112 113
                                     :wiki_enabled,
                                     :snippets_enabled,
K
Kamil Trzcinski 已提交
114
                                     :shared_runners_enabled,
115
                                     :namespace_id,
116
                                     :public,
117 118
                                     :visibility_level,
                                     :import_url]
119
        attrs = map_public_to_visibility_level(attrs)
120
        @project = ::Projects::CreateService.new(current_user, attrs).execute
121
        if @project.saved?
122 123
          present @project, with: Entities::Project,
                            user_can_admin_project: can?(current_user, :admin_project, @project)
124
        else
125 126 127
          if @project.errors[:limit_reached].present?
            error!(@project.errors[:limit_reached], 403)
          end
J
jubianchi 已提交
128
          render_validation_error!(@project)
129 130 131
        end
      end

A
Angus MacArthur 已提交
132 133 134 135 136 137 138
      # 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
139 140
      #   issues_enabled (optional)
      #   merge_requests_enabled (optional)
141
      #   builds_enabled (optional)
142 143
      #   wiki_enabled (optional)
      #   snippets_enabled (optional)
K
Kamil Trzcinski 已提交
144
      #   shared_runners_enabled (optional)
145 146
      #   public (optional) - if true same as setting visibility_level = 20
      #   visibility_level (optional)
147
      #   import_url (optional)
A
Angus MacArthur 已提交
148 149 150 151 152 153
      # Example Request
      #   POST /projects/user/:user_id
      post "user/:user_id" do
        authenticated_as_admin!
        user = User.find(params[:user_id])
        attrs = attributes_for_keys [:name,
154 155 156 157
                                     :description,
                                     :default_branch,
                                     :issues_enabled,
                                     :merge_requests_enabled,
158
                                     :builds_enabled,
159 160
                                     :wiki_enabled,
                                     :snippets_enabled,
K
Kamil Trzcinski 已提交
161
                                     :shared_runners_enabled,
162
                                     :public,
163 164
                                     :visibility_level,
                                     :import_url]
165
        attrs = map_public_to_visibility_level(attrs)
166
        @project = ::Projects::CreateService.new(user, attrs).execute
A
Angus MacArthur 已提交
167
        if @project.saved?
168 169
          present @project, with: Entities::Project,
                            user_can_admin_project: can?(current_user, :admin_project, @project)
A
Angus MacArthur 已提交
170
        else
J
jubianchi 已提交
171
          render_validation_error!(@project)
A
Angus MacArthur 已提交
172 173 174
        end
      end

175 176 177 178 179 180 181 182 183 184 185 186 187
      # Fork new project for the current user.
      #
      # Parameters:
      #   id (required) - The ID of a project
      # Example Request
      #   POST /projects/fork/:id
      post 'fork/:id' do
        @forked_project =
          ::Projects::ForkService.new(user_project,
                                      current_user).execute
        if @forked_project.errors.any?
          conflict!(@forked_project.errors.messages)
        else
188 189 190
          present @forked_project, with: Entities::Project,
                                   user_can_admin_project: can?(current_user, :admin_project, @forked_project)
         end
191 192
      end

193 194 195 196 197 198 199 200 201
      # 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)
202
      #   builds_enabled (optional)
203 204
      #   wiki_enabled (optional)
      #   snippets_enabled (optional)
K
Kamil Trzcinski 已提交
205
      #   shared_runners_enabled (optional)
206 207 208 209 210 211 212 213 214 215 216
      #   public (optional) - if true same as setting visibility_level = 20
      #   visibility_level (optional) - visibility level of a project
      # Example Request
      #   PUT /projects/:id
      put ':id' do
        attrs = attributes_for_keys [:name,
                                     :path,
                                     :description,
                                     :default_branch,
                                     :issues_enabled,
                                     :merge_requests_enabled,
217
                                     :builds_enabled,
218 219
                                     :wiki_enabled,
                                     :snippets_enabled,
K
Kamil Trzcinski 已提交
220
                                     :shared_runners_enabled,
221 222 223 224 225 226 227 228 229 230 231 232
                                     :public,
                                     :visibility_level]
        attrs = map_public_to_visibility_level(attrs)
        authorize_admin_project
        authorize! :rename_project, user_project if attrs[:name].present?
        if attrs[:visibility_level].present?
          authorize! :change_visibility_level, user_project
        end

        ::Projects::UpdateService.new(user_project,
                                      current_user, attrs).execute

233
        if user_project.errors.any?
234
          render_validation_error!(user_project)
235
        else
236 237
          present user_project, with: Entities::Project,
                                user_can_admin_project: can?(current_user, :admin_project, user_project)
238 239 240
        end
      end

241 242 243 244 245 246 247 248
      # Remove project
      #
      # Parameters:
      #   id (required) - The ID of a project
      # Example Request:
      #   DELETE /projects/:id
      delete ":id" do
        authorize! :remove_project, user_project
V
Vinnie Okada 已提交
249
        ::Projects::DestroyService.new(user_project, current_user, {}).execute
250
      end
A
Angus MacArthur 已提交
251

252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
      # 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
      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
        else
269
          not_found!("Source Project")
270 271 272 273 274 275 276
        end

      end

      # Remove a forked_from relationship
      #
      # Parameters:
D
Douwe Maan 已提交
277
      #   id: (required) - The ID of the project being marked as a fork
278 279 280
      # Example Request:
      #  DELETE /projects/:id/fork
      delete ":id/fork" do
281
        authorize! :remove_fork_project, user_project
282
        if user_project.forked?
283 284 285
          user_project.forked_project_link.destroy
        end
      end
D
Douwe Maan 已提交
286 287 288 289 290 291 292 293 294 295

      # Upload a file
      #
      # Parameters:
      #   id: (required) - The ID of the project
      #   file: (required) - The file to be uploaded
      post ":id/uploads" do
        ::Projects::UploadService.new(user_project, params[:file]).execute
      end

296 297 298 299
      # search for projects current_user has access to
      #
      # Parameters:
      #   query (required) - A string contained in the project name
300 301
      #   per_page (optional) - number of projects to return per page
      #   page (optional) - the page to retrieve
302 303 304 305
      # Example Request:
      #   GET /projects/search/:query
      get "/search/:query" do
        ids = current_user.authorized_projects.map(&:id)
306 307
        visibility_levels = [ Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC ]
        projects = Project.where("(id in (?) OR visibility_level in (?)) AND (name LIKE (?))", ids, visibility_levels, "%#{params[:query]}%")
308
        sort = params[:sort] == 'desc' ? 'desc' : 'asc'
309 310

        projects = case params["order_by"]
311 312 313 314 315
                   when 'id' then projects.order("id #{sort}")
                   when 'name' then projects.order("name #{sort}")
                   when 'created_at' then projects.order("created_at #{sort}")
                   when 'last_activity_at' then projects.order("last_activity_at #{sort}")
                   else projects
316 317
                   end

318
        present paginate(projects), with: Entities::Project
319
      end
320 321 322 323 324 325 326 327 328 329


      # 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
330
        present @users, with: Entities::UserBasic
331
      end
N
Nihad Abbasov 已提交
332 333 334
    end
  end
end