diff options
Diffstat (limited to 'lib/api/users.rb')
-rw-r--r-- | lib/api/users.rb | 131 |
1 files changed, 85 insertions, 46 deletions
diff --git a/lib/api/users.rb b/lib/api/users.rb index e7c1d644324..501ed629c7e 100644 --- a/lib/api/users.rb +++ b/lib/api/users.rb @@ -8,6 +8,8 @@ module API allow_access_with_scope :read_user, if: -> (request) { request.get? } + feature_category :users, ['/users/:id/custom_attributes', '/users/:id/custom_attributes/:key'] + resource :users, requirements: { uid: /[0-9]*/, id: /[0-9]*/ } do include CustomAttributesEndpoints @@ -63,9 +65,9 @@ module API params :sort_params do optional :order_by, type: String, values: %w[id name username created_at updated_at], - default: 'id', desc: 'Return users ordered by a field' + default: 'id', desc: 'Return users ordered by a field' optional :sort, type: String, values: %w[asc desc], default: 'desc', - desc: 'Return users sorted in ascending and descending order' + desc: 'Return users sorted in ascending and descending order' end end @@ -93,7 +95,7 @@ module API use :optional_index_params_ee end # rubocop: disable CodeReuse/ActiveRecord - get do + get feature_category: :users do authenticated_as_admin! if params[:external].present? || (params[:extern_uid].present? && params[:provider].present?) unless current_user&.admin? @@ -134,7 +136,7 @@ module API use :with_custom_attributes end # rubocop: disable CodeReuse/ActiveRecord - get ":id" do + get ":id", feature_category: :users do user = User.find_by(id: params[:id]) not_found!('User') unless user && can?(current_user, :read_user, user) @@ -149,7 +151,7 @@ module API params do requires :user_id, type: String, desc: 'The ID or username of the user' end - get ":user_id/status", requirements: API::USER_REQUIREMENTS do + get ":user_id/status", requirements: API::USER_REQUIREMENTS, feature_category: :users do user = find_user(params[:user_id]) not_found!('User') unless user && can?(current_user, :read_user, user) @@ -170,7 +172,7 @@ module API optional :force_random_password, type: Boolean, desc: 'Flag indicating a random password will be set' use :optional_attributes end - post do + post feature_category: :users do authenticated_as_admin! params = declared_params(include_missing: false) @@ -204,7 +206,7 @@ module API use :optional_attributes end # rubocop: disable CodeReuse/ActiveRecord - put ":id" do + put ":id", feature_category: :users do authenticated_as_admin! user = User.find_by(id: params.delete(:id)) @@ -245,7 +247,7 @@ module API requires :provider, type: String, desc: 'The external provider' end # rubocop: disable CodeReuse/ActiveRecord - delete ":id/identities/:provider" do + delete ":id/identities/:provider", feature_category: :authentication_and_authorization do authenticated_as_admin! user = User.find_by(id: params[:id]) @@ -268,7 +270,7 @@ module API optional :expires_at, type: DateTime, desc: 'The expiration date of the SSH key in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)' end # rubocop: disable CodeReuse/ActiveRecord - post ":id/keys" do + post ":id/keys", feature_category: :authentication_and_authorization do authenticated_as_admin! user = User.find_by(id: params.delete(:id)) @@ -291,7 +293,7 @@ module API requires :user_id, type: String, desc: 'The ID or username of the user' use :pagination end - get ':user_id/keys', requirements: API::USER_REQUIREMENTS do + get ':user_id/keys', requirements: API::USER_REQUIREMENTS, feature_category: :authentication_and_authorization do user = find_user(params[:user_id]) not_found!('User') unless user && can?(current_user, :read_user, user) @@ -307,7 +309,7 @@ module API requires :key_id, type: Integer, desc: 'The ID of the SSH key' end # rubocop: disable CodeReuse/ActiveRecord - delete ':id/keys/:key_id' do + delete ':id/keys/:key_id', feature_category: :authentication_and_authorization do authenticated_as_admin! user = User.find_by(id: params[:id]) @@ -332,7 +334,7 @@ module API requires :key, type: String, desc: 'The new GPG key' end # rubocop: disable CodeReuse/ActiveRecord - post ':id/gpg_keys' do + post ':id/gpg_keys', feature_category: :authentication_and_authorization do authenticated_as_admin! user = User.find_by(id: params.delete(:id)) @@ -357,7 +359,7 @@ module API use :pagination end # rubocop: disable CodeReuse/ActiveRecord - get ':id/gpg_keys' do + get ':id/gpg_keys', feature_category: :authentication_and_authorization do user = User.find_by(id: params[:id]) not_found!('User') unless user @@ -374,7 +376,7 @@ module API requires :key_id, type: Integer, desc: 'The ID of the GPG key' end # rubocop: disable CodeReuse/ActiveRecord - get ':id/gpg_keys/:key_id' do + get ':id/gpg_keys/:key_id', feature_category: :authentication_and_authorization do user = User.find_by(id: params[:id]) not_found!('User') unless user @@ -393,7 +395,7 @@ module API requires :key_id, type: Integer, desc: 'The ID of the GPG key' end # rubocop: disable CodeReuse/ActiveRecord - delete ':id/gpg_keys/:key_id' do + delete ':id/gpg_keys/:key_id', feature_category: :authentication_and_authorization do authenticated_as_admin! user = User.find_by(id: params[:id]) @@ -417,7 +419,7 @@ module API requires :key_id, type: Integer, desc: 'The ID of the GPG key' end # rubocop: disable CodeReuse/ActiveRecord - post ':id/gpg_keys/:key_id/revoke' do + post ':id/gpg_keys/:key_id/revoke', feature_category: :authentication_and_authorization do authenticated_as_admin! user = User.find_by(id: params[:id]) @@ -440,7 +442,7 @@ module API optional :skip_confirmation, type: Boolean, desc: 'Skip confirmation of email and assume it is verified' end # rubocop: disable CodeReuse/ActiveRecord - post ":id/emails" do + post ":id/emails", feature_category: :users do authenticated_as_admin! user = User.find_by(id: params.delete(:id)) @@ -464,7 +466,7 @@ module API use :pagination end # rubocop: disable CodeReuse/ActiveRecord - get ':id/emails' do + get ':id/emails', feature_category: :users do authenticated_as_admin! user = User.find_by(id: params[:id]) not_found!('User') unless user @@ -481,7 +483,7 @@ module API requires :email_id, type: Integer, desc: 'The ID of the email' end # rubocop: disable CodeReuse/ActiveRecord - delete ':id/emails/:email_id' do + delete ':id/emails/:email_id', feature_category: :users do authenticated_as_admin! user = User.find_by(id: params[:id]) not_found!('User') unless user @@ -503,7 +505,7 @@ module API optional :hard_delete, type: Boolean, desc: "Whether to remove a user's contributions" end # rubocop: disable CodeReuse/ActiveRecord - delete ":id" do + delete ":id", feature_category: :users do Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab/issues/20757') authenticated_as_admin! @@ -523,7 +525,7 @@ module API requires :id, type: Integer, desc: 'The ID of the user' end # rubocop: disable CodeReuse/ActiveRecord - post ':id/activate' do + post ':id/activate', feature_category: :authentication_and_authorization do authenticated_as_admin! user = User.find_by(id: params[:id]) @@ -538,7 +540,7 @@ module API requires :id, type: Integer, desc: 'The ID of the user' end # rubocop: disable CodeReuse/ActiveRecord - post ':id/deactivate' do + post ':id/deactivate', feature_category: :authentication_and_authorization do authenticated_as_admin! user = User.find_by(id: params[:id]) not_found!('User') unless user @@ -564,7 +566,7 @@ module API requires :id, type: Integer, desc: 'The ID of the user' end # rubocop: disable CodeReuse/ActiveRecord - post ':id/block' do + post ':id/block', feature_category: :authentication_and_authorization do authenticated_as_admin! user = User.find_by(id: params[:id]) not_found!('User') unless user @@ -589,7 +591,7 @@ module API requires :id, type: Integer, desc: 'The ID of the user' end # rubocop: disable CodeReuse/ActiveRecord - post ':id/unblock' do + post ':id/unblock', feature_category: :authentication_and_authorization do authenticated_as_admin! user = User.find_by(id: params[:id]) not_found!('User') unless user @@ -612,7 +614,7 @@ module API optional :type, type: String, values: %w[Project Namespace] use :pagination end - get ":user_id/memberships" do + get ":user_id/memberships", feature_category: :users do authenticated_as_admin! user = find_user_by_id(params) @@ -656,7 +658,9 @@ module API use :pagination optional :state, type: String, default: 'all', values: %w[all active inactive], desc: 'Filters (all|active|inactive) impersonation_tokens' end - get { present paginate(finder(declared_params(include_missing: false)).execute), with: Entities::ImpersonationToken } + get feature_category :authentication_and_authorization do + present paginate(finder(declared_params(include_missing: false)).execute), with: Entities::ImpersonationToken + end desc 'Create a impersonation token. Available only for admins.' do detail 'This feature was introduced in GitLab 9.0' @@ -667,7 +671,7 @@ module API optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the impersonation token' optional :scopes, type: Array, desc: 'The array of scopes of the impersonation token' end - post do + post feature_category: :authentication_and_authorization do impersonation_token = finder.build(declared_params(include_missing: false)) if impersonation_token.save @@ -684,7 +688,7 @@ module API params do requires :impersonation_token_id, type: Integer, desc: 'The ID of the impersonation token' end - get ':impersonation_token_id' do + get ':impersonation_token_id', feature_category: :authentication_and_authorization do present find_impersonation_token, with: Entities::ImpersonationToken end @@ -694,7 +698,7 @@ module API params do requires :impersonation_token_id, type: Integer, desc: 'The ID of the impersonation token' end - delete ':impersonation_token_id' do + delete ':impersonation_token_id', feature_category: :authentication_and_authorization do token = find_impersonation_token destroy_conditionally!(token) do @@ -702,6 +706,40 @@ module API end end end + + resource :personal_access_tokens do + helpers do + def target_user + find_user_by_id(params) + end + end + + before { authenticated_as_admin! } + + desc 'Create a personal access token. Available only for admins.' do + detail 'This feature was introduced in GitLab 13.6' + success Entities::PersonalAccessTokenWithToken + end + params do + requires :name, type: String, desc: 'The name of the personal access token' + requires :scopes, type: Array[String], coerce_with: ::API::Validations::Types::CommaSeparatedToArray.coerce, values: ::Gitlab::Auth.all_available_scopes.map(&:to_s), + desc: 'The array of scopes of the personal access token' + optional :expires_at, type: Date, desc: 'The expiration date in the format YEAR-MONTH-DAY of the personal access token' + end + post feature_category: :authentication_and_authorization do + not_found! unless Feature.enabled?(:pat_creation_api_for_admin) + + response = ::PersonalAccessTokens::CreateService.new( + current_user: current_user, target_user: target_user, params: declared_params(include_missing: false) + ).execute + + if response.success? + present response.payload[:personal_access_token], with: Entities::PersonalAccessTokenWithToken + else + render_api_error!(response.message, response.http_status || :unprocessable_entity) + end + end + end end end @@ -716,7 +754,7 @@ module API desc 'Get the currently authenticated user' do success Entities::UserPublic end - get do + get feature_category: :users do entity = if current_user.admin? Entities::UserWithAdmin @@ -734,7 +772,7 @@ module API params do use :pagination end - get "keys" do + get "keys", feature_category: :authentication_and_authorization do keys = current_user.keys.preload_users present paginate(keys), with: Entities::SSHKey @@ -747,7 +785,7 @@ module API requires :key_id, type: Integer, desc: 'The ID of the SSH key' end # rubocop: disable CodeReuse/ActiveRecord - get "keys/:key_id" do + get "keys/:key_id", feature_category: :authentication_and_authorization do key = current_user.keys.find_by(id: params[:key_id]) not_found!('Key') unless key @@ -763,7 +801,7 @@ module API requires :title, type: String, desc: 'The title of the new SSH key' optional :expires_at, type: DateTime, desc: 'The expiration date of the SSH key in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)' end - post "keys" do + post "keys", feature_category: :authentication_and_authorization do key = ::Keys::CreateService.new(current_user, declared_params(include_missing: false)).execute if key.persisted? @@ -780,7 +818,7 @@ module API requires :key_id, type: Integer, desc: 'The ID of the SSH key' end # rubocop: disable CodeReuse/ActiveRecord - delete "keys/:key_id" do + delete "keys/:key_id", feature_category: :authentication_and_authorization do key = current_user.keys.find_by(id: params[:key_id]) not_found!('Key') unless key @@ -798,7 +836,7 @@ module API params do use :pagination end - get 'gpg_keys' do + get 'gpg_keys', feature_category: :authentication_and_authorization do present paginate(current_user.gpg_keys), with: Entities::GpgKey end @@ -810,7 +848,7 @@ module API requires :key_id, type: Integer, desc: 'The ID of the GPG key' end # rubocop: disable CodeReuse/ActiveRecord - get 'gpg_keys/:key_id' do + get 'gpg_keys/:key_id', feature_category: :authentication_and_authorization do key = current_user.gpg_keys.find_by(id: params[:key_id]) not_found!('GPG Key') unless key @@ -825,7 +863,7 @@ module API params do requires :key, type: String, desc: 'The new GPG key' end - post 'gpg_keys' do + post 'gpg_keys', feature_category: :authentication_and_authorization do key = ::GpgKeys::CreateService.new(current_user, declared_params(include_missing: false)).execute if key.persisted? @@ -842,7 +880,7 @@ module API requires :key_id, type: Integer, desc: 'The ID of the GPG key' end # rubocop: disable CodeReuse/ActiveRecord - post 'gpg_keys/:key_id/revoke' do + post 'gpg_keys/:key_id/revoke', feature_category: :authentication_and_authorization do key = current_user.gpg_keys.find_by(id: params[:key_id]) not_found!('GPG Key') unless key @@ -858,7 +896,7 @@ module API requires :key_id, type: Integer, desc: 'The ID of the SSH key' end # rubocop: disable CodeReuse/ActiveRecord - delete 'gpg_keys/:key_id' do + delete 'gpg_keys/:key_id', feature_category: :authentication_and_authorization do key = current_user.gpg_keys.find_by(id: params[:key_id]) not_found!('GPG Key') unless key @@ -875,7 +913,7 @@ module API params do use :pagination end - get "emails" do + get "emails", feature_category: :users do present paginate(current_user.emails), with: Entities::Email end @@ -886,7 +924,7 @@ module API requires :email_id, type: Integer, desc: 'The ID of the email' end # rubocop: disable CodeReuse/ActiveRecord - get "emails/:email_id" do + get "emails/:email_id", feature_category: :users do email = current_user.emails.find_by(id: params[:email_id]) not_found!('Email') unless email @@ -900,7 +938,7 @@ module API params do requires :email, type: String, desc: 'The new email' end - post "emails" do + post "emails", feature_category: :users do email = Emails::CreateService.new(current_user, declared_params.merge(user: current_user)).execute if email.errors.blank? @@ -915,7 +953,7 @@ module API requires :email_id, type: Integer, desc: 'The ID of the email' end # rubocop: disable CodeReuse/ActiveRecord - delete "emails/:email_id" do + delete "emails/:email_id", feature_category: :users do email = current_user.emails.find_by(id: params[:email_id]) not_found!('Email') unless email @@ -931,7 +969,7 @@ module API use :pagination end # rubocop: disable CodeReuse/ActiveRecord - get "activities" do + get "activities", feature_category: :users do authenticated_as_admin! activities = User @@ -948,8 +986,9 @@ module API params do optional :emoji, type: String, desc: "The emoji to set on the status" optional :message, type: String, desc: "The status message to set" + optional :availability, type: String, desc: "The availability of user to set" end - put "status" do + put "status", feature_category: :users do forbidden! unless can?(current_user, :update_user_status, current_user) if ::Users::SetStatusService.new(current_user, declared_params).execute @@ -962,7 +1001,7 @@ module API desc 'get the status of the current user' do success Entities::UserStatus end - get 'status' do + get 'status', feature_category: :users do present current_user.status || {}, with: Entities::UserStatus end end |