2021-01-03 14:25:43 +05:30
# frozen_string_literal: true
module API
class FeatureFlags < :: API :: Base
include PaginationParams
2023-01-13 00:05:48 +05:30
feature_flags_tags = %w[ feature_flags ]
2021-01-03 14:25:43 +05:30
FEATURE_FLAG_ENDPOINT_REQUIREMENTS = API :: NAMESPACE_OR_PROJECT_REQUIREMENTS
. merge ( name : API :: NO_SLASH_URL_PART_REGEX )
2021-01-29 00:20:46 +05:30
feature_category :feature_flags
2022-07-16 23:28:13 +05:30
urgency :low
2021-01-29 00:20:46 +05:30
2021-01-03 14:25:43 +05:30
before do
authorize_read_feature_flags!
end
params do
2023-01-13 00:05:48 +05:30
requires :id , types : [ String , Integer ] , desc : 'The ID or URL-encoded path of the project'
2021-01-03 14:25:43 +05:30
end
resource 'projects/:id' , requirements : API :: NAMESPACE_OR_PROJECT_REQUIREMENTS do
resource :feature_flags do
2023-01-13 00:05:48 +05:30
desc 'List feature flags for a project' do
detail 'Gets all feature flags of the requested project. This feature was introduced in GitLab 12.5.'
2021-01-03 14:25:43 +05:30
success :: API :: Entities :: FeatureFlag
2023-01-13 00:05:48 +05:30
failure [
{ code : 401 , message : 'Unauthorized' } ,
{ code : 404 , message : 'Not found' }
]
is_array true
tags feature_flags_tags
2021-01-03 14:25:43 +05:30
end
params do
2022-08-27 11:52:29 +05:30
optional :scope ,
type : String ,
2023-01-13 00:05:48 +05:30
desc : 'The scope of feature flags, one of: `enabled`, `disabled`' ,
2022-08-27 11:52:29 +05:30
values : %w[ enabled disabled ]
2021-01-03 14:25:43 +05:30
use :pagination
end
get do
feature_flags = :: FeatureFlagsFinder
. new ( user_project , current_user , declared_params ( include_missing : false ) )
. execute
present_entity ( paginate ( feature_flags ) )
end
desc 'Create a new feature flag' do
2023-01-13 00:05:48 +05:30
detail 'Creates a new feature flag. This feature was introduced in GitLab 12.5.'
2021-01-03 14:25:43 +05:30
success :: API :: Entities :: FeatureFlag
2023-01-13 00:05:48 +05:30
failure [
{ code : 400 , message : 'Bad request' } ,
{ code : 401 , message : 'Unauthorized' } ,
{ code : 403 , message : 'Forbidden' }
]
tags feature_flags_tags
2021-01-03 14:25:43 +05:30
end
params do
2023-01-13 00:05:48 +05:30
requires :name , type : String , desc : 'The name of the feature flag'
2021-01-03 14:25:43 +05:30
optional :description , type : String , desc : 'The description of the feature flag'
2023-01-13 00:05:48 +05:30
optional :active , type : Boolean , desc : 'The active state of the flag. Defaults to `true`. Supported in GitLab 13.3 and later'
optional :version , type : String , desc : 'The version of the feature flag. Must be `new_version_flag`. Omit to create a Legacy feature flag.'
2021-01-03 14:25:43 +05:30
optional :strategies , type : Array do
2023-01-13 00:05:48 +05:30
requires :name , type : String , desc : 'The strategy name. Can be `default`, `gradualRolloutUserId`, `userWithId`, or `gitlabUserList`. In GitLab 13.5 and later, can be `flexibleRollout`'
requires :parameters , type : JSON , desc : 'The strategy parameters as a JSON-formatted string e.g. `{"userIds":"user1"}`' , documentation : { type : 'String' }
2021-01-03 14:25:43 +05:30
optional :scopes , type : Array do
requires :environment_scope , type : String , desc : 'The environment scope of the scope'
end
end
end
post do
authorize_create_feature_flag!
attrs = declared_params ( include_missing : false )
rename_key ( attrs , :scopes , :scopes_attributes )
rename_key ( attrs , :strategies , :strategies_attributes )
update_value ( attrs , :strategies_attributes ) do | strategies |
strategies . map { | s | rename_key ( s , :scopes , :scopes_attributes ) }
end
result = :: FeatureFlags :: CreateService
. new ( user_project , current_user , attrs )
. execute
if result [ :status ] == :success
present_entity ( result [ :feature_flag ] )
else
render_api_error! ( result [ :message ] , result [ :http_status ] )
end
end
end
params do
requires :feature_flag_name , type : String , desc : 'The name of the feature flag'
end
resource 'feature_flags/:feature_flag_name' , requirements : FEATURE_FLAG_ENDPOINT_REQUIREMENTS do
2023-01-13 00:05:48 +05:30
desc 'Get a single feature flag' do
detail 'Gets a single feature flag. This feature was introduced in GitLab 12.5.'
2021-01-03 14:25:43 +05:30
success :: API :: Entities :: FeatureFlag
2023-01-13 00:05:48 +05:30
failure [
{ code : 401 , message : 'Unauthorized' } ,
{ code : 404 , message : 'Not found' }
]
tags feature_flags_tags
2021-01-03 14:25:43 +05:30
end
get do
authorize_read_feature_flag!
2021-09-04 01:27:46 +05:30
exclude_legacy_flags_check!
2021-01-03 14:25:43 +05:30
present_entity ( feature_flag )
end
desc 'Update a feature flag' do
2023-01-13 00:05:48 +05:30
detail 'Updates a feature flag. This feature was introduced in GitLab 13.2.'
2021-01-03 14:25:43 +05:30
success :: API :: Entities :: FeatureFlag
2023-01-13 00:05:48 +05:30
failure [
{ code : 401 , message : 'Unauthorized' } ,
{ code : 403 , message : 'Forbidden' } ,
{ code : 404 , message : 'Not found' } ,
{ code : 422 , message : 'Unprocessable entity' }
]
tags feature_flags_tags
2021-01-03 14:25:43 +05:30
end
params do
2023-01-13 00:05:48 +05:30
optional :name , type : String , desc : 'The new name of the feature flag. Supported in GitLab 13.3 and later'
2021-01-03 14:25:43 +05:30
optional :description , type : String , desc : 'The description of the feature flag'
2023-01-13 00:05:48 +05:30
optional :active , type : Boolean , desc : 'The active state of the flag. Supported in GitLab 13.3 and later'
2021-01-03 14:25:43 +05:30
optional :strategies , type : Array do
2023-01-13 00:05:48 +05:30
optional :id , type : Integer , desc : 'The feature flag strategy ID'
optional :name , type : String , desc : 'The strategy name'
optional :parameters , type : JSON , desc : 'The strategy parameters as a JSON-formatted string e.g. `{"userIds":"user1"}`' , documentation : { type : 'String' }
2021-01-03 14:25:43 +05:30
optional :_destroy , type : Boolean , desc : 'Delete the strategy when true'
optional :scopes , type : Array do
2023-01-13 00:05:48 +05:30
optional :id , type : Integer , desc : 'The scope id'
2021-01-03 14:25:43 +05:30
optional :environment_scope , type : String , desc : 'The environment scope of the scope'
optional :_destroy , type : Boolean , desc : 'Delete the scope when true'
end
end
end
put do
authorize_update_feature_flag!
2021-09-04 01:27:46 +05:30
exclude_legacy_flags_check!
2021-11-11 11:23:49 +05:30
render_api_error! ( 'PUT operations are not supported for legacy feature flags' , :unprocessable_entity ) unless feature_flag . new_version_flag?
2021-01-03 14:25:43 +05:30
attrs = declared_params ( include_missing : false )
rename_key ( attrs , :strategies , :strategies_attributes )
update_value ( attrs , :strategies_attributes ) do | strategies |
strategies . map { | s | rename_key ( s , :scopes , :scopes_attributes ) }
end
result = :: FeatureFlags :: UpdateService
. new ( user_project , current_user , attrs )
. execute ( feature_flag )
if result [ :status ] == :success
present_entity ( result [ :feature_flag ] )
else
render_api_error! ( result [ :message ] , result [ :http_status ] )
end
end
desc 'Delete a feature flag' do
2023-01-13 00:05:48 +05:30
detail 'Deletes a feature flag. This feature was introduced in GitLab 12.5.'
2021-01-03 14:25:43 +05:30
success :: API :: Entities :: FeatureFlag
2023-01-13 00:05:48 +05:30
failure [
{ code : 401 , message : 'Unauthorized' } ,
{ code : 403 , message : 'Forbidden' } ,
{ code : 404 , message : 'Not found' }
]
tags feature_flags_tags
2021-01-03 14:25:43 +05:30
end
delete do
authorize_destroy_feature_flag!
result = :: FeatureFlags :: DestroyService
. new ( user_project , current_user , declared_params ( include_missing : false ) )
. execute ( feature_flag )
if result [ :status ] == :success
present_entity ( result [ :feature_flag ] )
else
render_api_error! ( result [ :message ] , result [ :http_status ] )
end
end
end
end
helpers do
def authorize_read_feature_flags!
authorize! :read_feature_flag , user_project
end
def authorize_read_feature_flag!
authorize! :read_feature_flag , feature_flag
end
def authorize_create_feature_flag!
authorize! :create_feature_flag , user_project
end
def authorize_update_feature_flag!
authorize! :update_feature_flag , feature_flag
end
def authorize_destroy_feature_flag!
authorize! :destroy_feature_flag , feature_flag
end
def present_entity ( result )
present result ,
2021-02-22 17:27:13 +05:30
with : :: API :: Entities :: FeatureFlag
2021-01-03 14:25:43 +05:30
end
def feature_flag
2021-02-22 17:27:13 +05:30
@feature_flag || = user_project . operations_feature_flags . find_by_name! ( params [ :feature_flag_name ] )
2021-01-03 14:25:43 +05:30
end
2021-09-04 01:27:46 +05:30
def project
@project || = feature_flag . project
end
2021-01-03 14:25:43 +05:30
def new_version_flag_present?
user_project . operations_feature_flags . new_version_flag . find_by_name ( params [ :name ] ) . present?
end
def rename_key ( hash , old_key , new_key )
hash [ new_key ] = hash . delete ( old_key ) if hash . key? ( old_key )
hash
end
def update_value ( hash , key )
hash [ key ] = yield ( hash [ key ] ) if hash . key? ( key )
hash
end
2021-09-04 01:27:46 +05:30
def exclude_legacy_flags_check!
2021-11-11 11:23:49 +05:30
unless feature_flag . new_version_flag?
2021-09-04 01:27:46 +05:30
not_found!
end
end
2021-01-03 14:25:43 +05:30
end
end
end