BigW Consortium Gitlab

groups.rb 7.43 KB
Newer Older
1 2 3 4 5 6 7 8
module API
  module V3
    class Groups < Grape::API
      include PaginationParams

      before { authenticate! }

      helpers do
9 10 11 12 13 14 15
        params :optional_params do
          optional :description, type: String, desc: 'The description of the group'
          optional :visibility_level, type: Integer, desc: 'The visibility level of the group'
          optional :lfs_enabled, type: Boolean, desc: 'Enable/disable LFS for the projects in this group'
          optional :request_access_enabled, type: Boolean, desc: 'Allow users to request member access'
        end

16 17 18 19 20 21
        params :statistics_params do
          optional :statistics, type: Boolean, default: false, desc: 'Include project statistics'
        end

        def present_groups(groups, options = {})
          options = options.reverse_merge(
22
            with: Entities::Group,
23
            current_user: current_user
24 25 26 27 28 29 30 31
          )

          groups = groups.with_statistics if options[:statistics]
          present paginate(groups), options
        end
      end

      resource :groups do
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
        desc 'Get a groups list' do
          success Entities::Group
        end
        params do
          use :statistics_params
          optional :skip_groups, type: Array[Integer], desc: 'Array of group ids to exclude from list'
          optional :all_available, type: Boolean, desc: 'Show all group that you have access to'
          optional :search, type: String, desc: 'Search for a specific group'
          optional :order_by, type: String, values: %w[name path], default: 'name', desc: 'Order by name or path'
          optional :sort, type: String, values: %w[asc desc], default: 'asc', desc: 'Sort by asc (ascending) or desc (descending)'
          use :pagination
        end
        get do
          groups = if current_user.admin
                     Group.all
                   elsif params[:all_available]
48
                     GroupsFinder.new(current_user).execute
49 50 51 52 53 54 55 56
                   else
                     current_user.groups
                   end

          groups = groups.search(params[:search]) if params[:search].present?
          groups = groups.where.not(id: params[:skip_groups]) if params[:skip_groups].present?
          groups = groups.reorder(params[:order_by] => params[:sort])

57
          present_groups groups, statistics: params[:statistics] && current_user.admin?
58 59
        end

60
        desc 'Get list of owned groups for authenticated user' do
61
          success Entities::Group
62 63 64 65 66 67 68 69
        end
        params do
          use :pagination
          use :statistics_params
        end
        get '/owned' do
          present_groups current_user.owned_groups, statistics: params[:statistics]
        end
70 71 72 73 74 75 76

        desc 'Create a group. Available only for users who can create groups.' do
          success Entities::Group
        end
        params do
          requires :name, type: String, desc: 'The name of the group'
          requires :path, type: String, desc: 'The path of the group'
77 78 79 80 81

          if ::Group.supports_nested_groups?
            optional :parent_id, type: Integer, desc: 'The parent group id for creating nested group'
          end

82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
          use :optional_params
        end
        post do
          authorize! :create_group

          group = ::Groups::CreateService.new(current_user, declared_params(include_missing: false)).execute

          if group.persisted?
            present group, with: Entities::Group, current_user: current_user
          else
            render_api_error!("Failed to save group #{group.errors.messages}", 400)
          end
        end
      end

      params do
        requires :id, type: String, desc: 'The ID of a group'
      end
100
      resource :groups, requirements: { id: %r{[^/]+} } do
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
        desc 'Update a group. Available only for users who can administrate groups.' do
          success Entities::Group
        end
        params do
          optional :name, type: String, desc: 'The name of the group'
          optional :path, type: String, desc: 'The path of the group'
          use :optional_params
          at_least_one_of :name, :path, :description, :visibility_level,
                          :lfs_enabled, :request_access_enabled
        end
        put ':id' do
          group = find_group!(params[:id])
          authorize! :admin_group, group

          if ::Groups::UpdateService.new(group, current_user, declared_params(include_missing: false)).execute
            present group, with: Entities::GroupDetail, current_user: current_user
          else
            render_validation_error!(group)
          end
        end

        desc 'Get a single group, with containing projects.' do
          success Entities::GroupDetail
        end
        get ":id" do
          group = find_group!(params[:id])
          present group, with: Entities::GroupDetail, current_user: current_user
        end

        desc 'Remove a group.'
        delete ":id" do
          group = find_group!(params[:id])
          authorize! :admin_group, group
          present ::Groups::DestroyService.new(group, current_user).execute, with: Entities::GroupDetail, current_user: current_user
        end

        desc 'Get a list of projects in this group.' do
          success Entities::Project
        end
        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'
          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'
          optional :simple, type: Boolean, default: false,
                            desc: 'Return only the ID, URL, name, and path of each project'
          optional :owned, type: Boolean, default: false, desc: 'Limit by owned by authenticated user'
          optional :starred, type: Boolean, default: false, desc: 'Limit by starred status'

          use :pagination
        end
        get ":id/projects" do
          group = find_group!(params[:id])
158
          projects = GroupProjectsFinder.new(group: group, current_user: current_user).execute
159 160 161 162 163 164 165 166 167 168 169
          projects = filter_projects(projects)
          entity = params[:simple] ? ::API::Entities::BasicProjectDetails : Entities::Project
          present paginate(projects), with: entity, current_user: current_user
        end

        desc 'Transfer a project to the group namespace. Available only for admin.' do
          success Entities::GroupDetail
        end
        params do
          requires :project_id, type: String, desc: 'The ID or path of the project'
        end
170
        post ":id/projects/:project_id", requirements: { project_id: /.+/ } do
171 172 173 174 175 176 177 178 179 180 181
          authenticated_as_admin!
          group = find_group!(params[:id])
          project = find_project!(params[:project_id])
          result = ::Projects::TransferService.new(project, current_user).execute(group)

          if result
            present group, with: Entities::GroupDetail, current_user: current_user
          else
            render_api_error!("Failed to transfer project #{project.errors.messages}", 400)
          end
        end
182 183 184 185
      end
    end
  end
end