Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ private void loadToConfigsInMemForSw360(ConfigContainer configContainer) {
.put(IS_BULK_RELEASE_DELETING_ENABLED, getOrDefault(configContainer, IS_BULK_RELEASE_DELETING_ENABLED, "false"))
.put(DISABLE_CLEARING_FOSSOLOGY_REPORT_DOWNLOAD, getOrDefault(configContainer, DISABLE_CLEARING_FOSSOLOGY_REPORT_DOWNLOAD, "false"))
.put(IS_FORCE_UPDATE_ENABLED, getOrDefault(configContainer, IS_FORCE_UPDATE_ENABLED, "false"))
.put(LICENSE_MANUAL_CREATION_ENABLED, getOrDefault(configContainer, LICENSE_MANUAL_CREATION_ENABLED, "false"))
.put(SBOM_IMPORT_EXPORT_ACCESS_USER_ROLE, getOrDefault(configContainer, SBOM_IMPORT_EXPORT_ACCESS_USER_ROLE, UserGroup.USER.name()))
.put(TOOL_NAME, getOrDefault(configContainer, TOOL_NAME, SW360Constants.DEFAULT_SBOM_TOOL_NAME))
.put(TOOL_VENDOR, getOrDefault(configContainer, TOOL_VENDOR, SW360Constants.DEFAULT_SBOM_TOOL_VENDOR))
Expand Down Expand Up @@ -197,6 +198,7 @@ private boolean isConfigValid(String configKey, String configValue) {
MAIL_REQUEST_FOR_PROJECT_REPORT,
MAIL_REQUEST_FOR_COMPONENT_REPORT,
IS_FORCE_UPDATE_ENABLED,
LICENSE_MANUAL_CREATION_ENABLED,
DISABLE_CLEARING_FOSSOLOGY_REPORT_DOWNLOAD,
IS_BULK_RELEASE_DELETING_ENABLED,
IS_PACKAGE_PORTLET_ENABLED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ public class SW360ConfigKeys {
// This property enable force update feature
public static final String IS_FORCE_UPDATE_ENABLED = "rest.force.update.enabled";

// This property is used to enable manual license creation
public static final String LICENSE_MANUAL_CREATION_ENABLED = "license.manual.creation.enabled";

// This property is used to control the user role for SBOM import and export
public static final String SBOM_IMPORT_EXPORT_ACCESS_USER_ROLE = "sbom.import.export.access.usergroup";

Expand Down Expand Up @@ -131,6 +134,7 @@ public class SW360ConfigKeys {
SKIP_DOMAINS_FOR_VALID_SOURCE_CODE,
ATTACHMENT_STORE_FILE_SYSTEM_LOCATION,
IS_FORCE_UPDATE_ENABLED,
LICENSE_MANUAL_CREATION_ENABLED,
AUTO_SET_ECC_STATUS,
IS_ADMIN_PRIVATE_ACCESS_ENABLED,
DISABLE_CLEARING_FOSSOLOGY_REPORT_DOWNLOAD,
Expand All @@ -146,7 +150,8 @@ public class SW360ConfigKeys {
ATTACHMENT_DELETE_NO_OF_DAYS, ATTACHMENT_STORE_FILE_SYSTEM_LOCATION,
COMBINED_CLI_PARSER_EXTERNAL_ID_CORRELATION_KEY, AUTO_SET_ECC_STATUS, MAIL_REQUEST_FOR_PROJECT_REPORT,
MAIL_REQUEST_FOR_COMPONENT_REPORT, IS_BULK_RELEASE_DELETING_ENABLED,
DISABLE_CLEARING_FOSSOLOGY_REPORT_DOWNLOAD, IS_FORCE_UPDATE_ENABLED, SBOM_IMPORT_EXPORT_ACCESS_USER_ROLE,
DISABLE_CLEARING_FOSSOLOGY_REPORT_DOWNLOAD, IS_FORCE_UPDATE_ENABLED, LICENSE_MANUAL_CREATION_ENABLED,
SBOM_IMPORT_EXPORT_ACCESS_USER_ROLE,
TOOL_NAME, TOOL_VENDOR, IS_PACKAGE_PORTLET_ENABLED, PACKAGE_PORTLET_WRITE_ACCESS_USER_ROLE, INHERIT_ATTACHMENT_USAGES,
RELEASE_FRIENDLY_URL, IS_ADMIN_PRIVATE_ACCESS_ENABLED, SKIP_DOMAINS_FOR_VALID_SOURCE_CODE, VCS_HOSTS,
NON_PKG_MANAGED_COMPS_PROP, REST_API_TOKEN_LENGTH,
Expand Down
5 changes: 4 additions & 1 deletion rest/resource-server/src/docs/asciidoc/licenses.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ include::{snippets}/should_document_get_license/links.adoc[]
==== Create a license

A `POST` request will create a license.
Manual license creation is deprecated and disabled by default. To enable it, set `license.manual.creation.enabled`
to `true` in SW360 configurations. If disabled, the API responds with `403 Forbidden` and a message instructing
you to sync licenses from LicenseDB.

===== Response structure
include::{snippets}/should_document_create_license/response-fields.adoc[]
Expand Down Expand Up @@ -280,4 +283,4 @@ A `DELETE` request will delete a single license type.
include::{snippets}/should_document_delete_license_type/curl-request.adoc[]

===== Example response
include::{snippets}/should_document_delete_license_type/http-response.adoc[]
include::{snippets}/should_document_delete_license_type/http-response.adoc[]
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.eclipse.sw360.datahandler.common.CommonUtils;
import org.eclipse.sw360.datahandler.common.SW360ConfigKeys;
import org.eclipse.sw360.datahandler.common.SW360Utils;
import org.eclipse.sw360.datahandler.permissions.PermissionUtils;
import org.eclipse.sw360.datahandler.resourcelists.PaginationOptions;
Expand Down Expand Up @@ -823,6 +824,9 @@ private void isLicenseValid(Set<String> licenses) {
}

private void createMissingLicense(String licenseId) throws Exception {
if (!SW360Utils.readConfig(SW360ConfigKeys.LICENSE_MANUAL_CREATION_ENABLED, false)) {
throw new BadRequestClientException("Manual license creation is disabled. Please sync licenses from LicenseDB.");
}
License newLicense = new License();
newLicense.setId(licenseId);
newLicense.setShortname(licenseId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.eclipse.sw360.datahandler.common.SW360ConfigKeys;
import org.eclipse.sw360.datahandler.common.SW360Utils;
import org.eclipse.sw360.datahandler.common.CommonUtils;
import org.eclipse.sw360.datahandler.common.SW360Constants;
import org.eclipse.sw360.datahandler.resourcelists.PaginationParameterException;
Expand Down Expand Up @@ -102,6 +104,10 @@ public class LicenseController implements RepresentationModelProcessor<Repositor

private static final ImmutableMap<String, String> RESPONSE_BODY_FOR_MODERATION_REQUEST = ImmutableMap.<String, String>builder()
.put("message", "Moderation request is created").build();
private static final ImmutableMap<String, String> RESPONSE_BODY_FOR_LICENSE_CREATION_DISABLED = ImmutableMap.<String, String>builder()
.put("message", "Manual license creation is disabled. Please sync licenses from LicenseDB.").build();
private static final String LICENSE_CREATION_DEPRECATION_WARNING =
"299 - \"Manual license creation is deprecated; sync from LicenseDB.\"";

@Operation(
summary = "List all of the service's licenses.",
Expand Down Expand Up @@ -231,14 +237,21 @@ public ResponseEntity deleteLicense(
)
@PreAuthorize("hasAuthority('WRITE')")
@PostMapping(value = LICENSES_URL)
public ResponseEntity<EntityModel<License>> createLicense(
public ResponseEntity<?> createLicense(
@Parameter(description = "The license to be created.")
@RequestBody License license
) throws TException {
User sw360User = restControllerHelper.getSw360UserFromAuthentication();
if (!SW360Utils.readConfig(SW360ConfigKeys.LICENSE_MANUAL_CREATION_ENABLED, false)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.header("Warning", LICENSE_CREATION_DEPRECATION_WARNING)
.body(RESPONSE_BODY_FOR_LICENSE_CREATION_DISABLED);
}
List<License> sw360Licenses = licenseService.getLicenses();
if(restControllerHelper.checkDuplicateLicense(sw360Licenses, license.shortname)) {
return new ResponseEntity("sw360 license with name " + license.shortname + " already exists.", HttpStatus.CONFLICT);
return ResponseEntity.status(HttpStatus.CONFLICT)
.header("Warning", LICENSE_CREATION_DEPRECATION_WARNING)
.body("sw360 license with name " + license.shortname + " already exists.");
}
license = licenseService.createLicense(license, sw360User);
HalResource<License> halResource = createHalLicense(license);
Expand All @@ -247,7 +260,9 @@ public ResponseEntity<EntityModel<License>> createLicense(
.fromCurrentRequest().path("/{id}")
.buildAndExpand(license.getId()).toUri();

return ResponseEntity.created(location).body(halResource);
return ResponseEntity.created(location)
.header("Warning", LICENSE_CREATION_DEPRECATION_WARNING)
.body(halResource);
}

@PreAuthorize("hasAuthority('WRITE')")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,18 +239,10 @@ public void should_create_license() throws IOException, TException {
requestEntity,
String.class);

assertEquals(HttpStatus.CREATED, response.getStatusCode());
assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
assertNotNull(response.getBody());

String responseBody = response.getBody();
assertTrue("Response should contain created license fullName", responseBody.contains("fullName"));
assertTrue("Response should contain created license shortName", responseBody.contains("shortName"));
assertTrue("Response should contain Apache 3.0", responseBody.contains("Apache 3.0"));
assertTrue("Response should contain Apache License 3.0", responseBody.contains("Apache License 3.0"));
assertTrue("Response should contain checked field", responseBody.contains("checked"));
assertTrue("Response should contain OSIApproved field", responseBody.contains("OSIApproved"));
assertTrue("Response should contain FSFLibre field", responseBody.contains("FSFLibre"));
assertTrue("Response should contain _links", responseBody.contains("_links"));
assertTrue("Response should instruct to sync licenses from LicenseDB",
response.getBody().contains("LicenseDB"));
}

@Test
Expand Down Expand Up @@ -529,7 +521,7 @@ public void should_handle_exception_in_create_license() throws IOException, TExc
requestEntity,
String.class);

assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
package org.eclipse.sw360.rest.resourceserver.restdocs;

import org.apache.thrift.TException;
import org.eclipse.sw360.datahandler.common.SW360ConfigKeys;
import org.eclipse.sw360.datahandler.common.SW360Utils;
import org.eclipse.sw360.datahandler.thrift.licenses.License;
import org.eclipse.sw360.datahandler.thrift.licenses.LicenseType;
import org.eclipse.sw360.datahandler.thrift.users.User;
Expand All @@ -26,6 +28,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
Expand Down Expand Up @@ -53,6 +56,7 @@
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;

@RunWith(SpringJUnit4ClassRunner.class)
public class LicenseSpecTest extends TestRestDocsSpecBase {
Expand Down Expand Up @@ -306,24 +310,29 @@ public void should_document_create_license() throws Exception {
Map<String, String> licenseRequestBody = new HashMap<>();
licenseRequestBody.put("fullName", "Apache 3.0");
licenseRequestBody.put("shortName", "Apache License 3.0");
this.mockMvc.perform(post("/api/licenses")
.contentType(MediaTypes.HAL_JSON)
.content(this.objectMapper.writeValueAsString(licenseRequestBody))
.header("Authorization", TestHelper.generateAuthHeader(testUserId, testUserPassword)))
.andExpect(status().isCreated())
.andDo(this.documentationHandler.document(
requestFields(
fieldWithPath("fullName").description("The fullName of the new license"),
fieldWithPath("shortName").description("The shortname of the origin license")
),
responseFields(
fieldWithPath("fullName").description("The fullName of the license"),
fieldWithPath("shortName").description("The shortname of the license"),
fieldWithPath("checked").description("The information, whether the license is already checked, optional and defaults to true"),
subsectionWithPath("OSIApproved").description("The OSI aprroved information, possible values are: " + Arrays.asList(Quadratic.values())),
fieldWithPath("FSFLibre").description("The FSF libre information, possible values are: " + Arrays.asList(Quadratic.values())),
subsectionWithPath("_links").description("<<resources-index-links,Links>> to other resources")
)));
try (MockedStatic<SW360Utils> sw360UtilsMock = Mockito.mockStatic(SW360Utils.class)) {
sw360UtilsMock.when(() -> SW360Utils.readConfig(SW360ConfigKeys.LICENSE_MANUAL_CREATION_ENABLED, false))
.thenReturn(true);
this.mockMvc.perform(post("/api/licenses")
.contentType(MediaTypes.HAL_JSON)
.content(this.objectMapper.writeValueAsString(licenseRequestBody))
.header("Authorization", TestHelper.generateAuthHeader(testUserId, testUserPassword)))
.andExpect(status().isCreated())
.andExpect(header().string("Warning", "299 - \"Manual license creation is deprecated; sync from LicenseDB.\""))
.andDo(this.documentationHandler.document(
requestFields(
fieldWithPath("fullName").description("The fullName of the new license"),
fieldWithPath("shortName").description("The shortname of the origin license")
),
responseFields(
fieldWithPath("fullName").description("The fullName of the license"),
fieldWithPath("shortName").description("The shortname of the license"),
fieldWithPath("checked").description("The information, whether the license is already checked, optional and defaults to true"),
subsectionWithPath("OSIApproved").description("The OSI aprroved information, possible values are: " + Arrays.asList(Quadratic.values())),
fieldWithPath("FSFLibre").description("The FSF libre information, possible values are: " + Arrays.asList(Quadratic.values())),
subsectionWithPath("_links").description("<<resources-index-links,Links>> to other resources")
)));
}
}

@Test
Expand Down
Loading