Loading config/routes/project.rb +4 −0 Original line number Diff line number Diff line Loading @@ -519,6 +519,10 @@ # its preferable to keep it below all other project routes draw :wiki draw :repository ## EE-specific resources :managed_licenses, only: [:index, :show, :new, :create, :edit, :update, :destroy] ## EE-specific end resources(:projects, Loading db/schema.rb +16 −0 Original line number Diff line number Diff line Loading @@ -2463,6 +2463,20 @@ add_index "snippets", ["updated_at"], name: "index_snippets_on_updated_at", using: :btree add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree create_table "software_license_policies", force: :cascade do |t| t.integer "project_id", null: false t.integer "software_license_id", null: false t.integer "approval_status", default: 0, null: false end add_index "software_license_policies", ["project_id", "software_license_id"], name: "index_software_license_policies_unique_per_project", unique: true, using: :btree create_table "software_licenses", force: :cascade do |t| t.string "name", null: false end add_index "software_licenses", ["name"], name: "index_software_licenses_on_name", using: :btree create_table "spam_logs", force: :cascade do |t| t.integer "user_id" t.string "source_ip" Loading Loading @@ -3021,6 +3035,8 @@ add_foreign_key "services", "projects", name: "fk_71cce407f9", on_delete: :cascade add_foreign_key "slack_integrations", "services", on_delete: :cascade add_foreign_key "snippets", "projects", name: "fk_be41fd4bb7", on_delete: :cascade add_foreign_key "software_license_policies", "projects", on_delete: :cascade add_foreign_key "software_license_policies", "software_licenses", on_delete: :cascade add_foreign_key "subscriptions", "projects", on_delete: :cascade add_foreign_key "system_note_metadata", "notes", name: "fk_d83a918cb1", on_delete: :cascade add_foreign_key "term_agreements", "application_setting_terms", column: "term_id" Loading doc/api/README.md +1 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ following locations: - [Keys](keys.md) - [Labels](labels.md) - [License](license.md) - [Managed licenses](managed_licenses.md) **[ULTIMATE]** - [Markdown](markdown.md) - [Merge Requests](merge_requests.md) - [Merge Request Approvals](merge_request_approvals.md) **[STARTER]** Loading doc/api/managed_licenses.md 0 → 100644 +136 −0 Original line number Diff line number Diff line # Managed Licenses API **[ULTIMATE]** ## List managed licenses Get all managed licenses for a given project. ``` GET /projects/:id/managed_licenses ``` | Attribute | Type | Required | Description | | --------- | ------- | -------- | --------------------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | ```bash curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/managed_licenses ``` Example response: ```json [ { "id": 1, "name": "MIT", "approval_status": "approved" }, { "id": 3, "name": "ISC", "approval_status": "blacklisted" } ] ``` ## Show an existing managed license Shows an existing managed license. ``` GET /projects/:id/managed_licenses/:managed_license_id ``` | Attribute | Type | Required | Description | | --------------- | ------- | --------------------------------- | ------------------------------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project | ```bash curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6" ``` Example response: ```json { "id": 1, "name": "MIT", "approval_status": "blacklisted" } ``` ## Create a new managed license Creates a new managed license for the given project with the given name and approval status. ``` POST /projects/:id/managed_licenses ``` | Attribute | Type | Required | Description | | ------------- | ------- | -------- | ---------------------------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `name` | string | yes | The name of the managed license | | `approval_status` | string | yes | The approval status. "approved" or "blacklisted" | ```bash curl --data "name=MIT&approval_status=blacklisted" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/managed_licenses" ``` Example response: ```json { "id": 1, "name": "MIT", "approval_status": "approved" } ``` ## Delete a managed license Deletes a managed license with a given id. ``` DELETE /projects/:id/managed_licenses/:managed_license_id ``` | Attribute | Type | Required | Description | | --------- | ------- | -------- | --------------------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project | ```bash curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/4" ``` When successful, it replies with an HTTP 204 response. ## Edit an existing managed license Updates an existing managed license with a new approval status. ``` PATCH /projects/:id/managed_licenses/:managed_license_id ``` | Attribute | Type | Required | Description | | --------------- | ------- | --------------------------------- | ------------------------------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project | | `approval_status` | string | yes | The approval status. "approved" or "blacklisted" | ```bash curl --request PATCH --data "approval_status=blacklisted" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6" ``` Example response: ```json { "id": 1, "name": "MIT", "approval_status": "blacklisted" } ``` ee/app/controllers/projects/managed_licenses_controller.rb 0 → 100644 +124 −0 Original line number Diff line number Diff line # frozen_string_literal: true class Projects::ManagedLicensesController < Projects::ApplicationController before_action :software_license_policy, only: [:show, :edit, :update, :destroy] before_action :authorize_can_read!, only: [:index, :show] before_action :authorize_can_admin!, only: [:new, :create, :edit, :update, :destroy] def index respond_to do |format| format.json do render_software_license_policies end end end def show respond_to do |format| format.json do render_software_license_policy end end end def new @software_license_policy = @project.software_license_policies.new end def create result = SoftwareLicensePolicies::CreateService.new( @project, current_user, software_license_policies_params ).execute if result[:status] == :success @software_license_policy = result[:software_license_policy] respond_to do |format| format.json { render_software_license_policy } end else respond_to do |format| format.json { render_error(result[:message], 400) } end end end def edit end def update result = SoftwareLicensePolicies::UpdateService.new( @project, current_user, software_license_policies_params ).execute(@software_license_policy) if result[:status] == :success respond_to do |format| format.json { render_software_license_policy } end else respond_to do |format| format.json { render_error(result[:message], 400) } end end end def destroy @software_license_policy.destroy! respond_to do |format| format.json { render_ok } end end private def respond_400 head :bad_request end # Fetch the existing software license policy when given an id or name def software_license_policy id = params[:id] id = CGI.unescape(id) unless id.is_a?(Integer) || id =~ /^\d+$/ @software_license_policy ||= SoftwareLicensePoliciesFinder.new(current_user, project).find_by_name_or_id(id) if @software_license_policy.nil? # The license was not found render_404 end end def render_ok render status: :ok, nothing: true end def render_software_license_policy render status: :ok, json: ManagedLicenseSerializer.new.represent(@software_license_policy) end def render_software_license_policies render status: :ok, json: { software_license_policies: ManagedLicenseSerializer.new.represent(@project.software_license_policies) } end def render_error(error, status = 400) render json: error, status: status end def software_license_policies_params # Require the presence of an hash containing the software license policy fields params.require(:managed_license).permit(:name, :approval_status) end def authorize_can_read! render_404 unless can?(current_user, :read_software_license_policy, @project) end def authorize_can_admin! authorize_can_read! render_403 unless can?(current_user, :admin_software_license_policy, @project) end end Loading
config/routes/project.rb +4 −0 Original line number Diff line number Diff line Loading @@ -519,6 +519,10 @@ # its preferable to keep it below all other project routes draw :wiki draw :repository ## EE-specific resources :managed_licenses, only: [:index, :show, :new, :create, :edit, :update, :destroy] ## EE-specific end resources(:projects, Loading
db/schema.rb +16 −0 Original line number Diff line number Diff line Loading @@ -2463,6 +2463,20 @@ add_index "snippets", ["updated_at"], name: "index_snippets_on_updated_at", using: :btree add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree create_table "software_license_policies", force: :cascade do |t| t.integer "project_id", null: false t.integer "software_license_id", null: false t.integer "approval_status", default: 0, null: false end add_index "software_license_policies", ["project_id", "software_license_id"], name: "index_software_license_policies_unique_per_project", unique: true, using: :btree create_table "software_licenses", force: :cascade do |t| t.string "name", null: false end add_index "software_licenses", ["name"], name: "index_software_licenses_on_name", using: :btree create_table "spam_logs", force: :cascade do |t| t.integer "user_id" t.string "source_ip" Loading Loading @@ -3021,6 +3035,8 @@ add_foreign_key "services", "projects", name: "fk_71cce407f9", on_delete: :cascade add_foreign_key "slack_integrations", "services", on_delete: :cascade add_foreign_key "snippets", "projects", name: "fk_be41fd4bb7", on_delete: :cascade add_foreign_key "software_license_policies", "projects", on_delete: :cascade add_foreign_key "software_license_policies", "software_licenses", on_delete: :cascade add_foreign_key "subscriptions", "projects", on_delete: :cascade add_foreign_key "system_note_metadata", "notes", name: "fk_d83a918cb1", on_delete: :cascade add_foreign_key "term_agreements", "application_setting_terms", column: "term_id" Loading
doc/api/README.md +1 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ following locations: - [Keys](keys.md) - [Labels](labels.md) - [License](license.md) - [Managed licenses](managed_licenses.md) **[ULTIMATE]** - [Markdown](markdown.md) - [Merge Requests](merge_requests.md) - [Merge Request Approvals](merge_request_approvals.md) **[STARTER]** Loading
doc/api/managed_licenses.md 0 → 100644 +136 −0 Original line number Diff line number Diff line # Managed Licenses API **[ULTIMATE]** ## List managed licenses Get all managed licenses for a given project. ``` GET /projects/:id/managed_licenses ``` | Attribute | Type | Required | Description | | --------- | ------- | -------- | --------------------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | ```bash curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/managed_licenses ``` Example response: ```json [ { "id": 1, "name": "MIT", "approval_status": "approved" }, { "id": 3, "name": "ISC", "approval_status": "blacklisted" } ] ``` ## Show an existing managed license Shows an existing managed license. ``` GET /projects/:id/managed_licenses/:managed_license_id ``` | Attribute | Type | Required | Description | | --------------- | ------- | --------------------------------- | ------------------------------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project | ```bash curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6" ``` Example response: ```json { "id": 1, "name": "MIT", "approval_status": "blacklisted" } ``` ## Create a new managed license Creates a new managed license for the given project with the given name and approval status. ``` POST /projects/:id/managed_licenses ``` | Attribute | Type | Required | Description | | ------------- | ------- | -------- | ---------------------------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `name` | string | yes | The name of the managed license | | `approval_status` | string | yes | The approval status. "approved" or "blacklisted" | ```bash curl --data "name=MIT&approval_status=blacklisted" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/managed_licenses" ``` Example response: ```json { "id": 1, "name": "MIT", "approval_status": "approved" } ``` ## Delete a managed license Deletes a managed license with a given id. ``` DELETE /projects/:id/managed_licenses/:managed_license_id ``` | Attribute | Type | Required | Description | | --------- | ------- | -------- | --------------------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project | ```bash curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/4" ``` When successful, it replies with an HTTP 204 response. ## Edit an existing managed license Updates an existing managed license with a new approval status. ``` PATCH /projects/:id/managed_licenses/:managed_license_id ``` | Attribute | Type | Required | Description | | --------------- | ------- | --------------------------------- | ------------------------------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project | | `approval_status` | string | yes | The approval status. "approved" or "blacklisted" | ```bash curl --request PATCH --data "approval_status=blacklisted" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6" ``` Example response: ```json { "id": 1, "name": "MIT", "approval_status": "blacklisted" } ```
ee/app/controllers/projects/managed_licenses_controller.rb 0 → 100644 +124 −0 Original line number Diff line number Diff line # frozen_string_literal: true class Projects::ManagedLicensesController < Projects::ApplicationController before_action :software_license_policy, only: [:show, :edit, :update, :destroy] before_action :authorize_can_read!, only: [:index, :show] before_action :authorize_can_admin!, only: [:new, :create, :edit, :update, :destroy] def index respond_to do |format| format.json do render_software_license_policies end end end def show respond_to do |format| format.json do render_software_license_policy end end end def new @software_license_policy = @project.software_license_policies.new end def create result = SoftwareLicensePolicies::CreateService.new( @project, current_user, software_license_policies_params ).execute if result[:status] == :success @software_license_policy = result[:software_license_policy] respond_to do |format| format.json { render_software_license_policy } end else respond_to do |format| format.json { render_error(result[:message], 400) } end end end def edit end def update result = SoftwareLicensePolicies::UpdateService.new( @project, current_user, software_license_policies_params ).execute(@software_license_policy) if result[:status] == :success respond_to do |format| format.json { render_software_license_policy } end else respond_to do |format| format.json { render_error(result[:message], 400) } end end end def destroy @software_license_policy.destroy! respond_to do |format| format.json { render_ok } end end private def respond_400 head :bad_request end # Fetch the existing software license policy when given an id or name def software_license_policy id = params[:id] id = CGI.unescape(id) unless id.is_a?(Integer) || id =~ /^\d+$/ @software_license_policy ||= SoftwareLicensePoliciesFinder.new(current_user, project).find_by_name_or_id(id) if @software_license_policy.nil? # The license was not found render_404 end end def render_ok render status: :ok, nothing: true end def render_software_license_policy render status: :ok, json: ManagedLicenseSerializer.new.represent(@software_license_policy) end def render_software_license_policies render status: :ok, json: { software_license_policies: ManagedLicenseSerializer.new.represent(@project.software_license_policies) } end def render_error(error, status = 400) render json: error, status: status end def software_license_policies_params # Require the presence of an hash containing the software license policy fields params.require(:managed_license).permit(:name, :approval_status) end def authorize_can_read! render_404 unless can?(current_user, :read_software_license_policy, @project) end def authorize_can_admin! authorize_can_read! render_403 unless can?(current_user, :admin_software_license_policy, @project) end end