diff options
Diffstat (limited to 'app/controllers/projects/feature_flags_controller.rb')
-rw-r--r-- | app/controllers/projects/feature_flags_controller.rb | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/app/controllers/projects/feature_flags_controller.rb b/app/controllers/projects/feature_flags_controller.rb new file mode 100644 index 00000000000..e9d450a6ce3 --- /dev/null +++ b/app/controllers/projects/feature_flags_controller.rb @@ -0,0 +1,174 @@ +# frozen_string_literal: true + +class Projects::FeatureFlagsController < Projects::ApplicationController + respond_to :html + + before_action :authorize_read_feature_flag! + before_action :authorize_create_feature_flag!, only: [:new, :create] + before_action :authorize_update_feature_flag!, only: [:edit, :update] + before_action :authorize_destroy_feature_flag!, only: [:destroy] + + before_action :feature_flag, only: [:edit, :update, :destroy] + + before_action :ensure_legacy_flags_writable!, only: [:update] + + before_action do + push_frontend_feature_flag(:feature_flag_permissions) + push_frontend_feature_flag(:feature_flags_new_version, project, default_enabled: true) + push_frontend_feature_flag(:feature_flags_legacy_read_only, project, default_enabled: true) + push_frontend_feature_flag(:feature_flags_legacy_read_only_override, project) + end + + feature_category :feature_flags + + def index + @feature_flags = FeatureFlagsFinder + .new(project, current_user, scope: params[:scope]) + .execute + .page(params[:page]) + .per(30) + + respond_to do |format| + format.html + format.json do + Gitlab::PollingInterval.set_header(response, interval: 10_000) + + render json: { feature_flags: feature_flags_json }.merge(summary_json) + end + end + end + + def new + end + + def show + respond_to do |format| + format.json do + Gitlab::PollingInterval.set_header(response, interval: 10_000) + + render_success_json(feature_flag) + end + end + end + + def create + result = FeatureFlags::CreateService.new(project, current_user, create_params).execute + + if result[:status] == :success + respond_to do |format| + format.json { render_success_json(result[:feature_flag]) } + end + else + respond_to do |format| + format.json { render_error_json(result[:message]) } + end + end + end + + def edit + end + + def update + result = FeatureFlags::UpdateService.new(project, current_user, update_params).execute(feature_flag) + + if result[:status] == :success + respond_to do |format| + format.json { render_success_json(result[:feature_flag]) } + end + else + respond_to do |format| + format.json { render_error_json(result[:message]) } + end + end + end + + def destroy + result = FeatureFlags::DestroyService.new(project, current_user).execute(feature_flag) + + if result[:status] == :success + respond_to do |format| + format.html { redirect_to_index(notice: _('Feature flag was successfully removed.')) } + format.json { render_success_json(feature_flag) } + end + else + respond_to do |format| + format.html { redirect_to_index(alert: _('Feature flag was not removed.')) } + format.json { render_error_json(result[:message]) } + end + end + end + + protected + + def feature_flag + @feature_flag ||= @noteable = if new_version_feature_flags_enabled? + project.operations_feature_flags.find_by_iid!(params[:iid]) + else + project.operations_feature_flags.legacy_flag.find_by_iid!(params[:iid]) + end + end + + def new_version_feature_flags_enabled? + ::Feature.enabled?(:feature_flags_new_version, project, default_enabled: true) + end + + def ensure_legacy_flags_writable! + if ::Feature.enabled?(:feature_flags_legacy_read_only, project, default_enabled: true) && + ::Feature.disabled?(:feature_flags_legacy_read_only_override, project) && + feature_flag.legacy_flag? + render_error_json(['Legacy feature flags are read-only']) + end + end + + def create_params + params.require(:operations_feature_flag) + .permit(:name, :description, :active, :version, + scopes_attributes: [:environment_scope, :active, + strategies: [:name, parameters: [:groupId, :percentage, :userIds]]], + strategies_attributes: [:name, :user_list_id, + parameters: [:groupId, :percentage, :userIds, :rollout, :stickiness], + scopes_attributes: [:environment_scope]]) + end + + def update_params + params.require(:operations_feature_flag) + .permit(:name, :description, :active, + scopes_attributes: [:id, :environment_scope, :active, :_destroy, + strategies: [:name, parameters: [:groupId, :percentage, :userIds]]], + strategies_attributes: [:id, :name, :user_list_id, :_destroy, + parameters: [:groupId, :percentage, :userIds, :rollout, :stickiness], + scopes_attributes: [:id, :environment_scope, :_destroy]]) + end + + def feature_flag_json(feature_flag) + FeatureFlagSerializer + .new(project: @project, current_user: @current_user) + .represent(feature_flag) + end + + def feature_flags_json + FeatureFlagSerializer + .new(project: @project, current_user: @current_user) + .with_pagination(request, response) + .represent(@feature_flags) + end + + def summary_json + FeatureFlagSummarySerializer + .new(project: @project, current_user: @current_user) + .represent(@project) + end + + def redirect_to_index(**args) + redirect_to project_feature_flags_path(@project), status: :found, **args + end + + def render_success_json(feature_flag) + render json: feature_flag_json(feature_flag), status: :ok + end + + def render_error_json(messages) + render json: { message: messages }, + status: :bad_request + end +end |