Commit 3c342953 authored by Qingyu Zhao's avatar Qingyu Zhao Committed by James Lopez

Add API to set credit card validation timestamp on user in GitLab

parent 9b466bb0
# frozen_string_literal: true
module Users
class UpsertCreditCardValidationService < BaseService
def initialize(params)
@params = params.to_h.with_indifferent_access
end
def execute
::Users::CreditCardValidation.upsert(@params)
ServiceResponse.success(message: 'CreditCardValidation was set')
rescue ActiveRecord::InvalidForeignKey, ActiveRecord::NotNullViolation => e
ServiceResponse.error(message: "Could not set CreditCardValidation: #{e.message}")
rescue StandardError => e
Gitlab::ErrorTracking.track_exception(e, params: @params, class: self.class.to_s)
ServiceResponse.error(message: "Could not set CreditCardValidation: #{e.message}")
end
end
end
---
title: Add API to set credit card validation timestamp for user
merge_request: 60828
author:
type: added
# frozen_string_literal: true
module API
module Entities
class UserCreditCardValidations < Grape::Entity
expose :user_id, :credit_card_validated_at
end
end
end
......@@ -996,6 +996,30 @@ module API
present paginate(current_user.emails), with: Entities::Email
end
desc "Update a user's credit_card_validation" do
success Entities::UserCreditCardValidations
end
params do
requires :user_id, type: String, desc: 'The ID or username of the user'
requires :credit_card_validated_at, type: DateTime, desc: 'The time when the user\'s credit card was validated'
end
put ":user_id/credit_card_validation", feature_category: :users do
authenticated_as_admin!
user = find_user(params[:user_id])
not_found!('User') unless user
attrs = declared_params(include_missing: false)
service = ::Users::UpsertCreditCardValidationService.new(attrs).execute
if service.success?
present user.credit_card_validation, with: Entities::UserCreditCardValidations
else
render_api_error!('400 Bad Request', 400)
end
end
desc "Update the current user's preferences" do
success Entities::UserPreferences
detail 'This feature was introduced in GitLab 13.10.'
......
......@@ -1449,6 +1449,48 @@ RSpec.describe API::Users do
end
end
describe "PUT /user/:id/credit_card_validation" do
let(:credit_card_validated_time) { Time.utc(2020, 1, 1) }
context 'when unauthenticated' do
it 'returns authentication error' do
put api("/user/#{user.id}/credit_card_validation"), params: { credit_card_validated_at: credit_card_validated_time }
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
context 'when authenticated as non-admin' do
it "does not allow updating user's credit card validation", :aggregate_failures do
put api("/user/#{user.id}/credit_card_validation", user), params: { credit_card_validated_at: credit_card_validated_time }
expect(response).to have_gitlab_http_status(:forbidden)
end
end
context 'when authenticated as admin' do
it "updates user's credit card validation", :aggregate_failures do
put api("/user/#{user.id}/credit_card_validation", admin), params: { credit_card_validated_at: credit_card_validated_time }
expect(response).to have_gitlab_http_status(:ok)
expect(user.reload.credit_card_validated_at).to eq(credit_card_validated_time)
end
it "returns 400 error if credit_card_validated_at is missing" do
put api("/user/#{user.id}/credit_card_validation", admin), params: {}
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'returns 404 error if user not found' do
put api("/user/#{non_existing_record_id}/credit_card_validation", admin), params: { credit_card_validated_at: credit_card_validated_time }
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message']).to eq('404 User Not Found')
end
end
end
describe "DELETE /users/:id/identities/:provider" do
let(:test_user) { create(:omniauth_user, provider: 'ldapmain') }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Users::UpsertCreditCardValidationService do
let_it_be(:user) { create(:user) }
let(:user_id) { user.id }
let(:credit_card_validated_time) { Time.utc(2020, 1, 1) }
let(:params) { { user_id: user_id, credit_card_validated_at: credit_card_validated_time } }
describe '#execute' do
subject(:service) { described_class.new(params) }
context 'successfully set credit card validation record for the user' do
context 'when user does not have credit card validation record' do
it 'creates the credit card validation and returns a success' do
expect(user.credit_card_validated_at).to be nil
result = service.execute
expect(result.status).to eq(:success)
expect(user.reload.credit_card_validated_at).to eq(credit_card_validated_time)
end
end
context 'when user has credit card validation record' do
let(:old_time) { Time.utc(1999, 2, 2) }
before do
create(:credit_card_validation, user: user, credit_card_validated_at: old_time)
end
it 'updates the credit card validation and returns a success' do
expect(user.credit_card_validated_at).to eq(old_time)
result = service.execute
expect(result.status).to eq(:success)
expect(user.reload.credit_card_validated_at).to eq(credit_card_validated_time)
end
end
end
shared_examples 'returns an error without tracking the exception' do
it do
expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
result = service.execute
expect(result.status).to eq(:error)
end
end
context 'when user id does not exist' do
let(:user_id) { non_existing_record_id }
it_behaves_like 'returns an error without tracking the exception'
end
context 'when missing credit_card_validated_at' do
let(:params) { { user_id: user_id } }
it_behaves_like 'returns an error without tracking the exception'
end
context 'when missing user id' do
let(:params) { { credit_card_validated_at: credit_card_validated_time } }
it_behaves_like 'returns an error without tracking the exception'
end
context 'when unexpected exception happen' do
it 'tracks the exception and returns an error' do
expect(::Users::CreditCardValidation).to receive(:upsert).and_raise(e = StandardError.new('My exception!'))
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(e, class: described_class.to_s, params: params)
result = service.execute
expect(result.status).to eq(:error)
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment