lib/api/v1/teams.rb

Summary

Maintainability
C
1 day
Test Coverage
# frozen_string_literal: true

module API
  module V1
    class Teams < Grape::API
      include PaginationParams
      include OrderingParams

      version "v1", using: :path

      resource :teams do
        before do
          authorization!(force_admin: false)
        end

        desc "Returns list of teams",
             tags:     ["teams"],
             detail:   "This will expose all teams that the user is member of or has access to.
                        That mean if the user is an admin, this will return all the teams created by
                        all the users. If you want to check if the user is a member of a team, check
                        the role attribute.",
             is_array: true,
             entity:   API::Entities::Teams,
             failure:  [
               [401, "Authentication fails"],
               [403, "Authorization fails"]
             ]

        params do
          use :pagination
          use :ordering
        end

        get do
          teams = paginate(order(policy_scope(Team)))
          present teams, with: API::Entities::Teams, type: current_type
        end

        desc "Create a team",
             entity:   API::Entities::Teams,
             consumes: ["application/x-www-form-urlencoded", "application/json"],
             failure:  [
               [400, "Bad request", API::Entities::ApiErrors],
               [401, "Authentication fails"],
               [403, "Authorization fails"],
               [422, "Unprocessable Entity", API::Entities::FullApiErrors]
             ]

        params do
          requires :name, type: String, documentation: { desc: "Team name" }
          optional :description, type: String, documentation: { desc: "Team description" }
          optional :owner_id, type: Integer, documentation: { desc: "Team owner" }
        end

        post do
          authorize Team, :create?

          team = ::Teams::CreateService.new(current_user, permitted_params).execute

          if team.valid?
            present team,
                    with:         API::Entities::Teams,
                    current_user: current_user,
                    type:         current_type
          else
            unprocessable_entity!(team.errors)
          end
        end

        # Update team with given :id.
        desc "Update team",
             params:   API::Entities::Teams.documentation.slice(:id),
             failure:  [
               [400, "Bad request", API::Entities::ApiErrors],
               [401, "Authentication fails"],
               [403, "Authorization fails"],
               [404, "Not found"],
               [422, "Unprocessable Entity", API::Entities::FullApiErrors]
             ],
             consumes: ["application/x-www-form-urlencoded", "application/json"]

        params do
          requires :team, type: Hash do
            optional :all,
                     only:  [:name],
                     using: API::Entities::Teams.documentation.slice(:name)
            optional :all,
                     only:  [:description],
                     using: API::Entities::Teams.documentation.slice(:description)
          end
        end

        put ":id" do
          attrs = permitted_params.merge(id: params[:id])
          ts = ::Teams::UpdateService.new(current_user, attrs)
          team = ts.build
          authorize team, :update?

          if ts.execute
            present team.reload,
                    with:         API::Entities::Teams,
                    current_user: current_user,
                    type:         current_type
          else
            unprocessable_entity!(team.errors.messages)
          end
        end

        desc "Deletes a team",
             entity:  API::Entities::Teams,
             failure: [
               [400, "Unprocessable Entity", API::Entities::ApiErrors],
               [401, "Authentication fails"],
               [403, "Authorization fails"],
               [404, "Not found"],
               [422, "Unprocessable Entity", API::Entities::ApiErrors]
             ]

        params do
          requires :id, documentation: { desc: "Team id" }
          optional :new_team, documentation: { desc: "Team that will get the original namespaces
            from the deleted team" }
        end

        delete ":id" do
          team = Team.find_by!(id: params[:id])
          new_team = Team.find_by!(name: params[:new_team]) if params[:new_team].present?
          authorize team, :destroy?

          svc = ::Teams::DestroyService.new(current_user)
          destroyed = svc.execute(team, new_team)

          if destroyed
            status 204
          else
            unprocessable_entity!(svc.error)
          end
        end

        desc "Disables any LDAP check for the team",
             params:   API::Entities::Teams.documentation.slice(:id),
             failure:  [
               [400, "Bad request", API::Entities::ApiErrors],
               [401, "Authentication fails"],
               [403, "Authorization fails"],
               [404, "Not found"],
               [405, "Method Not Allowed", API::Entities::ApiErrors]
             ],
             consumes: ["application/x-www-form-urlencoded", "application/json"]

        params do
          requires :id, documentation: { desc: "Team id" }
        end

        post ":id/ldap_check" do
          if APP_CONFIG.disabled?("ldap") || APP_CONFIG.disabled?("ldap.group_sync")
            method_not_allowed!("this instance has disabled this endpoint")
          else
            attrs = permitted_params.merge(id: params[:id])
            team = Team.find(attrs[:id])
            authorize team, :update?

            team.update!(ldap_group_checked: Team.ldap_statuses[:disabled])
            status :ok
          end
        end

        route_param :id, type: String, requirements: { id: /.*/ } do
          resource :namespaces do
            desc "Returns the list of namespaces for the given team",
                 params:   API::Entities::Teams.documentation.slice(:id),
                 is_array: true,
                 entity:   API::Entities::Namespaces,
                 failure:  [
                   [401, "Authentication fails"],
                   [403, "Authorization fails"],
                   [404, "Not found"]
                 ]

            get do
              team = Team.find params[:id]
              authorize team, :show?
              present team.namespaces, with: API::Entities::Namespaces, type: current_type
            end
          end

          resource :members do
            desc "Returns the list of team members",
                 params:   API::Entities::Teams.documentation.slice(:id),
                 is_array: true,
                 entity:   API::Entities::Users,
                 failure:  [
                   [401, "Authentication fails"],
                   [403, "Authorization fails"],
                   [404, "Not found"]
                 ]

            get do
              team = Team.find params[:id]
              authorize team, :member?
              present team.users, with: API::Entities::Users
            end

            desc "Deletes a member from a team",
                 entity:  API::Entities::TeamMembers,
                 failure: [
                   [400, "Unprocessable Entity", API::Entities::ApiErrors],
                   [401, "Authentication fails"],
                   [403, "Authorization fails"],
                   [404, "Not found"],
                   [422, "Unprocessable Entity", API::Entities::ApiErrors]
                 ]

            params do
              requires :id, documentation: { desc: "Team id" }
              requires :member_id, documentation: { desc: "Team member id" }
            end

            delete ":member_id" do
              team_user = TeamUser.find_by!(id: params[:member_id], team_id: params[:id])
              authorize team_user, :destroy?

              svc = ::TeamUsers::DestroyService.new(current_user)
              destroyed = svc.execute(team_user)

              if destroyed
                status 204
              else
                unprocessable_entity!(svc.message)
              end
            end

            desc "Updates a member from a team",
                 entity:  API::Entities::TeamMembers,
                 failure: [
                   [400, "Unprocessable Entity", API::Entities::ApiErrors],
                   [401, "Authentication fails"],
                   [403, "Authorization fails"],
                   [404, "Not found"],
                   [422, "Unprocessable Entity", API::Entities::ApiErrors]
                 ]

            params do
              requires :id, documentation: { desc: "Team id" }
              requires :member_id, type: Integer, documentation: { desc: "Team member id" }
              requires :role, type: String, documentation: { desc: "Team member role" }
            end

            put ":member_id" do
              team_user = TeamUser.find_by!(id: params[:member_id], team_id: params[:id])
              authorize team_user, :update?

              svc = ::TeamUsers::UpdateService.new(current_user, permitted_params)
              updated = svc.execute(team_user)

              if updated
                present team_user,
                        with:         API::Entities::TeamMembers,
                        current_user: current_user,
                        type:         current_type
              else
                unprocessable_entity!(svc.message)
              end
            end

            desc "Adds a user as member in a team",
                 entity:  API::Entities::TeamMembers,
                 failure: [
                   [401, "Authentication fails"],
                   [403, "Authorization fails"],
                   [404, "Not found"]
                 ]

            params do
              requires :id, documentation: { desc: "Team id" }
              requires :role, type: String, documentation: { desc: "Team member role" }
              requires :user, type: String, documentation: { desc: "Team member username" }
            end

            post do
              team_user = ::TeamUsers::BuildService.new(current_user, permitted_params).execute
              authorize team_user, :create?

              team_user = ::TeamUsers::CreateService.new(current_user, team_user).execute

              if team_user.valid? && team_user.persisted?
                present team_user,
                        with:         API::Entities::TeamMembers,
                        current_user: current_user,
                        type:         current_type
              else
                unprocessable_entity!(team_user.errors)
              end
            end
          end

          desc "Show teams by id",
               entity:  API::Entities::Teams,
               failure: [
                 [401, "Authentication fails"],
                 [403, "Authorization fails"],
                 [404, "Not found"]
               ]

          params do
            requires :id, type: String, documentation: { desc: "Team ID" }
          end

          get do
            team = Team.find(params[:id])
            authorize team, :show?
            present team, with: API::Entities::Teams, type: current_type
          end
        end
      end
    end
  end
end