Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1fdd957e9e | ||
|
|
18de1e52f5 | ||
|
|
00ef5f67a1 | ||
|
|
74b289b38c | ||
|
|
100b1c4cc1 | ||
|
|
f96adb2097 | ||
|
|
4e43e4e255 | ||
|
|
7bb15fe456 | ||
|
|
a169fb585c | ||
|
|
af38bb2f29 | ||
|
|
f25253cb3b | ||
|
|
ad7035d7cf | ||
|
|
dfa4009b84 | ||
|
|
4eefde9ff6 | ||
|
|
45f6386104 | ||
|
|
db495d17b3 | ||
|
|
e0a1df09ab | ||
|
|
93e3315a8a | ||
|
|
5e3d632846 | ||
|
|
6412b50ff9 | ||
|
|
4e4a8d7089 | ||
|
|
e2f84d9bbf | ||
|
|
09a86f0a23 | ||
|
|
8adeb37275 | ||
|
|
6968f94e6e | ||
|
|
01731bb7a4 | ||
|
|
47ffe83b8f | ||
|
|
b3757876a7 | ||
|
|
dddf2ba3d1 | ||
|
|
38bbb71965 | ||
|
|
014e82e9b3 | ||
|
|
f5f08b215e | ||
|
|
a540524d52 | ||
|
|
8cba143c76 | ||
|
|
5e0a363aff | ||
|
|
26525d4baa | ||
|
|
c6ea2430bb | ||
|
|
f88dd799b0 | ||
|
|
f4555e1737 | ||
|
|
50e6178060 | ||
|
|
25b2db376b | ||
|
|
0cba921ce2 | ||
|
|
ce8cfff69e | ||
|
|
2c2f3464e9 | ||
|
|
eaa70cffb1 | ||
|
|
6bbe3316ac | ||
|
|
3f94e66eda | ||
|
|
114fbfc62f | ||
|
|
d3e575159f | ||
|
|
5e7dcb1689 | ||
|
|
f9668a3c07 | ||
|
|
aa9fe087f5 | ||
|
|
310339a5d9 | ||
|
|
23c3b6787e | ||
|
|
ae21409577 | ||
|
|
ae04a6fd74 | ||
|
|
d5b2cb2af2 | ||
|
|
e71712450d |
@ -94,12 +94,16 @@ configurations {
|
||||
}
|
||||
}
|
||||
|
||||
val persistenceServiceVersion = "2.589.1-RED10196.2"
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation("com.knecon.fforesight:database-tenant-commons:0.24.0")
|
||||
implementation("com.iqser.red.service:persistence-service-internal-api-v1:${persistenceServiceVersion}")
|
||||
implementation("com.knecon.fforesight:database-tenant-commons:0.28.0-RED10196.0")
|
||||
implementation("com.knecon.fforesight:keycloak-commons:0.28.0")
|
||||
implementation("com.knecon.fforesight:swagger-commons:0.7.0")
|
||||
implementation("com.knecon.fforesight:tracing-commons:0.5.0")
|
||||
implementation("com.knecon.fforesight:lifecycle-commons:0.6.0")
|
||||
implementation("net.logstash.logback:logstash-logback-encoder:7.4")
|
||||
implementation("ch.qos.logback:logback-classic")
|
||||
implementation("org.postgresql:postgresql:42.5.4")
|
||||
|
||||
@ -8,16 +8,22 @@ import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfigurat
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
|
||||
import com.knecon.fforesight.keycloakcommons.DefaultKeyCloakCommonsAutoConfiguration;
|
||||
import com.knecon.fforesight.lifecyclecommons.LifecycleAutoconfiguration;
|
||||
import com.knecon.fforesight.swaggercommons.SpringDocAutoConfiguration;
|
||||
import com.knecon.fforesight.tenantcommons.MultiTenancyAutoConfiguration;
|
||||
import com.knecon.fforesight.tenantusermanagement.client.LicenseClient;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@ImportAutoConfiguration({MultiTenancyAutoConfiguration.class, LiquibaseAutoConfiguration.class, DefaultKeyCloakCommonsAutoConfiguration.class, SpringDocAutoConfiguration.class})
|
||||
@ImportAutoConfiguration({MultiTenancyAutoConfiguration.class, LiquibaseAutoConfiguration.class, DefaultKeyCloakCommonsAutoConfiguration.class, SpringDocAutoConfiguration.class, LifecycleAutoconfiguration.class})
|
||||
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class, CassandraAutoConfiguration.class, MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
|
||||
@EnableAspectJAutoProxy
|
||||
@EnableFeignClients(basePackageClasses = LicenseClient.class)
|
||||
public class TenantUserManagementServiceApplication {
|
||||
|
||||
/**
|
||||
|
||||
@ -17,8 +17,8 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.knecon.fforesight.tenantcommons.model.TenantResponse;
|
||||
import com.knecon.fforesight.tenantcommons.model.UpdateDetailsRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.DeploymentKeyResponse;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SimpleTenantResponse;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.CreateTenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.UpdateTenantRequest;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
@ -36,14 +36,13 @@ public interface TenantsResource {
|
||||
@PostMapping(value = TENANTS_PATH, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Create a new tenant", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
void createTenant(@RequestBody TenantRequest tenant);
|
||||
void createTenant(@RequestBody CreateTenantRequest tenant);
|
||||
|
||||
|
||||
@ResponseBody
|
||||
@ResponseStatus(value = HttpStatus.NO_CONTENT)
|
||||
@Operation(summary = "Deletes given tenant", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "403", description = "Forbidden access, you dont have rights to delete tenants"), @ApiResponse(responseCode = "405", description = "Operation is not allowed."),
|
||||
@ApiResponse(responseCode = "409", description = "Conflict while deleting tenant.")})
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "403", description = "Forbidden access, you dont have rights to delete tenants"), @ApiResponse(responseCode = "405", description = "Operation is not allowed."), @ApiResponse(responseCode = "409", description = "Conflict while deleting tenant.")})
|
||||
@DeleteMapping(value = TENANTS_TENANT_ID_PATH)
|
||||
void deleteTenant(@PathVariable("tenantId") String tenantId);
|
||||
|
||||
@ -63,7 +62,7 @@ public interface TenantsResource {
|
||||
@PutMapping(value = TENANTS_TENANT_ID_PATH, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Update existing tenant", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
TenantResponse updateTenant(@PathVariable("tenantId") String tenantId, @RequestBody TenantRequest tenantRequest);
|
||||
TenantResponse updateTenant(@PathVariable("tenantId") String tenantId, @RequestBody UpdateTenantRequest tenantRequest);
|
||||
|
||||
|
||||
@PostMapping(value = TENANTS_TENANT_ID_PATH + "/details", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ -72,12 +71,6 @@ public interface TenantsResource {
|
||||
void updateDetails(@PathVariable("tenantId") String tenantId, @RequestBody UpdateDetailsRequest request);
|
||||
|
||||
|
||||
@GetMapping(value = TENANTS_PATH + "/simple", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Gets all existing tenants in a simplified format", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
List<SimpleTenantResponse> getSimpleTenants();
|
||||
|
||||
|
||||
@GetMapping(value = "/deploymentKey" + TENANT_ID_PATH_PARAM, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Returns the deployment key for a tenant", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
|
||||
@ -10,7 +10,6 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
@ -61,7 +60,7 @@ public interface UserResource {
|
||||
@ResponseBody
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@Operation(summary = "Update a user profile", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "400", description = "Failed to update profile, e-mail invalid")})
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "204", description = "OK"), @ApiResponse(responseCode = "400", description = "Failed to update profile, e-mail invalid"), @ApiResponse(responseCode = "404", description = "The userId cannot be found.")})
|
||||
@PostMapping(value = UPDATE_USER_PROFILE_PATH + USER_ID_PATH_VARIABLE, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
User updateProfile(@PathVariable(USER_ID) String userId, @RequestBody UpdateProfileRequest updateProfileRequest);
|
||||
|
||||
@ -99,7 +98,7 @@ public interface UserResource {
|
||||
|
||||
@ResponseBody
|
||||
@Operation(summary = "Gets the user in realm including role info", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "The " + "userId cannot be found."), @ApiResponse(responseCode = "400", description = "The provided user id is empty or " + "null.")})
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "404", description = "The userId cannot be found."), @ApiResponse(responseCode = "400", description = "The provided user id is empty or null.")})
|
||||
@GetMapping(value = USER_REST_PATH + USER_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
User getUserById(@PathVariable(USER_ID) String userId);
|
||||
|
||||
@ -120,8 +119,7 @@ public interface UserResource {
|
||||
|
||||
@ResponseBody
|
||||
@Operation(summary = "Activate/deactivate a user profile", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Failed to activate/deactivate profile"),
|
||||
@ApiResponse(responseCode = "403", description = "Cannot activate/deactivate users with higher rank roles")})
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "400", description = "Failed to activate/deactivate profile"), @ApiResponse(responseCode = "403", description = "Cannot activate/deactivate users with higher rank roles"), @ApiResponse(responseCode = "404", description = "The userId cannot be found.")})
|
||||
@PostMapping(value = ACTIVATE_USER_PROFILE_PATH + USER_ID_PATH_VARIABLE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
User activateProfile(@PathVariable(USER_ID) String userId, @RequestParam(IS_ACTIVE_PARAM) boolean isActive);
|
||||
|
||||
|
||||
@ -12,11 +12,12 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.knecon.fforesight.tenantcommons.TenantApplicationType;
|
||||
import com.knecon.fforesight.tenantcommons.model.TenantResponse;
|
||||
import com.knecon.fforesight.tenantcommons.model.UpdateDetailsRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.DeploymentKeyResponse;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SimpleTenantResponse;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.CreateTenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.UpdateTenantRequest;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
@ -38,17 +39,17 @@ public interface InternalTenantsResource {
|
||||
@PostMapping(value = "/tenants", consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Creates a new Tenant", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
TenantResponse createTenant(@RequestBody TenantRequest tenant);
|
||||
TenantResponse createTenant(@RequestBody CreateTenantRequest tenant);
|
||||
|
||||
|
||||
@GetMapping(value = "/tenants", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Gets all existing tenant", description = "None")
|
||||
@Operation(summary = "Gets all existing tenants", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
List<TenantResponse> getTenants();
|
||||
|
||||
|
||||
@GetMapping(value = "/tenants/{tenantId}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Gets all existing tenant", description = "None")
|
||||
@Operation(summary = "Get the given tenant", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
TenantResponse getTenant(@PathVariable("tenantId") String tenantId);
|
||||
|
||||
@ -56,13 +57,7 @@ public interface InternalTenantsResource {
|
||||
@PutMapping(value = "/tenants/{tenantId}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Update existing tenant", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
TenantResponse updateTenant(@PathVariable("tenantId") String tenantId, @RequestBody TenantRequest tenantRequest);
|
||||
|
||||
|
||||
@GetMapping(value = "/tenants/simple", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Gets all existing tenant in a simplified format", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
List<SimpleTenantResponse> getSimpleTenants();
|
||||
TenantResponse updateTenant(@PathVariable("tenantId") String tenantId, @RequestBody UpdateTenantRequest tenantRequest);
|
||||
|
||||
|
||||
@GetMapping(value = "/deploymentKey" + TENANT_ID_PATH_PARAM, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ -76,4 +71,10 @@ public interface InternalTenantsResource {
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
void syncTenant(@PathVariable("tenantId") String tenantId, @RequestBody JsonNode payload);
|
||||
|
||||
|
||||
@GetMapping(value = {"/tenants/{tenantId}/application-type"}, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Operation(summary = "Gets the application type of the given tenant", description = "None")
|
||||
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")})
|
||||
TenantApplicationType getTenantApplicationType(@PathVariable("tenantId") String tenantId);
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.client;
|
||||
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.internal.resources.LicenseResource;
|
||||
|
||||
@FeignClient(name = "LicenseResource", url = "${persistence-service.url}")
|
||||
public interface LicenseClient extends LicenseResource {
|
||||
|
||||
}
|
||||
@ -7,10 +7,12 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantusermanagement.api.external.GeneralSettingsResource;
|
||||
import com.knecon.fforesight.tenantusermanagement.api.external.PublicResource;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.GeneralConfigurationModel;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.GeneralConfigurationService;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.TenantManagementService;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -21,13 +23,14 @@ import lombok.extern.slf4j.Slf4j;
|
||||
public class GeneralSettingsController implements GeneralSettingsResource, PublicResource {
|
||||
|
||||
private final GeneralConfigurationService generalConfigurationService;
|
||||
private final TenantManagementService tenantManagementService;
|
||||
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('" + READ_GENERAL_CONFIGURATION + "')")
|
||||
public GeneralConfigurationModel getGeneralConfigurations() {
|
||||
|
||||
return generalConfigurationService.getGeneralConfigurations();
|
||||
return generalConfigurationService.getGeneralConfigurations(tenantManagementService.getTenantApplicationType(TenantContext.getTenantId()));
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +38,7 @@ public class GeneralSettingsController implements GeneralSettingsResource, Publi
|
||||
@PreAuthorize("hasAuthority('" + WRITE_GENERAL_CONFIGURATION + "')")
|
||||
public void updateGeneralConfigurations(@RequestBody GeneralConfigurationModel generalConfigurationModel) {
|
||||
|
||||
generalConfigurationService.updateGeneralConfigurations(generalConfigurationModel);
|
||||
generalConfigurationService.updateGeneralConfigurations(generalConfigurationModel, tenantManagementService.getTenantApplicationType(TenantContext.getTenantId()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -21,9 +21,10 @@ import com.knecon.fforesight.tenantusermanagement.model.SMTPConfiguration;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SMTPResponse;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.EmailService;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.RealmService;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.SMTPService;
|
||||
|
||||
import jakarta.ws.rs.BadRequestException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@ -31,21 +32,16 @@ import lombok.extern.slf4j.Slf4j;
|
||||
@RequiredArgsConstructor
|
||||
public class SMTPConfigurationController implements SMTPConfigurationResource, PublicResource {
|
||||
|
||||
private final static String SMTP_PASSWORD_KEY = "FFORESIGHT_SMTP_PASSWORD";
|
||||
private final static String DEFAULT_PASSWORD = "**********";
|
||||
private final RealmService realmService;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final EncryptionDecryptionService encryptionDecryptionService;
|
||||
private final EmailService emailService;
|
||||
private final SMTPService smtpService;
|
||||
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('" + READ_SMTP_CONFIGURATION + "')")
|
||||
public SMTPConfiguration getCurrentSMTPConfiguration() {
|
||||
|
||||
var realm = realmService.realm(TenantContext.getTenantId()).toRepresentation();
|
||||
return objectMapper.convertValue(realm.getSmtpServer(), SMTPConfiguration.class);
|
||||
|
||||
return smtpService.getSMTPConfiguration();
|
||||
}
|
||||
|
||||
|
||||
@ -53,17 +49,14 @@ public class SMTPConfigurationController implements SMTPConfigurationResource, P
|
||||
@PreAuthorize("hasAuthority('" + WRITE_SMTP_CONFIGURATION + "')")
|
||||
public void updateSMTPConfiguration(@RequestBody SMTPConfiguration smtpConfigurationModel) {
|
||||
|
||||
var realmRepresentation = realmService.realm(TenantContext.getTenantId()).toRepresentation();
|
||||
var propertiesMap = convertSMTPConfigurationModelToMap(smtpConfigurationModel);
|
||||
realmRepresentation.setSmtpServer(propertiesMap);
|
||||
|
||||
if (!smtpConfigurationModel.getPassword().matches("\\**")) {
|
||||
realmRepresentation.getAttributesOrEmpty().put(SMTP_PASSWORD_KEY, encryptionDecryptionService.encrypt(smtpConfigurationModel.getPassword()));
|
||||
if (!smtpService.canUpdateSMTPConfig()) {
|
||||
throw new BadRequestException("Current license does not allow updating the SMTP configuration!");
|
||||
}
|
||||
|
||||
realmService.realm(TenantContext.getTenantId()).update(realmRepresentation);
|
||||
smtpService.updateSMTPConfiguration(smtpConfigurationModel);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('" + WRITE_SMTP_CONFIGURATION + "')")
|
||||
public SMTPResponse testSMTPConfiguration(@RequestBody SMTPConfiguration smtpConfiguration) {
|
||||
@ -77,53 +70,22 @@ public class SMTPConfigurationController implements SMTPConfigurationResource, P
|
||||
adminEmail = false;
|
||||
}
|
||||
|
||||
updatePassword(smtpConfiguration);
|
||||
smtpConfiguration.setPassword(encryptionDecryptionService.decrypt(smtpConfiguration.getPassword()));
|
||||
|
||||
SMTPResponse.SMTPResponseBuilder smtpResponseBuilder = emailService.send(convertSMTPConfigurationModelToMap(smtpConfiguration), targetEmail, "Redaction Test message", "This is a test message");
|
||||
SMTPResponse.SMTPResponseBuilder smtpResponseBuilder = emailService.send(smtpService.convertSMTPConfigToMap(smtpConfiguration),
|
||||
targetEmail,
|
||||
"Redaction Test message",
|
||||
"This is a test message");
|
||||
SMTPResponse smtpResponse = smtpResponseBuilder.adminEmail(adminEmail).recipientEmail(targetEmail).build();
|
||||
log.info("Test SMTP Configuration status: {}, reason: {}, recipient: {}", smtpResponse.getStatusCode(), smtpResponse.getReasonPhrase(), smtpResponse.getRecipientEmail());
|
||||
return smtpResponse;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@PreAuthorize("hasAuthority('" + WRITE_SMTP_CONFIGURATION + "')")
|
||||
public void clearSMTPConfiguration() {
|
||||
// also update in KC
|
||||
var realmRepresentation = realmService.realm(TenantContext.getTenantId()).toRepresentation();
|
||||
realmRepresentation.setSmtpServer(new HashMap<>());
|
||||
realmRepresentation.getAttributesOrEmpty().remove(SMTP_PASSWORD_KEY);
|
||||
realmService.realm(TenantContext.getTenantId()).update(realmRepresentation);
|
||||
|
||||
smtpService.createDefaultSMTPConfiguration();
|
||||
|
||||
}
|
||||
|
||||
private Map<String, String> convertSMTPConfigurationModelToMap(SMTPConfiguration smtpConfigurationModel) {
|
||||
|
||||
Map<String, Object> propertiesMap = objectMapper.convertValue(smtpConfigurationModel, new TypeReference<>() {});
|
||||
Map<String, String> stringPropertiesMap = new HashMap<>();
|
||||
propertiesMap.forEach((key, value) -> {
|
||||
if (value != null) {
|
||||
stringPropertiesMap.put(key, value.toString());
|
||||
} else {
|
||||
stringPropertiesMap.put(key, "");
|
||||
}
|
||||
});
|
||||
return stringPropertiesMap;
|
||||
}
|
||||
|
||||
private void updatePassword(SMTPConfiguration smtpConfiguration) {
|
||||
|
||||
if (DEFAULT_PASSWORD.equals(smtpConfiguration.getPassword())) {
|
||||
try {
|
||||
var password = realmService.realm(TenantContext.getTenantId()).toRepresentation().getAttributesOrEmpty().get(SMTP_PASSWORD_KEY);
|
||||
smtpConfiguration.setPassword(password);
|
||||
} catch (Exception e) {
|
||||
log.info("No current SMTP Config exists", e);
|
||||
}
|
||||
} else {
|
||||
smtpConfiguration.setPassword(encryptionDecryptionService.encrypt(smtpConfiguration.getPassword()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -22,8 +22,8 @@ import com.knecon.fforesight.tenantcommons.model.UpdateDetailsRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.api.external.PublicResource;
|
||||
import com.knecon.fforesight.tenantusermanagement.api.external.TenantsResource;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.DeploymentKeyResponse;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SimpleTenantResponse;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.CreateTenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.UpdateTenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.DeploymentKeyService;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.TenantManagementService;
|
||||
|
||||
@ -39,7 +39,7 @@ public class TenantsController implements TenantsResource, PublicResource {
|
||||
|
||||
|
||||
@PreAuthorize("hasAuthority('" + CREATE_TENANT + "')")
|
||||
public void createTenant(@Valid @RequestBody TenantRequest tenantRequest) {
|
||||
public void createTenant(@Valid @RequestBody CreateTenantRequest tenantRequest) {
|
||||
|
||||
try {
|
||||
tenantManagementService.createTenant(tenantRequest);
|
||||
@ -76,14 +76,8 @@ public class TenantsController implements TenantsResource, PublicResource {
|
||||
}
|
||||
|
||||
|
||||
public List<SimpleTenantResponse> getSimpleTenants() {
|
||||
|
||||
return tenantManagementService.getTenants().stream().map(t -> new SimpleTenantResponse(t.getTenantId(), t.getDisplayName(), t.getGuid())).toList();
|
||||
}
|
||||
|
||||
|
||||
@PreAuthorize("hasAuthority('" + UPDATE_TENANT + "')")
|
||||
public TenantResponse updateTenant(String tenantId, @RequestBody TenantRequest tenantRequest) {
|
||||
public TenantResponse updateTenant(String tenantId, @RequestBody UpdateTenantRequest tenantRequest) {
|
||||
|
||||
TenantResponse tenantResponse = tenantManagementService.updateTenant(tenantId, tenantRequest);
|
||||
return tenantManagementService.removePasswords(tenantResponse);
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.controller.external;
|
||||
|
||||
import static com.knecon.fforesight.tenantusermanagement.permissions.ApplicationRoles.KNECON_ROLE_FILTER;
|
||||
import static com.knecon.fforesight.tenantusermanagement.permissions.UserManagementPermissions.READ_ALL_USERS;
|
||||
import static com.knecon.fforesight.tenantusermanagement.permissions.UserManagementPermissions.READ_USERS;
|
||||
import static com.knecon.fforesight.tenantusermanagement.permissions.UserManagementPermissions.UPDATE_MY_PROFILE;
|
||||
@ -7,7 +8,6 @@ import static com.knecon.fforesight.tenantusermanagement.permissions.UserManagem
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -27,7 +27,7 @@ import com.knecon.fforesight.tenantusermanagement.model.UpdateMyProfileRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.UpdateProfileRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.User;
|
||||
import com.knecon.fforesight.tenantusermanagement.permissions.ApplicationRoles;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.TenantApplicationTypeService;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.UserService;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
@ -39,22 +39,9 @@ import lombok.extern.slf4j.Slf4j;
|
||||
@RequiredArgsConstructor
|
||||
public class UserController implements UserResource, PublicResource {
|
||||
|
||||
public static final Predicate<User> KNECON_ROLE_FILTER = user -> {
|
||||
Set<String> filteredRoles = user.getRoles()
|
||||
.stream()
|
||||
.filter(ApplicationRoles::isNoKneconRole)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (!user.getRoles().isEmpty() && filteredRoles.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
user.setRoles(filteredRoles);
|
||||
return true;
|
||||
};
|
||||
|
||||
private final UserService userService;
|
||||
private final TenantUserManagementProperties tenantUserManagementProperties;
|
||||
private final TenantApplicationTypeService tenantApplicationTypeService;
|
||||
|
||||
|
||||
@Override
|
||||
@ -64,7 +51,7 @@ public class UserController implements UserResource, PublicResource {
|
||||
if (bypassCache) {
|
||||
userService.evictUserCache();
|
||||
}
|
||||
var mappedRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles();
|
||||
var mappedRoles = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getAllRoles();
|
||||
|
||||
return userService.getAllUsers()
|
||||
.stream()
|
||||
|
||||
@ -9,16 +9,14 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantcommons.TenantApplicationType;
|
||||
import com.knecon.fforesight.tenantcommons.model.TenantResponse;
|
||||
import com.knecon.fforesight.tenantcommons.model.UpdateDetailsRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.api.internal.InternalResource;
|
||||
import com.knecon.fforesight.tenantusermanagement.api.internal.InternalTenantsResource;
|
||||
import com.knecon.fforesight.tenantusermanagement.events.TenantCreatedEvent;
|
||||
import com.knecon.fforesight.tenantusermanagement.events.TenantSyncEvent;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.CreateTenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.DeploymentKeyResponse;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SimpleTenantResponse;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.UpdateTenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.DeploymentKeyService;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.TenantManagementService;
|
||||
|
||||
@ -40,7 +38,7 @@ public class InternalTenantsController implements InternalTenantsResource, Inter
|
||||
}
|
||||
|
||||
|
||||
public TenantResponse createTenant(@Valid @RequestBody TenantRequest tenantRequest) {
|
||||
public TenantResponse createTenant(@Valid @RequestBody CreateTenantRequest tenantRequest) {
|
||||
|
||||
try {
|
||||
return tenantManagementService.createTenant(tenantRequest);
|
||||
@ -63,18 +61,12 @@ public class InternalTenantsController implements InternalTenantsResource, Inter
|
||||
|
||||
|
||||
@Override
|
||||
public TenantResponse updateTenant(String tenantId, TenantRequest tenantRequest) {
|
||||
public TenantResponse updateTenant(String tenantId, UpdateTenantRequest tenantRequest) {
|
||||
|
||||
return tenantManagementService.updateTenant(tenantId, tenantRequest);
|
||||
}
|
||||
|
||||
|
||||
public List<SimpleTenantResponse> getSimpleTenants() {
|
||||
|
||||
return tenantManagementService.getTenants().stream().map(t -> new SimpleTenantResponse(t.getTenantId(), t.getDisplayName(), t.getGuid())).toList();
|
||||
}
|
||||
|
||||
|
||||
public DeploymentKeyResponse getDeploymentKey(@PathVariable(TENANT_ID_PARAM) String tenantId) {
|
||||
|
||||
return new DeploymentKeyResponse(deploymentKeyService.getDeploymentKey(tenantId));
|
||||
@ -88,4 +80,10 @@ public class InternalTenantsController implements InternalTenantsResource, Inter
|
||||
|
||||
}
|
||||
|
||||
|
||||
public TenantApplicationType getTenantApplicationType(@PathVariable(TENANT_ID_PARAM) String tenantId) {
|
||||
|
||||
return tenantManagementService.getTenantApplicationType(tenantId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -15,14 +15,12 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.StatementCallback;
|
||||
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.model.AzureStorageConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.DatabaseConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.S3StorageConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.SearchConnection;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SearchConnectionRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.CreateTenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantUser;
|
||||
import com.knecon.fforesight.tenantusermanagement.repository.TenantRepository;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.TenantManagementService;
|
||||
@ -74,7 +72,7 @@ public class DevTestTenantService {
|
||||
createDatabase(tenantsDBName, tenantsDBPassword);
|
||||
createSchema(jdbcUrl, tenantId, tenantsDBName, tenantsDBPassword);
|
||||
|
||||
var tenantRequest = TenantRequest.builder()
|
||||
var tenantRequest = CreateTenantRequest.builder()
|
||||
.tenantId(tenantId)
|
||||
.displayName(tenantId)
|
||||
.guid(UUID.randomUUID().toString())
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "global_smtp_configuration")
|
||||
public class GlobalSMTPConfigurationEntity {
|
||||
|
||||
@Id
|
||||
@Column(nullable = false, updatable = false)
|
||||
private String id = "singleton";
|
||||
|
||||
@Column
|
||||
private Boolean auth;
|
||||
|
||||
@Column
|
||||
private String envelopeFrom;
|
||||
|
||||
@Column
|
||||
private String fromEmail;
|
||||
|
||||
@Column
|
||||
private String fromDisplayName;
|
||||
|
||||
@Column
|
||||
private String host;
|
||||
|
||||
@Column
|
||||
private String password;
|
||||
|
||||
@Column
|
||||
private Integer port;
|
||||
|
||||
@Column
|
||||
private String replyTo;
|
||||
|
||||
@Column
|
||||
private String replyToDisplayName;
|
||||
|
||||
@Column
|
||||
private Boolean ssl;
|
||||
|
||||
@Column
|
||||
private Boolean starttls;
|
||||
|
||||
@Column
|
||||
private String userName;
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ package com.knecon.fforesight.tenantusermanagement.entity;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.TenantApplicationType;
|
||||
import com.knecon.fforesight.tenantusermanagement.utils.JSONMapConverter;
|
||||
|
||||
import jakarta.persistence.Basic;
|
||||
@ -10,6 +11,8 @@ import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Convert;
|
||||
import jakarta.persistence.Embedded;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
@ -53,4 +56,9 @@ public class TenantEntity {
|
||||
@Convert(converter = JSONMapConverter.class)
|
||||
@Builder.Default
|
||||
private Map<String, Object> details = new HashMap<>();
|
||||
|
||||
@Column
|
||||
@Enumerated(EnumType.STRING)
|
||||
private TenantApplicationType applicationType;
|
||||
|
||||
}
|
||||
|
||||
@ -34,9 +34,7 @@ public class MigrateOnlyHook {
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
public void migrate() {
|
||||
|
||||
tenantManagementService.getTenants().forEach(tenant -> {
|
||||
keyCloakRoleManagerService.updateRoles(tenant.getTenantId());
|
||||
});
|
||||
tenantManagementService.getTenants().forEach(tenant -> keyCloakRoleManagerService.updateRoles(tenant.getTenantId(), tenant.getApplicationType()));
|
||||
|
||||
// This should only run in post upgrade hook
|
||||
if (isMigrateOnly) {
|
||||
|
||||
@ -3,6 +3,7 @@ package com.knecon.fforesight.tenantusermanagement.model;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.TenantApplicationType;
|
||||
import com.knecon.fforesight.tenantcommons.model.AzureStorageConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.DatabaseConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.S3StorageConnection;
|
||||
@ -20,8 +21,8 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Schema(description = "Object containing the request to create or update a tenant.")
|
||||
public class TenantRequest {
|
||||
@Schema(description = "Object containing the request to create a tenant.")
|
||||
public class CreateTenantRequest {
|
||||
|
||||
@NotBlank
|
||||
@Pattern(regexp = "[A-Za-z0-9_-]*", message = "Tenant Id must match [A-Za-z0-9_-]")
|
||||
@ -48,4 +49,7 @@ public class TenantRequest {
|
||||
@Schema(description = "Parameter containing a list of users of the tenant.")
|
||||
private List<TenantUser> defaultUsers = new ArrayList<>();
|
||||
|
||||
@Schema(description = "Parameter containing the application type of the tenant.")
|
||||
private TenantApplicationType applicationType;
|
||||
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.model;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Schema(description = "Object containing a simplified version of the tenant data.")
|
||||
public class SimpleTenantResponse {
|
||||
|
||||
@Schema(description = "Parameter containing the ID of the tenant.")
|
||||
private String tenantId;
|
||||
@Schema(description = "Parameter containing the display name of the tenant.")
|
||||
private String displayName;
|
||||
@Schema(description = "Parameter containing the global unique ID of the tenant.")
|
||||
private String guid;
|
||||
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.model.AzureStorageConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.DatabaseConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.S3StorageConnection;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Schema(description = "Object containing the request to update a tenant.")
|
||||
public class UpdateTenantRequest {
|
||||
|
||||
@NotBlank
|
||||
@Schema(description = "Parameter containing the display name of the tenant.")
|
||||
private String displayName;
|
||||
@Schema(description = "Parameter containing the global unique ID of the tenant.")
|
||||
private String guid;
|
||||
|
||||
@Schema(description = "Parameter containing data of the database connection.")
|
||||
private DatabaseConnection databaseConnection;
|
||||
@Schema(description = "Parameter containing data of the search connection.")
|
||||
private SearchConnectionRequest searchConnection;
|
||||
@Schema(description = "Parameter containing data of the Azure storage connection.")
|
||||
private AzureStorageConnection azureStorageConnection;
|
||||
@Schema(description = "Parameter containing data of the S3 storage connection.")
|
||||
private S3StorageConnection s3StorageConnection;
|
||||
@Schema(description = "Parameter containing data of the MongoDB connection.")
|
||||
private MongoDBConnection mongoDBConnection;
|
||||
|
||||
}
|
||||
@ -1,6 +1,10 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.permissions;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.knecon.fforesight.tenantusermanagement.model.User;
|
||||
|
||||
public final class ApplicationRoles {
|
||||
|
||||
@ -15,6 +19,21 @@ public final class ApplicationRoles {
|
||||
public static final Set<String> RED_ROLES = Set.of(RED_USER_ROLE, RED_MANAGER_ROLE, RED_ADMIN_ROLE, RED_USER_ADMIN_ROLE);
|
||||
|
||||
|
||||
public static final Predicate<User> KNECON_ROLE_FILTER = user -> {
|
||||
Set<String> filteredRoles = user.getRoles()
|
||||
.stream()
|
||||
.filter(ApplicationRoles::isNoKneconRole)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (!user.getRoles().isEmpty() && filteredRoles.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
user.setRoles(filteredRoles);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
public static boolean isNoKneconRole(String role) {
|
||||
|
||||
return !KNECON_ROLES.contains(role);
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.properties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.knecon.fforesight.tenantusermanagement.model.KCRoleMapping;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ApplicationTypeProperties {
|
||||
|
||||
private String applicationClientId;
|
||||
private String applicationName;
|
||||
private Integer tenantAccessTokenLifeSpan = 300;
|
||||
private Integer accessTokenLifeSpan = 1800;
|
||||
private Integer ssoSessionIdleTimeout = 86400;
|
||||
private Integer refreshTokenMaxReuse;
|
||||
private String defaultTheme = "redaction";
|
||||
private List<String> validRedirectUris = new ArrayList<>();
|
||||
private KCRoleMapping kcRoleMapping = new KCRoleMapping();
|
||||
private String loginTheme;
|
||||
private String appPrefix;
|
||||
|
||||
}
|
||||
@ -1,11 +1,13 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.properties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import com.knecon.fforesight.tenantusermanagement.model.KCRoleMapping;
|
||||
import com.knecon.fforesight.tenantcommons.TenantApplicationType;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@ -14,23 +16,17 @@ import lombok.Data;
|
||||
public class TenantUserManagementProperties {
|
||||
|
||||
private String serverUrl;
|
||||
private String publicServerUrl;
|
||||
private String realm;
|
||||
private String applicationClientId;
|
||||
private String swaggerClientId ="swagger-ui-client";
|
||||
private String realm = "master";
|
||||
private String swaggerClientId = "swagger-ui-client";
|
||||
private String swaggerClientSecret;
|
||||
private String clientId;
|
||||
private String clientSecret;
|
||||
private String publicServerUrl;
|
||||
private String basePath = "/";
|
||||
private String basePathV2 = "/api";
|
||||
private int connectionPoolSize = 10;
|
||||
private String applicationName;
|
||||
private Integer accessTokenLifeSpan = 1800;
|
||||
private Integer ssoSessionIdleTimeout = 86400;
|
||||
private String defaultTheme = "redaction";
|
||||
private List<String> validRedirectUris = new ArrayList<>();
|
||||
private KCRoleMapping kcRoleMapping = new KCRoleMapping();
|
||||
private String loginTheme;
|
||||
private String appPrefix;
|
||||
|
||||
private Map<String, ApplicationTypeProperties> applicationTypes = new HashMap<>();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import com.knecon.fforesight.tenantusermanagement.entity.GlobalSMTPConfigurationEntity;
|
||||
|
||||
public interface GlobalSMTPConfigurationRepository extends JpaRepository<GlobalSMTPConfigurationEntity, String> {
|
||||
|
||||
default Optional<GlobalSMTPConfigurationEntity> findSingleton() {
|
||||
|
||||
return findById("singleton");
|
||||
}
|
||||
}
|
||||
@ -2,11 +2,14 @@ package com.knecon.fforesight.tenantusermanagement.repository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.TenantApplicationType;
|
||||
import com.knecon.fforesight.tenantusermanagement.entity.TenantEntity;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
@ -16,10 +19,16 @@ public interface TenantRepository extends JpaRepository<TenantEntity, String> {
|
||||
@Query("select t from TenantEntity t where t.tenantId = :tenantId")
|
||||
Optional<TenantEntity> findByTenantId(@Param("tenantId") String tenantId);
|
||||
|
||||
|
||||
@CacheEvict(value = "tenantApplicationType", key = "#tenantId")
|
||||
@Transactional
|
||||
@Modifying(clearAutomatically = true, flushAutomatically = true)
|
||||
@Query("delete from TenantEntity t where t.id = :tenantId ")
|
||||
void deleteByQuery(String tenantId);
|
||||
|
||||
|
||||
@Cacheable(value = "tenantApplicationType", key = "#tenantId")
|
||||
@Query("select t.applicationType from TenantEntity t where t.tenantId = :tenantId")
|
||||
Optional<TenantApplicationType> findApplicationTypeByTenantId(@Param("tenantId") String tenantId);
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.service;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SMTPConfiguration;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class EnvironmentSMTPConfigurationProvider {
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
public static final Integer KEYCLOAK_DEFAULT_PORT = 25;
|
||||
public static final String SMTP_DEFAULT_HOST = "SMTP_DEFAULT_HOST";
|
||||
public static final String SMTP_DEFAULT_PORT = "SMTP_DEFAULT_PORT";
|
||||
public static final String SMTP_DEFAULT_SENDER_EMAIL = "SMTP_DEFAULT_SENDER_EMAIL";
|
||||
public static final String SMTP_DEFAULT_SENDER_NAME = "SMTP_DEFAULT_SENDER_NAME";
|
||||
public static final String SMTP_DEFAULT_REPLY_EMAIL = "SMTP_DEFAULT_REPLY_EMAIL";
|
||||
public static final String SMTP_DEFAULT_REPLY_NAME = "SMTP_DEFAULT_REPLY_NAME";
|
||||
public static final String SMTP_DEFAULT_SENDER_ENVELOPE = "SMTP_DEFAULT_SENDER_ENVELOPE";
|
||||
public static final String SMTP_DEFAULT_SSL = "SMTP_DEFAULT_SSL";
|
||||
public static final String SMTP_DEFAULT_STARTTLS = "SMTP_DEFAULT_STARTTLS";
|
||||
public static final String SMTP_DEFAULT_AUTH = "SMTP_DEFAULT_AUTH";
|
||||
public static final String SMTP_DEFAULT_AUTH_USER = "SMTP_DEFAULT_AUTH_USER";
|
||||
public static final String SMTP_DEFAULT_AUTH_PASSWORD = "SMTP_DEFAULT_AUTH_PASSWORD";
|
||||
|
||||
|
||||
public SMTPConfiguration get() {
|
||||
|
||||
String port = environment.getProperty(SMTP_DEFAULT_PORT, "");
|
||||
return SMTPConfiguration.builder()
|
||||
.id("singleton")
|
||||
.host(environment.getProperty(SMTP_DEFAULT_HOST, ""))
|
||||
.port(StringUtils.isEmpty(port) || !StringUtils.isNumeric(port) ? KEYCLOAK_DEFAULT_PORT : Integer.parseInt(port))
|
||||
.from(environment.getProperty(SMTP_DEFAULT_SENDER_EMAIL, ""))
|
||||
.fromDisplayName(environment.getProperty(SMTP_DEFAULT_SENDER_NAME, ""))
|
||||
.replyTo(environment.getProperty(SMTP_DEFAULT_REPLY_EMAIL, ""))
|
||||
.replyToDisplayName(environment.getProperty(SMTP_DEFAULT_REPLY_NAME, ""))
|
||||
.envelopeFrom(environment.getProperty(SMTP_DEFAULT_SENDER_ENVELOPE, ""))
|
||||
.ssl(Boolean.parseBoolean(environment.getProperty(SMTP_DEFAULT_SSL, "false")))
|
||||
.starttls(Boolean.parseBoolean(environment.getProperty(SMTP_DEFAULT_STARTTLS, "false")))
|
||||
.auth(Boolean.parseBoolean(environment.getProperty(SMTP_DEFAULT_AUTH, "false")))
|
||||
.user(environment.getProperty(SMTP_DEFAULT_AUTH_USER, ""))
|
||||
.password(environment.getProperty(SMTP_DEFAULT_AUTH_PASSWORD, ""))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@ -4,8 +4,10 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.TenantApplicationType;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.GeneralConfigurationModel;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.ApplicationTypeProperties;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -18,28 +20,30 @@ public class GeneralConfigurationService {
|
||||
|
||||
private final RealmService realmService;
|
||||
private final TenantUserManagementProperties tenantUserManagementProperties;
|
||||
private final TenantApplicationTypeService tenantApplicationTypeService;
|
||||
|
||||
|
||||
public void initGeneralConfiguration(String tenantId) {
|
||||
public void initGeneralConfiguration(String tenantId, TenantApplicationType tenantApplicationType) {
|
||||
|
||||
TenantContext.setTenantId(tenantId);
|
||||
var generalConfiguration = getGeneralConfigurations();
|
||||
log.info("Currently Configured Application Name: {}, default name: {}", generalConfiguration.getDisplayName(), tenantUserManagementProperties.getApplicationName());
|
||||
updateGeneralConfigurations(getGeneralConfigurations());
|
||||
var generalConfiguration = getGeneralConfigurations(tenantApplicationType);
|
||||
log.info("Currently Configured Application Name: {}, default name: {}", generalConfiguration.getDisplayName(), tenantApplicationTypeService.getProperties(tenantApplicationType).getApplicationName());
|
||||
updateGeneralConfigurations(getGeneralConfigurations(tenantApplicationType), tenantApplicationType);
|
||||
TenantContext.clear();
|
||||
}
|
||||
|
||||
|
||||
public GeneralConfigurationModel getGeneralConfigurations() {
|
||||
public GeneralConfigurationModel getGeneralConfigurations(TenantApplicationType tenantApplicationType) {
|
||||
|
||||
var realm = realmService.realm(TenantContext.getTenantId()).toRepresentation();
|
||||
var auxiliaryName = realm.getDisplayNameHtml();
|
||||
|
||||
String computedAuxiliaryName = null;
|
||||
|
||||
if (!tenantUserManagementProperties.getApplicationName().equals(auxiliaryName)) {
|
||||
ApplicationTypeProperties currentAppTypeProperties = tenantApplicationTypeService.getProperties(tenantApplicationType);
|
||||
if (!currentAppTypeProperties.getApplicationName().equals(auxiliaryName)) {
|
||||
|
||||
auxiliaryName = StringUtils.replaceOnce(auxiliaryName, tenantUserManagementProperties.getApplicationName(), "");
|
||||
auxiliaryName = StringUtils.replaceOnce(auxiliaryName, currentAppTypeProperties.getApplicationName(), "");
|
||||
auxiliaryName = StringUtils.replaceOnce(auxiliaryName, " (", "");
|
||||
auxiliaryName = StringUtils.reverse(StringUtils.replaceOnce(StringUtils.reverse(auxiliaryName), ")", ""));
|
||||
|
||||
@ -54,7 +58,7 @@ public class GeneralConfigurationService {
|
||||
}
|
||||
|
||||
|
||||
public void updateGeneralConfigurations(GeneralConfigurationModel generalConfigurationModel) {
|
||||
public void updateGeneralConfigurations(GeneralConfigurationModel generalConfigurationModel, TenantApplicationType tenantApplicationType) {
|
||||
|
||||
var realm = realmService.realm(TenantContext.getTenantId());
|
||||
|
||||
@ -68,12 +72,15 @@ public class GeneralConfigurationService {
|
||||
var realmRepresentation = realm.toRepresentation();
|
||||
realmRepresentation.setResetPasswordAllowed(generalConfigurationModel.isForgotPasswordFunctionEnabled());
|
||||
|
||||
realmRepresentation.setRevokeRefreshToken(true);
|
||||
ApplicationTypeProperties applicationTypeProperties = tenantApplicationTypeService.getProperties(tenantApplicationType);
|
||||
realmRepresentation.setRefreshTokenMaxReuse(applicationTypeProperties.getRefreshTokenMaxReuse());
|
||||
realmRepresentation.getAttributes().put("actionTokenGeneratedByUserLifespan.idp-verify-account-via-email", Integer.toString(86400));
|
||||
|
||||
if (!StringUtils.isEmpty(generalConfigurationModel.getAuxiliaryName())) {
|
||||
setDisplayName(realmRepresentation, tenantUserManagementProperties.getApplicationName() + " (" + generalConfigurationModel.getAuxiliaryName() + ")");
|
||||
setDisplayName(realmRepresentation, applicationTypeProperties.getApplicationName() + " (" + generalConfigurationModel.getAuxiliaryName() + ")");
|
||||
} else {
|
||||
setDisplayName(realmRepresentation, tenantUserManagementProperties.getApplicationName());
|
||||
setDisplayName(realmRepresentation, applicationTypeProperties.getApplicationName());
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.service;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.knecon.fforesight.tenantusermanagement.entity.GlobalSMTPConfigurationEntity;
|
||||
import com.knecon.fforesight.tenantusermanagement.repository.GlobalSMTPConfigurationRepository;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
|
||||
public class GlobalSMTPConfigurationPersistenceService {
|
||||
|
||||
GlobalSMTPConfigurationRepository smtpConfigurationRepository;
|
||||
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Optional<GlobalSMTPConfigurationEntity> get() {
|
||||
|
||||
return smtpConfigurationRepository.findSingleton();
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public GlobalSMTPConfigurationEntity createUpdate(GlobalSMTPConfigurationEntity smtpConfiguration) {
|
||||
|
||||
smtpConfiguration.setId("singleton");
|
||||
return smtpConfigurationRepository.save(smtpConfiguration);
|
||||
}
|
||||
|
||||
}
|
||||
@ -9,6 +9,8 @@ import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.TenantApplicationType;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.ApplicationTypeProperties;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -21,24 +23,26 @@ public class KeyCloakRoleManagerService {
|
||||
|
||||
private final RealmService realmService;
|
||||
private final TenantUserManagementProperties tenantUserManagementProperties;
|
||||
private final TenantApplicationTypeService tenantApplicationTypeService;
|
||||
|
||||
|
||||
public void updateRoles(String tenantId) {
|
||||
public void updateRoles(String tenantId, TenantApplicationType applicationType) {
|
||||
|
||||
var realm = realmService.realm(tenantId);
|
||||
|
||||
ApplicationTypeProperties applicationTypeProperties = tenantApplicationTypeService.getProperties(applicationType);
|
||||
log.info("Running KeyCloak Role Manager, managing client: {} with system client {}",
|
||||
tenantUserManagementProperties.getApplicationClientId(),
|
||||
tenantUserManagementProperties.getClientId());
|
||||
applicationTypeProperties.getApplicationClientId(),
|
||||
tenantUserManagementProperties.getClientId());
|
||||
var existingRoles = realm.roles().list().stream().map(RoleRepresentation::getName).collect(Collectors.toList());
|
||||
|
||||
log.info("Existing KC roles: {}", existingRoles);
|
||||
|
||||
var redactionClientRepresentation = getRedactionClientRepresentation(tenantId);
|
||||
var redactionClientRepresentation = getRedactionClientRepresentation(tenantId, applicationTypeProperties.getApplicationClientId());
|
||||
var redactionClient = realm.clients().get(redactionClientRepresentation.getId());
|
||||
var clientRoles = redactionClient.roles().list().stream().map(RoleRepresentation::getName).collect(Collectors.toList());
|
||||
|
||||
var allPermissions = tenantUserManagementProperties.getKcRoleMapping().getPermissions();
|
||||
var allPermissions = applicationTypeProperties.getKcRoleMapping().getPermissions();
|
||||
|
||||
log.info("Existing KC client roles: {}", clientRoles);
|
||||
log.info("Current Application KC client roles: {}", allPermissions);
|
||||
@ -65,8 +69,8 @@ public class KeyCloakRoleManagerService {
|
||||
|
||||
var allClientRoles = redactionClient.roles().list();
|
||||
|
||||
var allRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles();
|
||||
var rolePermissionMappings = tenantUserManagementProperties.getKcRoleMapping().getRolePermissionMapping();
|
||||
var allRoles = applicationTypeProperties.getKcRoleMapping().getAllRoles();
|
||||
var rolePermissionMappings = applicationTypeProperties.getKcRoleMapping().getRolePermissionMapping();
|
||||
|
||||
// if an application-role doesn't exist, create it
|
||||
for (String applicationRole : allRoles) {
|
||||
@ -93,7 +97,7 @@ public class KeyCloakRoleManagerService {
|
||||
log.info("Finished application role {}", applicationRole);
|
||||
}
|
||||
|
||||
var composites = tenantUserManagementProperties.getKcRoleMapping().getRoleComposites();
|
||||
var composites = applicationTypeProperties.getKcRoleMapping().getRoleComposites();
|
||||
for (var key : composites.keySet()) {
|
||||
var realmRole = realm.roles().get(key).toRepresentation();
|
||||
|
||||
@ -111,9 +115,8 @@ public class KeyCloakRoleManagerService {
|
||||
}
|
||||
|
||||
|
||||
private ClientRepresentation getRedactionClientRepresentation(String tenantId) {
|
||||
private ClientRepresentation getRedactionClientRepresentation(String tenantId, String applicationClientId) {
|
||||
|
||||
String applicationClientId = tenantUserManagementProperties.getApplicationClientId();
|
||||
var clientRepresentationIterator = realmService.realm(tenantId).clients().findByClientId(applicationClientId).iterator();
|
||||
|
||||
if (clientRepresentationIterator.hasNext()) {
|
||||
|
||||
@ -0,0 +1,258 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.Feature;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.RedactionLicenseModel;
|
||||
import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantusermanagement.client.LicenseClient;
|
||||
import com.knecon.fforesight.tenantusermanagement.entity.GlobalSMTPConfigurationEntity;
|
||||
import com.knecon.fforesight.tenantusermanagement.entity.TenantEntity;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SMTPConfiguration;
|
||||
import com.knecon.fforesight.tenantusermanagement.repository.TenantRepository;
|
||||
import com.knecon.fforesight.tenantusermanagement.utils.SMTPConfigurationMapper;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class SMTPService {
|
||||
|
||||
private final GlobalSMTPConfigurationPersistenceService smtpConfigurationPersistenceService;
|
||||
private final EnvironmentSMTPConfigurationProvider environmentSMTPConfigurationProvider;
|
||||
private final LicenseClient licenseClient;
|
||||
private final RealmService realmService;
|
||||
private final TenantRepository tenantRepository;
|
||||
|
||||
private final EncryptionDecryptionService encryptionDecryptionService;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private final static String SMTP_PASSWORD_KEY = "FFORESIGHT_SMTP_PASSWORD";
|
||||
private final static String DEFAULT_PASSWORD = "**********";
|
||||
public static final String CONFIGURABLE_SMTP_SERVER_FEATURE = "configurableSMTPServer";
|
||||
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
public void synchronizeSMTPConfigurations() {
|
||||
|
||||
log.info("Starting SMTP configuration synchronization...");
|
||||
|
||||
try {
|
||||
List<TenantEntity> tenants = tenantRepository.findAll();
|
||||
log.info("Retrieved {} tenants for SMTP synchronization.", tenants.size());
|
||||
|
||||
Optional<GlobalSMTPConfigurationEntity> optionalLatestGlobalConfigEntity = smtpConfigurationPersistenceService.get();
|
||||
|
||||
if (optionalLatestGlobalConfigEntity.isEmpty()) {
|
||||
log.info("Global SMTP configuration was newly added. Initializing all tenant SMTP configurations.");
|
||||
initializeGlobalSmtpConfig(tenants);
|
||||
|
||||
} else {
|
||||
updateGlobalSmtpConfig(optionalLatestGlobalConfigEntity.get(), tenants);
|
||||
}
|
||||
log.info("SMTP configuration synchronization completed successfully.");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to synchronize SMTP configurations: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initializeGlobalSmtpConfig(List<TenantEntity> tenants) {
|
||||
|
||||
SMTPConfiguration currentGlobalConfig = environmentSMTPConfigurationProvider.get();
|
||||
|
||||
initializeTenantsSmtpConfig(tenants, currentGlobalConfig);
|
||||
|
||||
currentGlobalConfig.setPassword(encryptionDecryptionService.encrypt(currentGlobalConfig.getPassword()));
|
||||
GlobalSMTPConfigurationEntity updatedGlobalConfig = SMTPConfigurationMapper.toEntity(currentGlobalConfig);
|
||||
smtpConfigurationPersistenceService.createUpdate(updatedGlobalConfig);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void updateGlobalSmtpConfig(GlobalSMTPConfigurationEntity latestGlobalConfigEntity, List<TenantEntity> tenants) {
|
||||
|
||||
SMTPConfiguration latestGlobalConfig = SMTPConfigurationMapper.toModel(latestGlobalConfigEntity);
|
||||
latestGlobalConfig.setPassword(encryptionDecryptionService.decrypt(latestGlobalConfig.getPassword()));
|
||||
log.info("Existing global SMTP configuration was loaded.");
|
||||
|
||||
// Generate the latest SMTP config from environment variables and compare it to the last/saved global config
|
||||
SMTPConfiguration currentGlobalConfig = environmentSMTPConfigurationProvider.get();
|
||||
if (!currentGlobalConfig.equals(latestGlobalConfig)) {
|
||||
|
||||
log.info("Environment SMTP configuration has changed. Updating global SMTP configuration.");
|
||||
updateTenantsSmtpConfig(tenants, latestGlobalConfig, currentGlobalConfig);
|
||||
|
||||
currentGlobalConfig.setPassword(encryptionDecryptionService.encrypt(currentGlobalConfig.getPassword()));
|
||||
GlobalSMTPConfigurationEntity updatedGlobalConfig = SMTPConfigurationMapper.toEntity(currentGlobalConfig);
|
||||
smtpConfigurationPersistenceService.createUpdate(updatedGlobalConfig);
|
||||
|
||||
} else {
|
||||
log.info("No changes detected in environment SMTP configuration.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initializeTenantsSmtpConfig(List<TenantEntity> tenants, SMTPConfiguration currentGlobalConfig) {
|
||||
|
||||
tenants.forEach(tenant -> processTenantSmtpConfig(tenant, currentGlobalConfig, null, true));
|
||||
}
|
||||
|
||||
|
||||
private void updateTenantsSmtpConfig(List<TenantEntity> tenants, SMTPConfiguration latestGlobalConfig, SMTPConfiguration currentGlobalConfig) {
|
||||
|
||||
tenants.forEach(tenant -> processTenantSmtpConfig(tenant, currentGlobalConfig, latestGlobalConfig, false));
|
||||
}
|
||||
|
||||
|
||||
private void processTenantSmtpConfig(TenantEntity tenant, SMTPConfiguration currentGlobalConfig, SMTPConfiguration latestGlobalConfig, boolean isInitialization) {
|
||||
|
||||
String tenantId = tenant.getTenantId();
|
||||
log.info("Processing SMTP configuration for tenant: {}", tenantId);
|
||||
|
||||
try {
|
||||
TenantContext.setTenantId(tenantId);
|
||||
SMTPConfiguration tenantSMTPConfig = getSMTPConfiguration();
|
||||
tenantSMTPConfig.setId("singleton");
|
||||
updatePassword(tenantSMTPConfig);
|
||||
|
||||
if (!StringUtils.isBlank(tenantSMTPConfig.getPassword())) {
|
||||
tenantSMTPConfig.setPassword(encryptionDecryptionService.decrypt(tenantSMTPConfig.getPassword()));
|
||||
}
|
||||
|
||||
if (isInitialization) {
|
||||
if (StringUtils.isBlank(tenantSMTPConfig.getHost())) {
|
||||
log.info("Tenant '{}' SMTP configuration has not been yet set.", tenantId);
|
||||
updateSMTPConfiguration(currentGlobalConfig);
|
||||
log.info("Tenant '{}' SMTP configuration set successfully.", tenantId);
|
||||
} else {
|
||||
log.info("Tenant '{}' SMTP configuration was already set. No action taken.", tenantId);
|
||||
}
|
||||
} else {
|
||||
if (tenantSMTPConfig.equals(latestGlobalConfig)) {
|
||||
log.info("Tenant '{}' SMTP configuration matches global. Updating to latest environment configuration.", tenantId);
|
||||
updateSMTPConfiguration(currentGlobalConfig);
|
||||
log.info("Tenant '{}' SMTP configuration updated successfully.", tenantId);
|
||||
} else {
|
||||
log.info("Tenant '{}' SMTP configuration differs from global. No action taken.", tenantId);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Error processing SMTP configuration for tenant '{}': {}", tenantId, e.getMessage());
|
||||
} finally {
|
||||
TenantContext.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public SMTPConfiguration getSMTPConfiguration() {
|
||||
|
||||
var realm = realmService.realm(TenantContext.getTenantId()).toRepresentation();
|
||||
return objectMapper.convertValue(realm.getSmtpServer(), SMTPConfiguration.class);
|
||||
}
|
||||
|
||||
|
||||
public Map<String, String> convertSMTPConfigToMap(SMTPConfiguration smtpConfiguration) {
|
||||
|
||||
updatePassword(smtpConfiguration);
|
||||
smtpConfiguration.setPassword(encryptionDecryptionService.decrypt(smtpConfiguration.getPassword()));
|
||||
return convertSMTPConfigurationModelToMap(smtpConfiguration);
|
||||
}
|
||||
|
||||
|
||||
public boolean canUpdateSMTPConfig() {
|
||||
|
||||
RedactionLicenseModel licenseModel = licenseClient.getLicense();
|
||||
String activeLicenseId = licenseModel.getActiveLicense();
|
||||
|
||||
return licenseModel.getLicenses()
|
||||
.stream()
|
||||
.filter(license -> license.getId().equals(activeLicenseId))
|
||||
.flatMap(license -> license.getFeatures()
|
||||
.stream())
|
||||
.filter(feature -> CONFIGURABLE_SMTP_SERVER_FEATURE.equals(feature.getName()))
|
||||
.map(Feature::getValue)
|
||||
.filter(Boolean.class::isInstance)
|
||||
.map(Boolean.class::cast)
|
||||
.findFirst()
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
|
||||
public void createDefaultSMTPConfiguration() {
|
||||
|
||||
SMTPConfiguration defaultConfig = environmentSMTPConfigurationProvider.get();
|
||||
updateSMTPConfiguration(defaultConfig);
|
||||
}
|
||||
|
||||
|
||||
public void updateSMTPConfiguration(SMTPConfiguration smtpConfigurationModel) {
|
||||
|
||||
String tenantId = TenantContext.getTenantId();
|
||||
var realmRepresentation = realmService.realm(tenantId).toRepresentation();
|
||||
var propertiesMap = convertSMTPConfigurationModelToMap(smtpConfigurationModel);
|
||||
realmRepresentation.setSmtpServer(propertiesMap);
|
||||
|
||||
if (smtpConfigurationModel.getPassword() != null && !smtpConfigurationModel.getPassword().matches("\\**")) {
|
||||
realmRepresentation.getAttributesOrEmpty().put(SMTP_PASSWORD_KEY, encryptionDecryptionService.encrypt(smtpConfigurationModel.getPassword()));
|
||||
}
|
||||
|
||||
realmService.realm(tenantId).update(realmRepresentation);
|
||||
}
|
||||
|
||||
|
||||
public void clearSMTPConfiguration() {
|
||||
|
||||
var realmRepresentation = realmService.realm(TenantContext.getTenantId()).toRepresentation();
|
||||
realmRepresentation.setSmtpServer(new HashMap<>());
|
||||
realmRepresentation.getAttributesOrEmpty().remove(SMTP_PASSWORD_KEY);
|
||||
realmService.realm(TenantContext.getTenantId()).update(realmRepresentation);
|
||||
}
|
||||
|
||||
|
||||
private Map<String, String> convertSMTPConfigurationModelToMap(SMTPConfiguration smtpConfigurationModel) {
|
||||
|
||||
Map<String, Object> propertiesMap = objectMapper.convertValue(smtpConfigurationModel, new TypeReference<>() {
|
||||
});
|
||||
Map<String, String> stringPropertiesMap = new HashMap<>();
|
||||
propertiesMap.forEach((key, value) -> {
|
||||
if (value != null) {
|
||||
stringPropertiesMap.put(key, value.toString());
|
||||
} else {
|
||||
stringPropertiesMap.put(key, "");
|
||||
}
|
||||
});
|
||||
return stringPropertiesMap;
|
||||
}
|
||||
|
||||
|
||||
private void updatePassword(SMTPConfiguration smtpConfiguration) {
|
||||
|
||||
if (DEFAULT_PASSWORD.equals(smtpConfiguration.getPassword())) {
|
||||
try {
|
||||
var password = realmService.realm(TenantContext.getTenantId()).toRepresentation().getAttributesOrEmpty().getOrDefault(SMTP_PASSWORD_KEY, "");
|
||||
smtpConfiguration.setPassword(password);
|
||||
} catch (Exception e) {
|
||||
log.info("No current SMTP Config exists", e);
|
||||
}
|
||||
} else {
|
||||
smtpConfiguration.setPassword(encryptionDecryptionService.encrypt(smtpConfiguration.getPassword()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.service;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.TenantApplicationType;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.ApplicationTypeProperties;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
import com.knecon.fforesight.tenantusermanagement.repository.TenantRepository;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
|
||||
public class TenantApplicationTypeService {
|
||||
|
||||
TenantUserManagementProperties tenantUserManagementProperties;
|
||||
TenantRepository tenantRepository;
|
||||
|
||||
|
||||
public TenantApplicationType getCurrent() {
|
||||
|
||||
return get(TenantContext.getTenantId());
|
||||
}
|
||||
|
||||
|
||||
public TenantApplicationType get(String tenantId) {
|
||||
|
||||
return tenantRepository.findApplicationTypeByTenantId(tenantId)
|
||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Tenant does not exist"));
|
||||
}
|
||||
|
||||
|
||||
public ApplicationTypeProperties getProperties(TenantApplicationType applicationType) {
|
||||
|
||||
return tenantUserManagementProperties.getApplicationTypes()
|
||||
.get(applicationType.name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
|
||||
public ApplicationTypeProperties getCurrentProperties() {
|
||||
|
||||
TenantApplicationType applicationType = get(TenantContext.getTenantId());
|
||||
return getProperties(applicationType);
|
||||
}
|
||||
|
||||
}
|
||||
@ -19,6 +19,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.bson.BsonArray;
|
||||
import org.bson.BsonDocument;
|
||||
import org.bson.BsonString;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
@ -42,6 +43,7 @@ import com.azure.storage.blob.BlobServiceClientBuilder;
|
||||
import com.azure.storage.blob.models.BlobItem;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService;
|
||||
import com.knecon.fforesight.tenantcommons.TenantApplicationType;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantcommons.TenantProvider;
|
||||
import com.knecon.fforesight.tenantcommons.model.AzureStorageConnection;
|
||||
@ -61,9 +63,11 @@ import com.knecon.fforesight.tenantusermanagement.entity.SearchConnectionEntity;
|
||||
import com.knecon.fforesight.tenantusermanagement.entity.TenantEntity;
|
||||
import com.knecon.fforesight.tenantusermanagement.events.TenantCreatedEvent;
|
||||
import com.knecon.fforesight.tenantusermanagement.events.TenantSyncEvent;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.CreateTenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SearchConnectionRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantUser;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.UpdateTenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.ApplicationTypeProperties;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
import com.knecon.fforesight.tenantusermanagement.repository.TenantRepository;
|
||||
import com.knecon.fforesight.tenantusermanagement.utils.JDBCUtils;
|
||||
@ -80,6 +84,7 @@ import software.amazon.awssdk.services.s3.model.DeleteBucketRequest;
|
||||
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
|
||||
import software.amazon.awssdk.services.s3.model.ListObjectsRequest;
|
||||
import software.amazon.awssdk.services.s3.model.ListObjectsResponse;
|
||||
import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
|
||||
import software.amazon.awssdk.services.s3.model.S3Object;
|
||||
|
||||
@Slf4j
|
||||
@ -103,17 +108,19 @@ public class TenantManagementService implements TenantProvider {
|
||||
private final RealmService realmService;
|
||||
private final RabbitTemplate rabbitTemplate;
|
||||
private final StorageConfiguration storageConfiguration;
|
||||
private final SMTPService smtpService;
|
||||
private final TenantApplicationTypeService tenantApplicationTypeService;
|
||||
|
||||
@Value("${fforesight.tenant-exchange.name}")
|
||||
private String tenantExchangeName;
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
public TenantResponse createTenant(TenantRequest tenantRequest) {
|
||||
public TenantResponse createTenant(CreateTenantRequest tenantRequest) {
|
||||
|
||||
// For now we update the master realm theme whenever we create the tenant
|
||||
updateMasterTheme(tenantUserManagementProperties.getLoginTheme());
|
||||
updateMasterDisplayName(tenantUserManagementProperties.getApplicationName());
|
||||
updateMasterTheme(tenantApplicationTypeService.getProperties(tenantRequest.getApplicationType()).getLoginTheme());
|
||||
updateMasterDisplayName(tenantApplicationTypeService.getProperties(tenantRequest.getApplicationType()).getApplicationName());
|
||||
|
||||
log.info("Tenants are: {}",
|
||||
tenantRepository.findAll()
|
||||
@ -135,6 +142,7 @@ public class TenantManagementService implements TenantProvider {
|
||||
.tenantId(tenantRequest.getTenantId())
|
||||
.displayName(tenantRequest.getDisplayName())
|
||||
.guid(UUID.randomUUID().toString())
|
||||
.applicationType(tenantRequest.getApplicationType() != null ? tenantRequest.getApplicationType() : TenantApplicationType.RedactManager)
|
||||
.databaseConnection(DatabaseConnectionEntity.builder()
|
||||
.driver(databaseConnection.getDriver())
|
||||
.host(databaseConnection.getHost())
|
||||
@ -152,7 +160,7 @@ public class TenantManagementService implements TenantProvider {
|
||||
.password(encryptionService.encrypt(searchConnection.getPassword()))
|
||||
.numberOfShards(searchConnection.getNumberOfShards())
|
||||
.numberOfReplicas(searchConnection.getNumberOfReplicas())
|
||||
.indexPrefix(buildIndexPrefix(tenantRequest.getTenantId()))
|
||||
.indexPrefix(buildIndexPrefix(tenantRequest.getTenantId(), tenantRequest.getApplicationType()))
|
||||
.build());
|
||||
MongoDBConnection mongoDBConnection = tenantRequest.getMongoDBConnection();
|
||||
if (mongoDBConnection != null) {
|
||||
@ -202,21 +210,26 @@ public class TenantManagementService implements TenantProvider {
|
||||
log.info("Skipping creation of mongo database for this tenant");
|
||||
}
|
||||
|
||||
propagateTenantToKeyCloak(tenantRequest.getTenantId(), tenantRequest.getDefaultUsers());
|
||||
propagateTenantToKeyCloak(tenantRequest.getTenantId(), tenantRequest.getApplicationType(), tenantRequest.getDefaultUsers());
|
||||
|
||||
log.info("Updated roles for tenant: {}", tenantRequest.getTenantId());
|
||||
|
||||
TenantContext.setTenantId(tenantEntity.getTenantId());
|
||||
smtpService.createDefaultSMTPConfiguration();
|
||||
|
||||
log.info("Created default SMTP configuration.");
|
||||
|
||||
var saved = tenantPersistenceService.save(tenantEntity);
|
||||
|
||||
log.info("Persisted tenant: {}", tenantRequest.getTenantId());
|
||||
|
||||
TenantContext.setTenantId(tenantEntity.getTenantId());
|
||||
rabbitTemplate.convertAndSend(tenantExchangeName, "tenant.created", new TenantCreatedEvent(tenantEntity.getTenantId()));
|
||||
TenantContext.clear();
|
||||
|
||||
log.info("Dispatched message for tenant: {}", tenantRequest.getTenantId());
|
||||
|
||||
return convert(saved);
|
||||
|
||||
} else {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "Tenant exists");
|
||||
}
|
||||
@ -273,34 +286,37 @@ public class TenantManagementService implements TenantProvider {
|
||||
try (var client = storageConfiguration.getS3StorageService().initAmazonS3(s3StorageConnection)) {
|
||||
String bucketName = s3StorageConnection.getBucketName();
|
||||
ListObjectsRequest listObjects = ListObjectsRequest.builder().bucket(bucketName).build();
|
||||
ListObjectsResponse objectList = client.listObjects(listObjects);
|
||||
for (S3Object object : objectList.contents()) {
|
||||
// Delete each object
|
||||
client.deleteObject(DeleteObjectRequest.builder().bucket(bucketName).key(object.key()).build());
|
||||
try {
|
||||
ListObjectsResponse objectList = client.listObjects(listObjects);
|
||||
for (S3Object object : objectList.contents()) {
|
||||
// Delete each object
|
||||
client.deleteObject(DeleteObjectRequest.builder().bucket(bucketName).key(object.key()).build());
|
||||
}
|
||||
DeleteBucketRequest deleteBucketRequest = DeleteBucketRequest.builder().bucket(bucketName).expectedBucketOwner(tenantId).build();
|
||||
client.deleteBucket(deleteBucketRequest);
|
||||
} catch (NoSuchBucketException noSuchBucketException) {
|
||||
log.info("The bucket did not exist and therefore did not need to be deleted.");
|
||||
}
|
||||
DeleteBucketRequest deleteBucketRequest = DeleteBucketRequest.builder().bucket(bucketName).expectedBucketOwner(tenantId).build();
|
||||
client.deleteBucket(deleteBucketRequest);
|
||||
}
|
||||
}
|
||||
log.info("Deleting mongodb database for tenant: {}", tenant.getTenantId());
|
||||
deleteMongoDBDatabase(tenant);
|
||||
deleteRealm(tenantId);
|
||||
tenantRepository.deleteById(tenant.getTenantId());
|
||||
tenantRepository.deleteByQuery(tenant.getTenantId());
|
||||
|
||||
}
|
||||
|
||||
|
||||
private String buildIndexPrefix(String tenantId) {
|
||||
private String buildIndexPrefix(String tenantId, TenantApplicationType applicationType) {
|
||||
|
||||
return tenantUserManagementProperties.getAppPrefix() + "_" + tenantId;
|
||||
return tenantApplicationTypeService.getProperties(applicationType).getAppPrefix() + "_" + tenantId;
|
||||
}
|
||||
|
||||
|
||||
private void propagateTenantToKeyCloak(String tenantId, List<TenantUser> usersToCreate) throws InterruptedException {
|
||||
private void propagateTenantToKeyCloak(String tenantId, TenantApplicationType applicationType, List<TenantUser> usersToCreate) throws InterruptedException {
|
||||
|
||||
log.info("Creating realm for tenant: {}", tenantId);
|
||||
createOrUpdateRealm(tenantId, usersToCreate);
|
||||
log.info("Created realm for tenant: {}", tenantId);
|
||||
log.info("Creating or updating realm for tenant: {}", tenantId);
|
||||
createOrUpdateRealm(tenantId, applicationType, usersToCreate);
|
||||
|
||||
var waitTime = 0;
|
||||
boolean realmReady;
|
||||
@ -316,13 +332,13 @@ public class TenantManagementService implements TenantProvider {
|
||||
} while (waitTime < MAX_WAIT_TIME);
|
||||
|
||||
if (!realmReady) {
|
||||
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to create KC realm");
|
||||
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Failed to create or update KC realm");
|
||||
}
|
||||
|
||||
setPasswordPolicyForRealm(tenantId);
|
||||
|
||||
generalConfigurationService.initGeneralConfiguration(tenantId);
|
||||
keyCloakRoleManagerService.updateRoles(tenantId);
|
||||
generalConfigurationService.initGeneralConfiguration(tenantId, applicationType);
|
||||
keyCloakRoleManagerService.updateRoles(tenantId, applicationType);
|
||||
}
|
||||
|
||||
|
||||
@ -344,7 +360,7 @@ public class TenantManagementService implements TenantProvider {
|
||||
}
|
||||
|
||||
|
||||
private void createSchema(TenantRequest tenantRequest) {
|
||||
private void createSchema(CreateTenantRequest tenantRequest) {
|
||||
|
||||
var jdbcUrl = JDBCUtils.buildJdbcUrl(tenantRequest.getDatabaseConnection());
|
||||
try (Connection connection = DriverManager.getConnection(jdbcUrl,
|
||||
@ -382,7 +398,7 @@ public class TenantManagementService implements TenantProvider {
|
||||
}
|
||||
|
||||
|
||||
private void createMongoDBDatabase(TenantRequest tenant) {
|
||||
private void createMongoDBDatabase(CreateTenantRequest tenant) {
|
||||
|
||||
MongoDBConnection mongoDBConnection = tenant.getMongoDBConnection();
|
||||
try (MongoClient mongoClient = MongoClients.create(MongoConnectionStringHelper.buildGenericMongoConnectionString(mongoDBConnection))) {
|
||||
@ -415,6 +431,7 @@ public class TenantManagementService implements TenantProvider {
|
||||
private void deleteMongoDBDatabase(TenantResponse tenant) {
|
||||
|
||||
MongoDBConnection mongoDBConnection = tenant.getMongoDBConnection();
|
||||
mongoDBConnection.setPassword(encryptionService.decrypt(mongoDBConnection.getPassword()));
|
||||
try (MongoClient mongoClient = MongoClients.create(MongoConnectionStringHelper.buildGenericMongoConnectionString(mongoDBConnection))) {
|
||||
String databaseName = mongoDBConnection.getDatabase();
|
||||
mongoClient.getDatabase(databaseName).drop();
|
||||
@ -422,9 +439,10 @@ public class TenantManagementService implements TenantProvider {
|
||||
}
|
||||
|
||||
|
||||
public void createOrUpdateRealm(String tenantId, List<TenantUser> users) {
|
||||
public void createOrUpdateRealm(String tenantId, TenantApplicationType applicationType, List<TenantUser> users) {
|
||||
|
||||
if (syncRealmIfExists(tenantId)) {
|
||||
if (syncRealmIfExists(tenantId, applicationType, users)) {
|
||||
log.info("Updated realm for tenant: {}", tenantId);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -432,12 +450,12 @@ public class TenantManagementService implements TenantProvider {
|
||||
realm.setId(tenantId);
|
||||
realm.setRealm(tenantId);
|
||||
realm.setEnabled(true);
|
||||
setRealmProperties(realm);
|
||||
setRealmProperties(realm, applicationType);
|
||||
|
||||
var clients = getRealmClients();
|
||||
var clients = getRealmClients(applicationType);
|
||||
realm.setClients(clients);
|
||||
|
||||
realm.setRoles(getRealmRoles());
|
||||
realm.setRoles(getRealmRoles(applicationType));
|
||||
|
||||
if (users != null) {
|
||||
realm.setUsers(users.stream()
|
||||
@ -446,6 +464,8 @@ public class TenantManagementService implements TenantProvider {
|
||||
}
|
||||
|
||||
keycloak.getAdminClient().realms().create(realm);
|
||||
log.info("Created realm for tenant: {}", tenantId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -453,7 +473,7 @@ public class TenantManagementService implements TenantProvider {
|
||||
|
||||
try {
|
||||
log.info("Deleting existing realms for tenant: {}", tenantId);
|
||||
keycloak.getAdminClient().realm(tenantId).remove();
|
||||
getRealmResource(tenantId).remove();
|
||||
} catch (Exception e) {
|
||||
log.warn("Could not delete realm:", e);
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Tenant deletion failed: " + e.getMessage(), e);
|
||||
@ -462,35 +482,61 @@ public class TenantManagementService implements TenantProvider {
|
||||
}
|
||||
|
||||
|
||||
private boolean syncRealmIfExists(String tenantId) {
|
||||
private boolean syncRealmIfExists(String tenantId, TenantApplicationType applicationType, List<TenantUser> users) {
|
||||
|
||||
try {
|
||||
var existingRealm = keycloak.getAdminClient().realm(tenantId).toRepresentation();
|
||||
var existingRealm = getRealmResource(tenantId).toRepresentation();
|
||||
if (existingRealm != null) {
|
||||
log.info("Updating existing realm: {}", tenantId);
|
||||
existingRealm.setLoginTheme(tenantUserManagementProperties.getDefaultTheme());
|
||||
existingRealm.setEmailTheme(tenantUserManagementProperties.getDefaultTheme());
|
||||
existingRealm.setAccountTheme(tenantUserManagementProperties.getDefaultTheme());
|
||||
existingRealm.setAccessTokenLifespan(tenantUserManagementProperties.getAccessTokenLifeSpan());
|
||||
existingRealm.setSsoSessionIdleTimeout(tenantUserManagementProperties.getSsoSessionIdleTimeout());
|
||||
var clients = getRealmClients();
|
||||
ApplicationTypeProperties applicationTypeProperties = tenantApplicationTypeService.getProperties(applicationType);
|
||||
existingRealm.setLoginTheme(applicationTypeProperties.getDefaultTheme());
|
||||
existingRealm.setEmailTheme(applicationTypeProperties.getDefaultTheme());
|
||||
existingRealm.setAccountTheme(applicationTypeProperties.getDefaultTheme());
|
||||
existingRealm.setAccessTokenLifespan(applicationTypeProperties.getAccessTokenLifeSpan());
|
||||
existingRealm.setSsoSessionIdleTimeout(applicationTypeProperties.getSsoSessionIdleTimeout());
|
||||
var clients = getRealmClients(applicationType);
|
||||
var relevantClientNames = clients.stream()
|
||||
.map(c -> c.getClientId().toLowerCase(Locale.getDefault()))
|
||||
.collect(Collectors.toSet());
|
||||
var existingClients = keycloak.getAdminClient().realm(tenantId).clients().findAll();
|
||||
var existingClients = getRealmResource(tenantId).clients().findAll();
|
||||
existingClients.forEach(ec -> {
|
||||
if (relevantClientNames.contains(ec.getClientId().toLowerCase(Locale.getDefault()))) {
|
||||
log.info("Removing client: {}", ec.getName());
|
||||
keycloak.getAdminClient().realm(tenantId).clients()
|
||||
getRealmResource(tenantId).clients()
|
||||
.get(ec.getId()).remove();
|
||||
}
|
||||
});
|
||||
|
||||
clients.forEach(c -> keycloak.getAdminClient().realm(tenantId).clients().create(c));
|
||||
clients.forEach(c -> getRealmResource(tenantId).clients().create(c));
|
||||
|
||||
existingRealm.setClients(clients);
|
||||
existingRealm.setRoles(getRealmRoles());
|
||||
keycloak.getAdminClient().realm(tenantId).update(existingRealm);
|
||||
existingRealm.setRoles(getRealmRoles(applicationType));
|
||||
|
||||
if (users != null) {
|
||||
|
||||
var userRepresentationlist = users.stream()
|
||||
.map(this::toUserRepresentation)
|
||||
.toList();
|
||||
if (existingRealm.getUsers() == null) {
|
||||
existingRealm.setUsers(new ArrayList<>());
|
||||
}
|
||||
List<UserRepresentation> toUpdate = userRepresentationlist.stream()
|
||||
.filter(existingRealm.getUsers()::contains)
|
||||
.toList();
|
||||
var toAdd = new ArrayList<>(userRepresentationlist);
|
||||
toAdd.removeAll(toUpdate);
|
||||
toAdd.forEach(user -> getRealmResource(tenantId).users().create(user));
|
||||
toUpdate.forEach(user -> getRealmResource(tenantId).users().searchByUsername(user.getUsername(), true)
|
||||
.stream()
|
||||
.findFirst()
|
||||
.ifPresent(userRepresentation -> {
|
||||
getRealmResource(tenantId).users()
|
||||
.get(userRepresentation.getId()).update(user);
|
||||
}));
|
||||
|
||||
existingRealm.getUsers().addAll(toAdd);
|
||||
}
|
||||
getRealmResource(tenantId).update(existingRealm);
|
||||
return true;
|
||||
}
|
||||
} catch (NotFoundException e) {
|
||||
@ -503,16 +549,23 @@ public class TenantManagementService implements TenantProvider {
|
||||
}
|
||||
|
||||
|
||||
private RolesRepresentation getRealmRoles() {
|
||||
private RealmResource getRealmResource(String tenantId) {
|
||||
|
||||
var allRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles();
|
||||
return keycloak.getAdminClient().realm(tenantId);
|
||||
}
|
||||
|
||||
|
||||
private RolesRepresentation getRealmRoles(TenantApplicationType applicationType) {
|
||||
|
||||
ApplicationTypeProperties applicationTypeProperties = tenantApplicationTypeService.getProperties(applicationType);
|
||||
var allRoles = applicationTypeProperties.getKcRoleMapping().getAllRoles();
|
||||
|
||||
var roles = new ArrayList<RoleRepresentation>();
|
||||
for (String applicationRole : allRoles) {
|
||||
var role = new RoleRepresentation();
|
||||
role.setComposite(true);
|
||||
role.setName(applicationRole);
|
||||
role.setContainerId(tenantUserManagementProperties.getApplicationClientId());
|
||||
role.setContainerId(applicationTypeProperties.getApplicationClientId());
|
||||
roles.add(role);
|
||||
}
|
||||
|
||||
@ -522,16 +575,18 @@ public class TenantManagementService implements TenantProvider {
|
||||
}
|
||||
|
||||
|
||||
private List<ClientRepresentation> getRealmClients() {
|
||||
private List<ClientRepresentation> getRealmClients(TenantApplicationType applicationType) {
|
||||
|
||||
ApplicationTypeProperties appTypeProperties = tenantApplicationTypeService.getProperties(applicationType);
|
||||
|
||||
var applicationClient = new ClientRepresentation();
|
||||
applicationClient.setEnabled(true);
|
||||
applicationClient.setName(tenantUserManagementProperties.getApplicationClientId());
|
||||
applicationClient.setClientId(tenantUserManagementProperties.getApplicationClientId());
|
||||
applicationClient.setName(appTypeProperties.getApplicationClientId());
|
||||
applicationClient.setClientId(appTypeProperties.getApplicationClientId());
|
||||
applicationClient.setStandardFlowEnabled(true);
|
||||
applicationClient.setImplicitFlowEnabled(true);
|
||||
applicationClient.setDirectAccessGrantsEnabled(true);
|
||||
applicationClient.setRedirectUris(tenantUserManagementProperties.getValidRedirectUris());
|
||||
applicationClient.setRedirectUris(appTypeProperties.getValidRedirectUris());
|
||||
applicationClient.setWebOrigins(List.of("+"));
|
||||
applicationClient.setPublicClient(true);
|
||||
setPostLogoutRedirectUriForClient(applicationClient);
|
||||
@ -546,7 +601,7 @@ public class TenantManagementService implements TenantProvider {
|
||||
swaggerClient.setDirectAccessGrantsEnabled(false);
|
||||
swaggerClient.setServiceAccountsEnabled(true);
|
||||
swaggerClient.setAuthorizationServicesEnabled(true);
|
||||
swaggerClient.setRedirectUris(tenantUserManagementProperties.getValidRedirectUris());
|
||||
swaggerClient.setRedirectUris(appTypeProperties.getValidRedirectUris());
|
||||
swaggerClient.setWebOrigins(List.of("+"));
|
||||
setPostLogoutRedirectUriForClient(swaggerClient);
|
||||
|
||||
@ -554,13 +609,16 @@ public class TenantManagementService implements TenantProvider {
|
||||
}
|
||||
|
||||
|
||||
private void setRealmProperties(RealmRepresentation realm) {
|
||||
private void setRealmProperties(RealmRepresentation realm, TenantApplicationType tenantApplicationType) {
|
||||
|
||||
realm.setLoginTheme(tenantUserManagementProperties.getDefaultTheme());
|
||||
realm.setEmailTheme(tenantUserManagementProperties.getDefaultTheme());
|
||||
realm.setAccountTheme(tenantUserManagementProperties.getDefaultTheme());
|
||||
realm.setAccessTokenLifespan(tenantUserManagementProperties.getAccessTokenLifeSpan());
|
||||
realm.setSsoSessionIdleTimeout(tenantUserManagementProperties.getSsoSessionIdleTimeout());
|
||||
ApplicationTypeProperties currentAppTypeProperties = tenantApplicationTypeService.getProperties(tenantApplicationType);
|
||||
realm.setLoginTheme(currentAppTypeProperties.getDefaultTheme());
|
||||
realm.setEmailTheme(currentAppTypeProperties.getDefaultTheme());
|
||||
realm.setAccountTheme(currentAppTypeProperties.getDefaultTheme());
|
||||
realm.setAccessTokenLifespan(currentAppTypeProperties.getAccessTokenLifeSpan());
|
||||
realm.setSsoSessionIdleTimeout(currentAppTypeProperties.getSsoSessionIdleTimeout());
|
||||
realm.setRevokeRefreshToken(true);
|
||||
realm.setRefreshTokenMaxReuse(currentAppTypeProperties.getRefreshTokenMaxReuse());
|
||||
|
||||
if (!ObjectUtils.isEmpty(tenantUserManagementProperties.getPublicServerUrl())) {
|
||||
Map<String, String> attributes = new HashMap<>();
|
||||
@ -615,7 +673,7 @@ public class TenantManagementService implements TenantProvider {
|
||||
user.setLastName(redUser.getLastName());
|
||||
user.setEmailVerified(true);
|
||||
|
||||
var roles = new ArrayList<String>(redUser.getRoles() != null ? redUser.getRoles() : new ArrayList<>());
|
||||
var roles = new ArrayList<>(redUser.getRoles() != null ? redUser.getRoles() : new ArrayList<>());
|
||||
roles.add("uma_authorization");
|
||||
roles.add("offline_access");
|
||||
|
||||
@ -656,7 +714,8 @@ public class TenantManagementService implements TenantProvider {
|
||||
}
|
||||
|
||||
|
||||
public TenantResponse updateTenant(String tenantId, TenantRequest tenantRequest) {
|
||||
@SneakyThrows
|
||||
public TenantResponse updateTenant(String tenantId, UpdateTenantRequest tenantRequest) {
|
||||
|
||||
if (tenantRequest.getS3StorageConnection() != null && tenantRequest.getAzureStorageConnection() != null) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Not possible to set both azure and s3 connection, please only specify one");
|
||||
@ -740,7 +799,20 @@ public class TenantManagementService implements TenantProvider {
|
||||
.build());
|
||||
}
|
||||
|
||||
return convert(tenantRepository.save(tenantEntity));
|
||||
propagateTenantToKeyCloak(tenantId, tenantEntity.getApplicationType(), null);
|
||||
|
||||
TenantResponse tenantResponse = convert(tenantRepository.save(tenantEntity));
|
||||
|
||||
log.info("Persisted tenant update: {}", tenantId);
|
||||
|
||||
TenantContext.setTenantId(tenantEntity.getTenantId());
|
||||
rabbitTemplate.convertAndSend(tenantExchangeName, "tenant.updated", tenantResponse);
|
||||
TenantContext.clear();
|
||||
|
||||
log.info("Dispatched message for tenant: {}", tenantId);
|
||||
|
||||
return tenantResponse;
|
||||
|
||||
} else {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Tenant does not exist");
|
||||
}
|
||||
@ -756,6 +828,13 @@ public class TenantManagementService implements TenantProvider {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TenantApplicationType getTenantApplicationType(String tenantId) {
|
||||
|
||||
return tenantApplicationTypeService.get(tenantId);
|
||||
}
|
||||
|
||||
|
||||
public TenantResponse removePasswords(TenantResponse tenantResponse) {
|
||||
|
||||
if (tenantResponse.getDatabaseConnection() != null) {
|
||||
@ -785,7 +864,7 @@ public class TenantManagementService implements TenantProvider {
|
||||
private TenantResponse convert(TenantEntity entity) {
|
||||
|
||||
var authDetails = realmService.getOpenIdConnectDetails(entity.getTenantId());
|
||||
var roleMapping = tenantUserManagementProperties.getKcRoleMapping();
|
||||
var roleMapping = tenantApplicationTypeService.getProperties(entity.getApplicationType()).getKcRoleMapping();
|
||||
authDetails.setClientRoles(roleMapping.getPermissions());
|
||||
authDetails.setRealmRoles(roleMapping.getAllRoles());
|
||||
|
||||
@ -795,6 +874,7 @@ public class TenantManagementService implements TenantProvider {
|
||||
.guid(entity.getGuid())
|
||||
.authDetails(authDetails)
|
||||
.details(entity.getDetails())
|
||||
.applicationType(entity.getApplicationType())
|
||||
.databaseConnection(DatabaseConnection.builder()
|
||||
.driver(entity.getDatabaseConnection().getDriver())
|
||||
.host(entity.getDatabaseConnection().getHost())
|
||||
@ -889,14 +969,15 @@ public class TenantManagementService implements TenantProvider {
|
||||
public void syncTenant(String tenantId, JsonNode payload) {
|
||||
|
||||
log.info("Syncing Realm: {}", tenantId);
|
||||
syncRealmIfExists(tenantId);
|
||||
setPasswordPolicyForRealm(tenantId);
|
||||
generalConfigurationService.initGeneralConfiguration(tenantId);
|
||||
keyCloakRoleManagerService.updateRoles(tenantId);
|
||||
propagateTenantToKeyCloak(tenantId, null);
|
||||
log.info("Realm: {} synced", tenantId);
|
||||
|
||||
TenantContext.setTenantId(tenantId);
|
||||
TenantApplicationType tenantApplicationType = getTenantApplicationType(tenantId);
|
||||
syncRealmIfExists(tenantId, tenantApplicationType, null);
|
||||
setPasswordPolicyForRealm(tenantId);
|
||||
generalConfigurationService.initGeneralConfiguration(tenantId, tenantApplicationType);
|
||||
keyCloakRoleManagerService.updateRoles(tenantId, tenantApplicationType);
|
||||
|
||||
propagateTenantToKeyCloak(tenantId, tenantApplicationType, null);
|
||||
log.info("Realm: {} synced", tenantId);
|
||||
rabbitTemplate.convertAndSend(tenantExchangeName, "tenant.sync", new TenantSyncEvent(tenantId, payload));
|
||||
TenantContext.clear();
|
||||
|
||||
|
||||
@ -14,7 +14,6 @@ import org.springframework.retry.support.RetryTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.knecon.fforesight.tenantusermanagement.model.User;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -26,7 +25,7 @@ public class UserListingService {
|
||||
|
||||
private final RealmService realmService;
|
||||
|
||||
private final TenantUserManagementProperties tenantUserManagementProperties;
|
||||
private final TenantApplicationTypeService tenantApplicationTypeService;
|
||||
private final RetryTemplate retryTemplate = RetryTemplate.builder().maxAttempts(3).exponentialBackoff(1000, 2, 5000).build();
|
||||
|
||||
|
||||
@ -41,7 +40,7 @@ public class UserListingService {
|
||||
Map<String, Set<String>> usersByRole = new HashMap<>();
|
||||
if (!allUsers.isEmpty()) {
|
||||
var realmRoles = realm.roles().list().stream().map(r -> r.getName().toUpperCase(Locale.ROOT)).collect(Collectors.toSet());
|
||||
var allRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles();
|
||||
var allRoles = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getAllRoles();
|
||||
for (var role : allRoles) {
|
||||
if (realmRoles.contains(role)) {
|
||||
List<UserRepresentation> users = realm.roles().get(role).getUserMembers(0, 500);
|
||||
@ -71,7 +70,7 @@ public class UserListingService {
|
||||
users.add(user);
|
||||
}
|
||||
|
||||
var roleComposites = tenantUserManagementProperties.getKcRoleMapping().getRoleComposites();
|
||||
var roleComposites = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getRoleComposites();
|
||||
users.forEach(user -> {
|
||||
for (var parentRole : roleComposites.keySet()) {
|
||||
if (user.getRoles().contains(parentRole)) {
|
||||
|
||||
@ -59,6 +59,7 @@ public class UserService {
|
||||
private final TenantUserManagementProperties tenantUserManagementProperties;
|
||||
private final UserListingService userListingService;
|
||||
private final RabbitTemplate rabbitTemplate;
|
||||
private final TenantApplicationTypeService tenantApplicationTypeService;
|
||||
|
||||
@Value("${fforesight.user-exchange.name}")
|
||||
private String userExchangeName;
|
||||
@ -86,7 +87,7 @@ public class UserService {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Email address format is not valid");
|
||||
}
|
||||
|
||||
tenantUserManagementProperties.getKcRoleMapping().validateRoles(user.getRoles());
|
||||
tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().validateRoles(user.getRoles());
|
||||
|
||||
UserRepresentation userRepresentation = new UserRepresentation();
|
||||
userRepresentation.setUsername(username);
|
||||
@ -130,9 +131,10 @@ public class UserService {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void checkRankOrderForAssigningRole(Set<String> newRoles, Set<String> currentUserRoles) {
|
||||
|
||||
var roleMapping = tenantUserManagementProperties.getKcRoleMapping();
|
||||
var roleMapping = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping();
|
||||
var maxRank = currentUserRoles.stream()
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.max(Integer::compare)
|
||||
@ -156,7 +158,7 @@ public class UserService {
|
||||
return userResource.roles().realmLevel().listEffective()
|
||||
.stream()
|
||||
.map(RoleRepresentation::getName)
|
||||
.filter(r -> tenantUserManagementProperties.getKcRoleMapping().isValidRole(r))
|
||||
.filter(r -> tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().isValidRole(r))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@ -166,9 +168,9 @@ public class UserService {
|
||||
|
||||
var currentUserRoles = this.getUserRoles(KeycloakSecurity.getUserId());
|
||||
|
||||
if (!userId.equalsIgnoreCase(KeycloakSecurity.getUserId()) && roles.stream()
|
||||
.anyMatch(ApplicationRoles::isKneconRole) && currentUserRoles.stream()
|
||||
.noneMatch(ApplicationRoles::isKneconRole)) {
|
||||
Set<String> oldRoles = getRoles(userId);
|
||||
if (!userId.equalsIgnoreCase(KeycloakSecurity.getUserId()) && !oldRoles.isEmpty() && oldRoles.stream()
|
||||
.allMatch(ApplicationRoles::isKneconRole)) {
|
||||
throw new NotFoundException("User with id: " + userId + " does not exist");
|
||||
}
|
||||
|
||||
@ -179,22 +181,21 @@ public class UserService {
|
||||
@CacheEvict(value = "${commons.keycloak.userCache}", allEntries = true, beforeInvocation = true)
|
||||
public User setRoles(String userId, Set<String> newRoles, Set<String> currentUserRoles) {
|
||||
|
||||
var allRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles();
|
||||
var allRoles = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getAllRoles();
|
||||
newRoles.forEach(role -> {
|
||||
|
||||
if (!allRoles.contains(role) || ApplicationRoles.isKneconRole(role) && currentUserRoles.stream()
|
||||
.noneMatch(ApplicationRoles::isKneconRole)) {
|
||||
if (!allRoles.contains(role) || ApplicationRoles.isKneconRole(role)) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid role: " + role);
|
||||
}
|
||||
});
|
||||
|
||||
var userResource = getUserResource(userId);
|
||||
var userRoles = userResource.roles().realmLevel().listEffective()
|
||||
var oldRoles = userResource.roles().realmLevel().listEffective()
|
||||
.stream()
|
||||
.map(RoleRepresentation::getName)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
validateSufficientRoles(userId, userRoles, newRoles, currentUserRoles);
|
||||
validateSufficientRoles(userId, oldRoles, newRoles, currentUserRoles);
|
||||
|
||||
var currentRolesAsRoleRepresentation = allRoles.stream()
|
||||
.map(this::getRoleRepresentation)
|
||||
@ -207,43 +208,98 @@ public class UserService {
|
||||
userResource.roles().realmLevel().add(newMappedRoles);
|
||||
|
||||
var userWithNewRoles = getUserByUsername(userResource.toRepresentation().getUsername());
|
||||
this.rabbitTemplate.convertAndSend(userExchangeName, "user.rolesUpdated", (new UserRolesUpdatedEvent(userWithNewRoles, userRoles, newRoles, KeycloakSecurity.getUserId())));
|
||||
this.rabbitTemplate.convertAndSend(userExchangeName, "user.rolesUpdated", (new UserRolesUpdatedEvent(userWithNewRoles, oldRoles, newRoles, KeycloakSecurity.getUserId())));
|
||||
|
||||
return userWithNewRoles;
|
||||
}
|
||||
|
||||
|
||||
@CacheEvict(value = "${commons.keycloak.userCache}", allEntries = true, beforeInvocation = true)
|
||||
public void removeRolesForDeletion(String userId, Set<String> roles) {
|
||||
|
||||
var allRoles = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getAllRoles();
|
||||
roles.forEach(role -> {
|
||||
|
||||
if (!allRoles.contains(role)) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Invalid role: " + role);
|
||||
}
|
||||
});
|
||||
|
||||
var userResource = getUserResource(userId);
|
||||
|
||||
var currentRolesAsRoleRepresentation = roles.stream()
|
||||
.map(this::getRoleRepresentation)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
userResource.roles().realmLevel().remove(currentRolesAsRoleRepresentation);
|
||||
}
|
||||
|
||||
|
||||
@CacheEvict(value = "${commons.keycloak.userCache}", allEntries = true, beforeInvocation = true)
|
||||
public void validateSufficientRoles(String userId, Set<String> userRoles, Set<String> newRoles, Set<String> currentUserRoles) {
|
||||
|
||||
var roleMapping = tenantUserManagementProperties.getKcRoleMapping();
|
||||
var maxRank = currentUserRoles.stream()
|
||||
var roleMapping = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping();
|
||||
|
||||
int maxCurrentUserRank = currentUserRoles.stream()
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
var newRolesRank = newRoles.stream()
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.toList();
|
||||
var maxNewRolesRank = newRolesRank.stream()
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
|
||||
var untouchableRoles = userRoles.stream()
|
||||
Set<String> untouchableRoles = userRoles.stream()
|
||||
.filter(roleMapping::isValidRole)
|
||||
.map(roleMapping::getRole)
|
||||
.filter(r -> r.getRank() > maxRank)
|
||||
.filter(r -> r.getRank() > maxCurrentUserRank && !ApplicationRoles.isKneconRole(r.getName()))
|
||||
.map(KCRole::getName)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (maxNewRolesRank > maxRank) {
|
||||
Set<String> kneconRoles = userRoles.stream()
|
||||
.filter(roleMapping::isValidRole)
|
||||
.map(roleMapping::getRole)
|
||||
.map(KCRole::getName)
|
||||
.filter(ApplicationRoles::isKneconRole)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
int maxNewRolesRank = newRoles.stream()
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
|
||||
newRoles.addAll(kneconRoles);
|
||||
|
||||
int maxNewRolesRankIncludingKnecon = newRoles.stream()
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
|
||||
ensureNoHigherRankAssigned(maxCurrentUserRank, maxNewRolesRank);
|
||||
ensureUntouchableRolesPreserved(untouchableRoles, newRoles);
|
||||
ensureHighestRankNotRemovedFromSelf(userId, maxCurrentUserRank, maxNewRolesRankIncludingKnecon, roleMapping.getMaxRank());
|
||||
}
|
||||
|
||||
|
||||
private void ensureNoHigherRankAssigned(int maxCurrentUserRank, int maxNewRolesRank) {
|
||||
|
||||
if (maxNewRolesRank > maxCurrentUserRank) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Cannot assign this role to that user. Insufficient rights");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ensureUntouchableRolesPreserved(Set<String> untouchableRoles, Set<String> newRoles) {
|
||||
|
||||
if (!newRoles.containsAll(untouchableRoles)) {
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Cannot modify some roles for this user. Insufficient rights");
|
||||
}
|
||||
}
|
||||
|
||||
if (userId.equalsIgnoreCase(KeycloakSecurity.getUserId()) && maxRank.equals(roleMapping.getMaxRank()) && !maxNewRolesRank.equals(maxRank)) {
|
||||
|
||||
private void ensureHighestRankNotRemovedFromSelf(String userId, int maxCurrentUserRank, int maxNewRolesRankIncludingKnecon, int overallMaxRank) {
|
||||
|
||||
boolean isSelf = userId.equalsIgnoreCase(KeycloakSecurity.getUserId());
|
||||
boolean isUserHighestRank = maxCurrentUserRank == overallMaxRank;
|
||||
boolean highestRankRemoved = !Integer.valueOf(maxNewRolesRankIncludingKnecon).equals(maxCurrentUserRank);
|
||||
|
||||
if (isSelf && isUserHighestRank && highestRankRemoved) {
|
||||
throw new ResponseStatusException(HttpStatus.CONFLICT, "Cannot remove highest ranking role from self.");
|
||||
}
|
||||
}
|
||||
@ -288,6 +344,10 @@ public class UserService {
|
||||
}
|
||||
|
||||
var updatedProfile = getUserByUsername(userRepresentation.getUsername());
|
||||
updatedProfile.setRoles(updatedProfile.getRoles()
|
||||
.stream()
|
||||
.filter(ApplicationRoles::isNoKneconRole)
|
||||
.collect(Collectors.toSet()));
|
||||
|
||||
this.rabbitTemplate.convertAndSend(userExchangeName, "user.ownProfileUpdated", (new UserUpdatedOwnProfileEvent(updatedProfile)));
|
||||
|
||||
@ -321,7 +381,7 @@ public class UserService {
|
||||
.realm(TenantContext.getTenantId())
|
||||
.username(username)
|
||||
.password(password)
|
||||
.clientId(tenantUserManagementProperties.getApplicationClientId())
|
||||
.clientId(tenantApplicationTypeService.getCurrentProperties().getApplicationClientId())
|
||||
.grantType(OAuth2Constants.PASSWORD)
|
||||
.resteasyClient(new ResteasyClientBuilderImpl().connectionTTL(2, TimeUnit.SECONDS)
|
||||
.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY)
|
||||
@ -382,7 +442,7 @@ public class UserService {
|
||||
var user = userListingService.convertBasicUser(userRepresentation);
|
||||
user.setRoles(getRoles(user.getUserId()));
|
||||
|
||||
var roleComposites = tenantUserManagementProperties.getKcRoleMapping().getRoleComposites();
|
||||
var roleComposites = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getRoleComposites();
|
||||
for (var parentRole : roleComposites.keySet()) {
|
||||
if (user.getRoles().contains(parentRole)) {
|
||||
user.getRoles().addAll(roleComposites.get(parentRole));
|
||||
@ -400,7 +460,7 @@ public class UserService {
|
||||
log.warn("User with id=" + id + " contains null role mappings.");
|
||||
return new TreeSet<>();
|
||||
}
|
||||
var allRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles();
|
||||
var allRoles = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getAllRoles();
|
||||
return realmMappings.stream()
|
||||
.map(RoleRepresentation::getName)
|
||||
.filter(allRoles::contains)
|
||||
@ -419,18 +479,25 @@ public class UserService {
|
||||
return;
|
||||
}
|
||||
|
||||
var status = validateExecution(KeycloakSecurity.getUserId(), userId);
|
||||
var status = validateExecutionForDeletion(KeycloakSecurity.getUserId(), userId);
|
||||
|
||||
if (status.equals(ValidationStatus.FORBIDDEN)) {
|
||||
if (status.equals(ValidationResult.FORBIDDEN)) {
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "It is not allowed to delete a user with higher ranking roles");
|
||||
} else if (status.equals(ValidationStatus.INVALID)) {
|
||||
} else if (status.equals(ValidationResult.INVALID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var userResource = getUserResource(userId);
|
||||
|
||||
var userToBeRemoved = getUserByUsername(userResource.toRepresentation().getUsername());
|
||||
userResource.remove();
|
||||
|
||||
if (status.equals(ValidationResult.ROLE_REMOVAL)) {
|
||||
removeRolesForDeletion(userId,
|
||||
getRoles(userId).stream()
|
||||
.filter(ApplicationRoles::isNoKneconRole)
|
||||
.collect(Collectors.toSet()));
|
||||
} else {
|
||||
userResource.remove();
|
||||
}
|
||||
|
||||
this.rabbitTemplate.convertAndSend(userExchangeName, "user.deleted", (new UserRemovedEvent(userToBeRemoved, KeycloakSecurity.getUserId())));
|
||||
|
||||
@ -443,8 +510,9 @@ public class UserService {
|
||||
var user = this.getUserResource(userId);
|
||||
var userRepresentation = user.toRepresentation();
|
||||
|
||||
if (getRoles(userId).stream()
|
||||
.anyMatch(ApplicationRoles::isKneconRole)) {
|
||||
Set<String> currentRoles = getRoles(userId);
|
||||
if (!userExists(userId) || !currentRoles.isEmpty() && currentRoles.stream()
|
||||
.allMatch(ApplicationRoles::isKneconRole)) {
|
||||
throw new NotFoundException("User with id: " + userId + " does not exist");
|
||||
}
|
||||
|
||||
@ -467,6 +535,10 @@ public class UserService {
|
||||
setRoles(userId, updateProfileRequest.getRoles());
|
||||
|
||||
var updatedUser = getUserByUsername(userRepresentation.getUsername());
|
||||
updatedUser.setRoles(updatedUser.getRoles()
|
||||
.stream()
|
||||
.filter(ApplicationRoles::isNoKneconRole)
|
||||
.collect(Collectors.toSet()));
|
||||
|
||||
this.rabbitTemplate.convertAndSend(userExchangeName, "user.updated", (new UserUpdatedEvent(updatedUser, KeycloakSecurity.getUserId())));
|
||||
|
||||
@ -479,9 +551,9 @@ public class UserService {
|
||||
if (!userId.equalsIgnoreCase(KeycloakSecurity.getUserId())) {
|
||||
var status = validateExecution(KeycloakSecurity.getUserId(), userId);
|
||||
|
||||
if (status.equals(ValidationStatus.FORBIDDEN)) {
|
||||
if (status.equals(ValidationResult.FORBIDDEN)) {
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "It is not allowed to activate/deactivate a user with higher ranking roles");
|
||||
} else if (status.equals(ValidationStatus.INVALID)) {
|
||||
} else if (status.equals(ValidationResult.INVALID)) {
|
||||
throw new NotFoundException("User with id: " + userId + " does not exist");
|
||||
}
|
||||
}
|
||||
@ -495,15 +567,18 @@ public class UserService {
|
||||
var currentRoles = getRoles(userId);
|
||||
|
||||
if (isActive && currentRoles.isEmpty()) { // add RED_USER role
|
||||
setRoles(userId, tenantUserManagementProperties.getKcRoleMapping().getDefaultRoles());
|
||||
setRoles(userId, tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getDefaultRoles());
|
||||
}
|
||||
|
||||
var toggledUser = getUserByUsername(userRepresentation.getUsername());
|
||||
toggledUser.setRoles(toggledUser.getRoles()
|
||||
.stream()
|
||||
.filter(ApplicationRoles::isNoKneconRole)
|
||||
.collect(Collectors.toSet()));
|
||||
|
||||
this.rabbitTemplate.convertAndSend(userExchangeName, "user.statusChanged", (new UserStatusToggleEvent(toggledUser, KeycloakSecurity.getUserId())));
|
||||
|
||||
return convert(this.getTenantUsersResource()
|
||||
.get(userId).toRepresentation());
|
||||
return toggledUser;
|
||||
}
|
||||
|
||||
|
||||
@ -512,9 +587,9 @@ public class UserService {
|
||||
if (!userId.equalsIgnoreCase(KeycloakSecurity.getUserId())) {
|
||||
var status = validateExecution(KeycloakSecurity.getUserId(), userId);
|
||||
|
||||
if (status.equals(ValidationStatus.FORBIDDEN)) {
|
||||
if (status.equals(ValidationResult.FORBIDDEN)) {
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "It is not allowed to reset the password of a user with higher ranking roles");
|
||||
} else if (status.equals(ValidationStatus.INVALID)) {
|
||||
} else if (status.equals(ValidationResult.INVALID)) {
|
||||
throw new NotFoundException("User with id: " + userId + " does not exist");
|
||||
}
|
||||
}
|
||||
@ -564,38 +639,65 @@ public class UserService {
|
||||
}
|
||||
|
||||
|
||||
private enum ValidationStatus {
|
||||
private enum ValidationResult {
|
||||
ALLOWED,
|
||||
FORBIDDEN,
|
||||
INVALID
|
||||
INVALID,
|
||||
ROLE_REMOVAL
|
||||
|
||||
}
|
||||
|
||||
|
||||
private ValidationStatus validateExecution(String executingUserId, String targetUserId) {
|
||||
private ValidationResult validateExecution(String executingUserId, String targetUserId) {
|
||||
|
||||
var currentUserResource = getUserResource(executingUserId);
|
||||
var currentRoles = getRoles(currentUserResource.toRepresentation().getId());
|
||||
var userRoles = getRoles(targetUserId);
|
||||
|
||||
if (userRoles.stream()
|
||||
.anyMatch(ApplicationRoles::isKneconRole)) {
|
||||
return ValidationStatus.INVALID;
|
||||
return validateRoleRanks(currentRoles, userRoles);
|
||||
}
|
||||
|
||||
|
||||
private ValidationResult validateExecutionForDeletion(String executingUserId, String targetUserId) {
|
||||
|
||||
var currentUserResource = getUserResource(executingUserId);
|
||||
var currentRoles = getRoles(currentUserResource.toRepresentation().getId());
|
||||
var userRoles = getRoles(targetUserId);
|
||||
|
||||
ValidationResult validationResult = validateRoleRanks(currentRoles, userRoles);
|
||||
if (validationResult == ValidationResult.ALLOWED) {
|
||||
if (userRoles.stream()
|
||||
.anyMatch(ApplicationRoles::isKneconRole) && userRoles.stream()
|
||||
.anyMatch(ApplicationRoles::isNoKneconRole)) {
|
||||
return ValidationResult.ROLE_REMOVAL;
|
||||
}
|
||||
}
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
|
||||
private ValidationResult validateRoleRanks(Set<String> currentRoles, Set<String> userRoles) {
|
||||
|
||||
if (!userRoles.isEmpty() && userRoles.stream()
|
||||
.allMatch(ApplicationRoles::isKneconRole)) {
|
||||
return ValidationResult.INVALID;
|
||||
}
|
||||
|
||||
var roleMapping = tenantUserManagementProperties.getKcRoleMapping();
|
||||
var roleMapping = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping();
|
||||
var maxRank = currentRoles.stream()
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
var targetRank = userRoles.stream()
|
||||
.filter(ApplicationRoles::isNoKneconRole)
|
||||
.map(r -> roleMapping.getRole(r).getRank())
|
||||
.max(Integer::compare)
|
||||
.orElse(-1);
|
||||
|
||||
if (targetRank <= maxRank) {
|
||||
return ValidationStatus.ALLOWED;
|
||||
return ValidationResult.ALLOWED;
|
||||
} else {
|
||||
return ValidationStatus.FORBIDDEN;
|
||||
return ValidationResult.FORBIDDEN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.utils;
|
||||
|
||||
import com.knecon.fforesight.tenantusermanagement.entity.GlobalSMTPConfigurationEntity;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SMTPConfiguration;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
@UtilityClass
|
||||
public final class SMTPConfigurationMapper {
|
||||
|
||||
public static GlobalSMTPConfigurationEntity toEntity(SMTPConfiguration smtpConfig) {
|
||||
|
||||
if (smtpConfig == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return GlobalSMTPConfigurationEntity.builder()
|
||||
.id("singleton")
|
||||
.auth(smtpConfig.isAuth())
|
||||
.envelopeFrom(smtpConfig.getEnvelopeFrom())
|
||||
.fromEmail(smtpConfig.getFrom())
|
||||
.fromDisplayName(smtpConfig.getFromDisplayName())
|
||||
.host(smtpConfig.getHost())
|
||||
.password(smtpConfig.getPassword())
|
||||
.port(smtpConfig.getPort())
|
||||
.replyTo(smtpConfig.getReplyTo())
|
||||
.replyToDisplayName(smtpConfig.getReplyToDisplayName())
|
||||
.ssl(smtpConfig.isSsl())
|
||||
.starttls(smtpConfig.isStarttls())
|
||||
.userName(smtpConfig.getUser())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
public static SMTPConfiguration toModel(GlobalSMTPConfigurationEntity entity) {
|
||||
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
SMTPConfiguration smtpConfig = new SMTPConfiguration();
|
||||
smtpConfig.setId(entity.getId());
|
||||
smtpConfig.setAuth(entity.getAuth() != null && entity.getAuth());
|
||||
smtpConfig.setEnvelopeFrom(entity.getEnvelopeFrom());
|
||||
smtpConfig.setFrom(entity.getFromEmail());
|
||||
smtpConfig.setFromDisplayName(entity.getFromDisplayName());
|
||||
smtpConfig.setHost(entity.getHost());
|
||||
smtpConfig.setPassword(entity.getPassword());
|
||||
smtpConfig.setPort(entity.getPort());
|
||||
smtpConfig.setReplyTo(entity.getReplyTo());
|
||||
smtpConfig.setReplyToDisplayName(entity.getReplyToDisplayName());
|
||||
smtpConfig.setSsl(entity.getSsl() != null && entity.getSsl());
|
||||
smtpConfig.setStarttls(entity.getStarttls() != null && entity.getStarttls());
|
||||
smtpConfig.setUser(entity.getUserName());
|
||||
|
||||
return smtpConfig;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,126 +0,0 @@
|
||||
fforesight:
|
||||
tenant-user-management:
|
||||
application-client-id: 'fforesight'
|
||||
application-name: 'Clarifynd'
|
||||
client-id: 'manager'
|
||||
accessTokenLifeSpan: 3600
|
||||
ssoSessionIdleTimeout: 86400
|
||||
realm: master
|
||||
default-theme: 'clarifynd'
|
||||
valid-redirect-uris: [ '/search/*', '/bdr-connector/*', '/sdi/*', '/tenant-user-management/*','http://localhost:4200/*', 'http://localhost:4300/*', '/ui/*' ,'/auth/*','/persistence/*', '/audit/*', '/contextual-query/*' ]
|
||||
kc-role-mapping:
|
||||
roles:
|
||||
- name: FF_USER
|
||||
set-by-default: true
|
||||
rank: 100
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-search'
|
||||
- 'fforesight-view-document'
|
||||
- 'fforesight-user-upload-files'
|
||||
- 'fforesight-user-manage-files'
|
||||
- 'fforesight-user-view-files'
|
||||
- 'fforesight-user-manage-analysis'
|
||||
- 'fforesight-user-view-analysis'
|
||||
- 'fforesight-user-view-favourites'
|
||||
- 'fforesight-user-add-to-favourites'
|
||||
- 'fforesight-user-delete-from-favourites'
|
||||
- 'fforesight-user-view-paragraph-tags'
|
||||
- 'fforesight-user-add-to-paragraph-tags'
|
||||
- 'fforesight-user-delete-from-paragraph-tags'
|
||||
- 'fforesight-read-tag'
|
||||
- 'fforesight-write-tag'
|
||||
- 'fforesight-download-file'
|
||||
- name: KNECON_ADMIN
|
||||
set-by-default: false
|
||||
rank: 1000
|
||||
permissions:
|
||||
- "red-read-license"
|
||||
- "red-update-license"
|
||||
- "fforesight-get-tenants"
|
||||
- "fforesight-create-tenant"
|
||||
- "fforesight-update-tenant"
|
||||
- "fforesight-delete-tenant"
|
||||
- "fforesight-read-users"
|
||||
- "fforesight-read-all-users"
|
||||
- "fforesight-write-users"
|
||||
- "fforesight-read-smtp-configuration"
|
||||
- "fforesight-write-smtp-configuration"
|
||||
- "fforesight-read-identity-provider-config"
|
||||
- "fforesight-write-identity-provider-config"
|
||||
- "red-unarchive-dossier"
|
||||
- name: KNECON_SUPPORT
|
||||
set-by-default: false
|
||||
rank: 1000
|
||||
permissions:
|
||||
- "red-read-license"
|
||||
- "red-update-license"
|
||||
- "fforesight-get-tenants"
|
||||
- "fforesight-create-tenant"
|
||||
- "fforesight-update-tenant"
|
||||
- "fforesight-delete-tenant"
|
||||
- "fforesight-read-users"
|
||||
- "fforesight-read-all-users"
|
||||
- "fforesight-write-users"
|
||||
- "fforesight-read-smtp-configuration"
|
||||
- "fforesight-write-smtp-configuration"
|
||||
- "fforesight-read-identity-provider-config"
|
||||
- "fforesight-write-identity-provider-config"
|
||||
- "red-unarchive-dossier"
|
||||
- name: FF_ADMIN
|
||||
set-by-default: true
|
||||
rank: 100
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- "fforesight-read-identity-provider-config"
|
||||
- "fforesight-write-identity-provider-config"
|
||||
- 'fforesight-search'
|
||||
- 'fforesight-search-audit-log'
|
||||
- 'fforesight-view-document'
|
||||
- 'fforesight-user-upload-files'
|
||||
- 'fforesight-user-manage-files'
|
||||
- 'fforesight-user-view-files'
|
||||
- 'fforesight-user-manage-analysis'
|
||||
- 'fforesight-user-view-analysis'
|
||||
- 'fforesight-user-view-favourites'
|
||||
- 'fforesight-user-add-to-favourites'
|
||||
- 'fforesight-user-view-paragraph-tags'
|
||||
- 'fforesight-user-add-to-paragraph-tags'
|
||||
- 'fforesight-user-delete-from-paragraph-tags'
|
||||
- 'fforesight-user-delete-from-favourites'
|
||||
- 'fforesight-system-upload-files'
|
||||
- 'fforesight-system-manage-files'
|
||||
- 'fforesight-system-view-files'
|
||||
- 'fforesight-system-manage-analysis'
|
||||
- 'fforesight-system-view-analysis'
|
||||
- 'fforesight-download-file'
|
||||
- 'fforesight-sdi-view-task'
|
||||
- 'fforesight-sdi-start-task'
|
||||
- 'fforesight-sdi-stop-task'
|
||||
- 'fforesight-read-tag'
|
||||
- 'fforesight-write-tag'
|
||||
- 'taas-bdr-connector-view-task'
|
||||
- 'taas-bdr-connector-start-task'
|
||||
- 'taas-bdr-connector-stop-task'
|
||||
springdoc:
|
||||
default-tenant: 'fforesight'
|
||||
|
||||
@ -1,91 +0,0 @@
|
||||
server:
|
||||
port: 8091
|
||||
|
||||
|
||||
fforesight:
|
||||
tenant-user-management:
|
||||
server-url: http://localhost:8080
|
||||
client-secret: p2InUtjQUDSlwsXyEUFuYrSWi1BeZD1P
|
||||
client-id: manager
|
||||
realm: master
|
||||
kc-role-mapping:
|
||||
roles:
|
||||
- name: SUPER_USER
|
||||
set-by-default: true
|
||||
rank: 100
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-delete-tenant'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
- name: KNECON_ADMIN
|
||||
set-by-default: true
|
||||
rank: 1000
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
- name: KNECON_SUPPORT
|
||||
set-by-default: true
|
||||
rank: 1000
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
application-name: "redaction"
|
||||
springdoc:
|
||||
auth-server-url: http://localhost:8080
|
||||
|
||||
dev.tenant.storage:
|
||||
mode: 'S3'
|
||||
s3:
|
||||
key: minioadmin
|
||||
secret: minioadmin
|
||||
bucket: redaction
|
||||
endpoint: http://localhost:9000
|
||||
|
||||
dev.tenant.db:
|
||||
port: 5432
|
||||
host: localhost
|
||||
database: master
|
||||
schema: public
|
||||
username: fforesight
|
||||
password: fforesight
|
||||
|
||||
cors.enabled: true
|
||||
93
src/main/resources/application-dev.yml
Normal file
93
src/main/resources/application-dev.yml
Normal file
@ -0,0 +1,93 @@
|
||||
server:
|
||||
port: 8091
|
||||
|
||||
|
||||
fforesight:
|
||||
tenant-user-management:
|
||||
server-url: http://localhost:8080
|
||||
client-secret: p2InUtjQUDSlwsXyEUFuYrSWi1BeZD1P
|
||||
client-id: manager
|
||||
realm: master
|
||||
application-types:
|
||||
redactmanager:
|
||||
kc-role-mapping:
|
||||
roles:
|
||||
- name: SUPER_USER
|
||||
set-by-default: true
|
||||
rank: 100
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-delete-tenant'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
- name: KNECON_ADMIN
|
||||
set-by-default: true
|
||||
rank: 1000
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
- name: KNECON_SUPPORT
|
||||
set-by-default: true
|
||||
rank: 1000
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
application-name: "redaction"
|
||||
springdoc:
|
||||
auth-server-url: http://localhost:8080
|
||||
|
||||
dev.tenant.storage:
|
||||
mode: 'S3'
|
||||
s3:
|
||||
key: minioadmin
|
||||
secret: minioadmin
|
||||
bucket: redaction
|
||||
endpoint: http://localhost:9000
|
||||
|
||||
dev.tenant.db:
|
||||
port: 5432
|
||||
host: localhost
|
||||
database: master
|
||||
schema: public
|
||||
username: fforesight
|
||||
password: fforesight
|
||||
|
||||
cors.enabled: true
|
||||
@ -1,61 +0,0 @@
|
||||
fforesight:
|
||||
tenant-user-management:
|
||||
application-client-id: 'redaction'
|
||||
application-name: 'Documine'
|
||||
client-id: 'manager'
|
||||
tenant-access-token-life-span: 300
|
||||
realm: master
|
||||
default-theme: 'scm'
|
||||
valid-redirect-uris: [ '/api/*','/redaction-gateway-v1/*','/tenant-user-management/*','http://localhost:4200/*','/ui/*' ,'/auth/*' ]
|
||||
kc-role-mapping:
|
||||
unmappedPermissions: [ "red-get-tables", "red-unarchive-dossier", "red-update-license", "fforesight-create-tenant", "fforesight-update-tenant", "red-experimental" ]
|
||||
compositeRoles:
|
||||
- name: RED_MANAGER
|
||||
composites:
|
||||
- name: RED_USER
|
||||
- name: RED_ADMIN
|
||||
composites:
|
||||
- name: RED_USER_ADMIN
|
||||
|
||||
|
||||
roles:
|
||||
- name: KNECON_ADMIN
|
||||
set-by-default: false
|
||||
rank: 1000
|
||||
permissions: [ "red-read-license", "red-update-license","fforesight-get-tenants", "fforesight-create-tenant", "fforesight-update-tenant", "fforesight-delete-tenant","fforesight-read-users", "fforesight-read-all-users", "fforesight-write-users","fforesight-read-smtp-configuration", "fforesight-write-smtp-configuration", "fforesight-read-identity-provider-config","fforesight-write-identity-provider-config", "red-unarchive-dossier", "red-use-support-controller" ]
|
||||
- name: KNECON_SUPPORT
|
||||
set-by-default: false
|
||||
rank: 1000
|
||||
permissions: [ "red-read-license", "red-update-license","fforesight-get-tenants", "fforesight-create-tenant", "fforesight-update-tenant", "fforesight-delete-tenant","fforesight-read-users", "fforesight-read-all-users", "fforesight-write-users","fforesight-read-smtp-configuration", "fforesight-write-smtp-configuration", "fforesight-read-identity-provider-config","fforesight-write-identity-provider-config", "red-unarchive-dossier", "red-use-support-controller" ]
|
||||
- name: RED_USER
|
||||
set-by-default: true
|
||||
rank: 100
|
||||
permissions: [ "red-get-rss", "red-add-comment", "red-read-license", "red-read-app-configuration", "red-read-dossier-status", "red-add-dossier-dictionary-entry", "red-add-redaction", "red-add-update-dossier-dictionary-type",
|
||||
"red-delete-comment", "red-delete-dossier-dictionary-entry", "red-delete-dossier-dictionary-type", "red-delete-file", "red-delete-manual-redaction", "red-download-annotated-file",
|
||||
"red-download-original-file", "red-download-redacted-file", "red-download-redaction-preview-file", "red-download-report-template", "red-exclude-include-file",
|
||||
"red-exclude-include-pages", "red-get-report-templates", "fforesight-manage-user-preferences", "red-manage-viewed-pages", "red-process-download", "red-process-manual-redaction-request",
|
||||
"red-read-colors", "red-read-dictionary-types", "red-read-digital-signature", "red-read-dossier", "red-read-dossier-attributes", "red-read-dossier-attributes-config",
|
||||
"red-read-dossier-templates", "red-read-download-status", "red-read-file-attributes-config", "red-read-file-status", "fforesight-read-general-configuration", "red-read-legal-basis",
|
||||
"red-read-manual-redactions", "red-read-notification", "red-read-redaction-log", "red-read-rules", "fforesight-read-users", "red-read-versions", "red-reanalyze-dossier",
|
||||
"red-reanalyze-file", "red-request-redaction", "red-rotate-page", "red-search", "red-search-audit-log", "red-set-reviewer", "red-set-status-approved", "red-set-status-under-approval",
|
||||
"fforesight-update-my-profile", "red-update-notification", "red-upload-file", "red-write-file-attributes", "red-process-texthighlights", "red-get-highlights", "red-convert-highlights", "red-delete-highlights", "red-delete-imported-redactions" ]
|
||||
- name: RED_ADMIN
|
||||
set-by-default: false
|
||||
rank: 800
|
||||
permissions: [ "red-add-dictionary-entry", "red-add-update-dictionary-type", "red-write-dossier-status", "red-read-dossier-status", "red-delete-dictionary-entry", "red-delete-dictionary-type",
|
||||
"red-delete-report-template", "red-download-report-template", "red-get-report-templates", "fforesight-manage-user-preferences", "red-read-colors", "red-read-dictionary-types",
|
||||
"red-read-digital-signature", "red-read-dossier-attributes", "red-read-dossier-attributes-config", "red-read-dossier-templates", "red-read-file-attributes-config",
|
||||
"red-read-legal-basis", "red-read-license-report", "red-read-notification", "red-read-rules", "fforesight-read-smtp-configuration", "fforesight-read-identity-provider-config", "red-read-versions", "red-reindex", "red-search-audit-log", "red-update-notification", "red-upload-report-template", "red-write-colors", "red-write-digital-signature", "red-write-dossier-attributes-config",
|
||||
"red-write-dossier-templates", "red-write-file-attributes-config", "fforesight-write-general-configuration", "red-write-legal-basis", "red-write-rules", "fforesight-write-smtp-configuration", "fforesight-write-identity-provider-config", "red-write-app-configuration", "red-manage-acl-permissions", "fforesight-create-tenant", "fforesight-get-tenants", "fforesight-update-tenant", "fforesight-deployment-info" ]
|
||||
- name: RED_MANAGER
|
||||
set-by-default: false
|
||||
rank: 200
|
||||
permissions: [ "red-add-update-dossier", "red-archived-dossier", "red-delete-dossier", "red-write-dossier-attributes" ]
|
||||
- name: RED_USER_ADMIN
|
||||
set-by-default: false
|
||||
rank: 400
|
||||
permissions: [ "fforesight-manage-user-preferences", "fforesight-read-all-users", "red-read-dossier", "red-read-app-configuration", "fforesight-read-general-configuration",
|
||||
"red-read-notification", "fforesight-read-users", "fforesight-update-my-profile", "red-update-notification", "fforesight-write-users", "red-read-license" ]
|
||||
|
||||
springdoc:
|
||||
default-tenant: 'redaction'
|
||||
@ -1,54 +0,0 @@
|
||||
server:
|
||||
port: 8091
|
||||
|
||||
|
||||
fforesight:
|
||||
tenant-user-management:
|
||||
server-url: http://localhost:8080
|
||||
client-secret: muEZIuVsAr57KsjFi4WpGJuw54RiJE0q
|
||||
client-id: manager
|
||||
realm: master
|
||||
springdoc:
|
||||
auth-server-url: http://localhost:8080
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:postgresql://${PSQL_HOST:localhost}:${PSQL_PORT:25432}/${PSQL_DATABASE:tenantmanager}?ApplicationName=${spring.application.name:}&cachePrepStmts=true&useServerPrepStmts=true&rewriteBatchedStatements=true
|
||||
driverClassName: org.postgresql.Driver
|
||||
username: ${PSQL_USERNAME:tenantmanager}
|
||||
password: ${PSQL_PASSWORD:r3dact3d}
|
||||
platform: org.hibernate.dialect.PostgreSQL95Dialect
|
||||
|
||||
cors.enabled: true
|
||||
|
||||
|
||||
|
||||
#dev.tenant.db:
|
||||
# port: 15432
|
||||
# host: localhost
|
||||
# database: red-tenant
|
||||
# schema: public
|
||||
# username: tenant
|
||||
# password: r3dact3d
|
||||
|
||||
dev.tenant.recreateTenant: true
|
||||
|
||||
dev.tenant.db:
|
||||
port: 5432
|
||||
host: syngenta-training-clone.postgres.database.azure.com
|
||||
database: syngenta-training-<YOUR_DB_COPY_NAME>
|
||||
schema: syngentatraining
|
||||
username: db_connection
|
||||
password: <DB_PASSWORD_FROM_WIKI>
|
||||
|
||||
dev.tenant.storage:
|
||||
mode: 'S3'
|
||||
s3:
|
||||
key: minioadmin
|
||||
secret: minioadmin
|
||||
bucket: redaction
|
||||
endpoint: http://localhost:9000
|
||||
# mode: 'AZURE'
|
||||
azure:
|
||||
containerName: syngenta-training-<YOUR_BLOB_COPY_NAME>
|
||||
connectionString: <AZURE_BLOB_CONNECTION_STRING_FROM_WIKI>
|
||||
@ -1,63 +0,0 @@
|
||||
fforesight:
|
||||
tenant-user-management:
|
||||
application-client-id: 'redaction'
|
||||
application-name: 'RedactManager'
|
||||
client-id: 'manager'
|
||||
tenant-access-token-life-span: 300
|
||||
realm: master
|
||||
default-theme: 'redaction'
|
||||
valid-redirect-uris: [ '/api/*','/redaction-gateway-v1/*','/tenant-user-management/*','http://localhost:4200/*','/ui/*' ,'/auth/*' ]
|
||||
kc-role-mapping:
|
||||
unmappedPermissions: [ "red-unarchive-dossier", "red-update-license", "red-get-rss","fforesight-create-tenant", "fforesight-update-tenant", "red-experimental" ]
|
||||
compositeRoles:
|
||||
- name: RED_MANAGER
|
||||
composites:
|
||||
- name: RED_USER
|
||||
- name: RED_ADMIN
|
||||
composites:
|
||||
- name: RED_USER_ADMIN
|
||||
|
||||
|
||||
roles:
|
||||
- name: RED_USER
|
||||
set-by-default: true
|
||||
rank: 100
|
||||
permissions: [ "red-add-comment", "red-read-license", "red-read-app-configuration", "red-read-dossier-status", "red-add-dossier-dictionary-entry", "red-add-redaction", "red-add-update-dossier-dictionary-type",
|
||||
"red-delete-comment", "red-delete-dossier-dictionary-entry", "red-delete-dossier-dictionary-type", "red-delete-file", "red-delete-manual-redaction", "red-download-annotated-file",
|
||||
"red-download-original-file", "red-download-redacted-file", "red-download-redaction-preview-file", "red-download-report-template", "red-exclude-include-file",
|
||||
"red-exclude-include-pages", "red-get-report-templates", "fforesight-manage-user-preferences", "red-manage-viewed-pages", "red-process-download", "red-process-manual-redaction-request",
|
||||
"red-read-colors", "red-read-dictionary-types", "red-read-digital-signature", "red-read-dossier", "red-read-dossier-attributes", "red-read-dossier-attributes-config",
|
||||
"red-read-dossier-templates", "red-read-download-status", "red-read-file-attributes-config", "red-read-file-status", "fforesight-read-general-configuration", "red-read-legal-basis",
|
||||
"red-read-manual-redactions", "red-read-notification", "red-read-redaction-log", "red-read-rules", "fforesight-read-users", "red-read-versions", "red-read-watermark", "red-reanalyze-dossier",
|
||||
"red-reanalyze-file", "red-request-redaction", "red-rotate-page", "red-search", "red-search-audit-log", "red-set-reviewer", "red-set-status-approved", "red-set-status-under-approval",
|
||||
"fforesight-update-my-profile", "red-update-notification", "red-upload-file", "red-write-file-attributes", "red-process-texthighlights", "red-get-highlights", "red-convert-highlights", "red-delete-highlights", "red-delete-imported-redactions" ]
|
||||
- name: RED_ADMIN
|
||||
set-by-default: false
|
||||
rank: 800
|
||||
permissions: [ "red-add-dictionary-entry", "red-add-update-dictionary-type", "red-write-dossier-status", "red-read-dossier-status", "red-delete-dictionary-entry", "red-delete-dictionary-type",
|
||||
"red-delete-report-template", "red-download-report-template", "red-get-report-templates", "fforesight-manage-user-preferences", "red-read-colors", "red-read-dictionary-types",
|
||||
"red-read-digital-signature", "red-read-dossier-attributes", "red-read-dossier-attributes-config", "red-read-dossier-templates", "red-read-file-attributes-config",
|
||||
"red-read-legal-basis", "red-read-license-report", "red-read-notification", "red-read-rules", "fforesight-read-smtp-configuration", "fforesight-read-identity-provider-config", "red-read-versions", "red-read-watermark",
|
||||
"red-reindex", "red-search-audit-log", "red-update-notification", "red-upload-report-template", "red-write-colors", "red-write-digital-signature", "red-write-dossier-attributes-config",
|
||||
"red-write-dossier-templates", "red-write-file-attributes-config", "fforesight-write-general-configuration", "red-write-legal-basis", "red-write-rules", "fforesight-write-smtp-configuration", "fforesight-write-identity-provider-config",
|
||||
"red-write-watermark", "red-write-app-configuration", "red-manage-acl-permissions", "fforesight-create-tenant", "fforesight-get-tenants", "fforesight-update-tenant", "fforesight-deployment-info" ]
|
||||
- name: RED_MANAGER
|
||||
set-by-default: false
|
||||
rank: 200
|
||||
permissions: [ "red-add-update-dossier", "red-archived-dossier", "red-delete-dossier", "red-write-dossier-attributes" ]
|
||||
- name: KNECON_ADMIN
|
||||
set-by-default: false
|
||||
rank: 1000
|
||||
permissions: [ "red-read-license", "red-update-license","fforesight-get-tenants", "fforesight-create-tenant", "fforesight-update-tenant", "fforesight-delete-tenant","fforesight-read-users", "fforesight-read-all-users", "fforesight-write-users","fforesight-read-smtp-configuration", "fforesight-write-smtp-configuration","red-unarchive-dossier", "red-use-support-controller" ]
|
||||
- name: KNECON_SUPPORT
|
||||
set-by-default: false
|
||||
rank: 1000
|
||||
permissions: [ "red-read-license", "red-update-license","fforesight-get-tenants", "fforesight-create-tenant", "fforesight-update-tenant", "fforesight-delete-tenant","fforesight-read-users", "fforesight-read-all-users", "fforesight-write-users","fforesight-read-smtp-configuration", "fforesight-write-smtp-configuration","red-unarchive-dossier", "red-use-support-controller" ]
|
||||
- name: RED_USER_ADMIN
|
||||
set-by-default: false
|
||||
rank: 400
|
||||
permissions: [ "fforesight-manage-user-preferences", "fforesight-read-all-users", "red-read-app-configuration", "fforesight-read-general-configuration",
|
||||
"red-read-notification", "fforesight-read-users", "fforesight-update-my-profile", "red-update-notification", "fforesight-write-users", "red-read-license" ]
|
||||
|
||||
springdoc:
|
||||
default-tenant: 'redaction'
|
||||
@ -4,6 +4,7 @@ logging.type: ${LOGGING_TYPE:CONSOLE}
|
||||
kubernetes.namespace: ${NAMESPACE:default}
|
||||
project.version: 1.0-SNAPSHOT
|
||||
|
||||
persistence-service.url: "http://persistence-service-v1:8080"
|
||||
|
||||
management:
|
||||
endpoint:
|
||||
@ -26,6 +27,9 @@ info:
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
lifecycle:
|
||||
base-package: com.knecon.fforesight.tenantusermanagement
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:postgresql://${PSQL_HOST:localhost}:${PSQL_PORT:5432}/${PSQL_DATABASE:master}?ApplicationName=${spring.application.name:}&cachePrepStmts=true&useServerPrepStmts=true&rewriteBatchedStatements=true
|
||||
@ -97,21 +101,259 @@ spring:
|
||||
password: ${REDIS_PASSWORD:}
|
||||
fforesight:
|
||||
keycloak:
|
||||
ignored-endpoints: [ '/actuator/health', '/actuator/health/**', '/tenant-user-management', '/tenant-user-management/', '/internal/**','/tenant-user-management/docs/**','/tenant-user-management/docs','/tenant-user-management/tenants/simple' ]
|
||||
ignored-endpoints: [ '/actuator/health', '/actuator/health/**', '/tenant-user-management', '/tenant-user-management/', '/internal/**','/tenant-user-management/docs/**','/tenant-user-management/docs','/actuator/prometheus' ]
|
||||
enabled: true
|
||||
springdoc:
|
||||
base-path: '/tenant-user-management'
|
||||
auth-server-url: '/auth'
|
||||
enabled: true
|
||||
default-client-id: 'swagger-ui-client'
|
||||
tenant-user-management:
|
||||
base-path: '/tenant-user-management'
|
||||
login-theme: 'redaction'
|
||||
app-prefix: 'fforesight'
|
||||
default-tenant: 'fforesight'
|
||||
tenant-exchange:
|
||||
name: 'tenants-exchange'
|
||||
user-exchange:
|
||||
name: 'users-exchange'
|
||||
tenant-user-management:
|
||||
base-path: '/tenant-user-management'
|
||||
client-id: 'manager'
|
||||
realm: master
|
||||
application-types:
|
||||
redactmanager:
|
||||
application-client-id: 'redaction'
|
||||
application-name: 'RedactManager'
|
||||
login-theme: 'redaction'
|
||||
default-theme: 'redaction'
|
||||
app-prefix: 'redaction'
|
||||
valid-redirect-uris: [ '/api/*','/redaction-gateway-v1/*','/tenant-user-management/*','http://localhost:4200/*','/ui/*' ,'/auth/*' ]
|
||||
kc-role-mapping:
|
||||
unmappedPermissions: [ "red-get-similiar-images","red-unarchive-dossier", "red-update-license", "red-get-rss","fforesight-create-tenant", "fforesight-update-tenant", "red-experimental" ]
|
||||
compositeRoles:
|
||||
- name: RED_MANAGER
|
||||
composites:
|
||||
- name: RED_USER
|
||||
- name: RED_ADMIN
|
||||
composites:
|
||||
- name: RED_USER_ADMIN
|
||||
|
||||
|
||||
roles:
|
||||
- name: RED_USER
|
||||
set-by-default: true
|
||||
rank: 100
|
||||
permissions: [ "red-add-comment", "red-get-similar-images", "red-read-license", "red-read-app-configuration", "red-read-dossier-status", "red-add-dossier-dictionary-entry", "red-add-redaction", "red-add-update-dossier-dictionary-type",
|
||||
"red-delete-comment", "red-delete-dossier-dictionary-entry", "red-delete-dossier-dictionary-type", "red-delete-file", "red-delete-manual-redaction", "red-download-annotated-file",
|
||||
"red-download-original-file", "red-download-redacted-file", "red-download-redaction-preview-file", "red-download-report-template", "red-exclude-include-file",
|
||||
"red-exclude-include-pages", "red-get-report-templates", "fforesight-manage-user-preferences", "red-manage-viewed-pages", "red-process-download", "red-process-manual-redaction-request",
|
||||
"red-read-colors", "red-read-dictionary-types", "red-read-digital-signature", "red-read-dossier", "red-read-dossier-attributes", "red-read-dossier-attributes-config",
|
||||
"red-read-dossier-templates", "red-read-download-status", "red-read-file-attributes-config", "red-read-file-status", "fforesight-read-general-configuration", "red-read-legal-basis",
|
||||
"red-read-manual-redactions", "red-read-notification", "red-read-redaction-log", "red-read-rules", "red-read-data-formats", "fforesight-read-users", "red-read-versions", "red-read-watermark", "red-reanalyze-dossier",
|
||||
"red-reanalyze-file", "red-request-redaction", "red-rotate-page", "red-search", "red-search-audit-log", "red-set-reviewer", "red-set-status-approved", "red-set-status-under-approval",
|
||||
"fforesight-update-my-profile", "red-update-notification", "red-upload-file", "red-write-file-attributes", "red-process-texthighlights", "red-get-highlights", "red-convert-highlights", "red-delete-highlights", "red-delete-imported-redactions" ]
|
||||
- name: RED_ADMIN
|
||||
set-by-default: false
|
||||
rank: 800
|
||||
permissions: [ "red-add-dictionary-entry","red-get-similar-images", "red-add-update-dictionary-type", "red-write-dossier-status", "red-read-dossier-status", "red-delete-dictionary-entry", "red-delete-dictionary-type",
|
||||
"red-delete-report-template", "red-download-report-template", "red-get-report-templates", "fforesight-manage-user-preferences", "red-read-colors", "red-read-dictionary-types",
|
||||
"red-read-digital-signature", "red-read-dossier-attributes", "red-read-dossier-attributes-config", "red-read-dossier-templates", "red-read-file-attributes-config",
|
||||
"red-read-legal-basis", "red-get-user-stats","red-read-license-report", "red-read-notification", "red-read-rules", "red-read-data-formats", "fforesight-read-smtp-configuration", "fforesight-read-identity-provider-config", "red-read-versions", "red-read-watermark",
|
||||
"red-reindex", "red-search-audit-log", "red-update-notification", "red-upload-report-template", "red-write-colors", "red-write-digital-signature", "red-write-dossier-attributes-config",
|
||||
"red-write-dossier-templates", "red-write-file-attributes-config", "fforesight-write-general-configuration", "red-write-legal-basis", "red-write-rules", "red-write-data-formats", "fforesight-write-smtp-configuration", "fforesight-write-identity-provider-config",
|
||||
"red-write-watermark", "red-write-app-configuration", "red-manage-acl-permissions", "fforesight-create-tenant", "fforesight-get-tenants", "fforesight-update-tenant", "fforesight-deployment-info" ]
|
||||
- name: RED_MANAGER
|
||||
set-by-default: false
|
||||
rank: 200
|
||||
permissions: [ "red-add-update-dossier", "red-archived-dossier", "red-delete-dossier", "red-write-dossier-attributes" ]
|
||||
- name: KNECON_ADMIN
|
||||
set-by-default: false
|
||||
rank: 1000
|
||||
permissions: [ "red-read-license", "red-get-similar-images","red-update-license","fforesight-get-tenants", "fforesight-create-tenant", "fforesight-update-tenant", "fforesight-delete-tenant","fforesight-read-users", "fforesight-read-all-users", "fforesight-write-users","fforesight-read-smtp-configuration", "fforesight-write-smtp-configuration","red-unarchive-dossier", "red-use-support-controller", "red-import-files", "red-process-download", "red-read-download-status" ]
|
||||
- name: KNECON_SUPPORT
|
||||
set-by-default: false
|
||||
rank: 1000
|
||||
permissions: [ "red-read-license", "red-get-similar-images","red-update-license","fforesight-get-tenants", "fforesight-create-tenant", "fforesight-update-tenant", "fforesight-delete-tenant","fforesight-read-users", "fforesight-read-all-users", "fforesight-write-users","fforesight-read-smtp-configuration", "fforesight-write-smtp-configuration","red-unarchive-dossier", "red-use-support-controller", "red-process-download", "red-read-download-status" ]
|
||||
- name: RED_USER_ADMIN
|
||||
set-by-default: false
|
||||
rank: 400
|
||||
permissions: [ "fforesight-manage-user-preferences", "fforesight-read-all-users", "red-read-app-configuration", "fforesight-read-general-configuration",
|
||||
"red-read-notification", "red-get-user-stats", "fforesight-read-users", "fforesight-update-my-profile", "red-update-notification", "fforesight-write-users", "red-read-license" ]
|
||||
documine:
|
||||
application-client-id: 'redaction'
|
||||
application-name: 'Documine'
|
||||
login-theme: 'scm'
|
||||
default-theme: 'scm'
|
||||
app-prefix: 'documine'
|
||||
valid-redirect-uris: [ '/api/*','/redaction-gateway-v1/*','/tenant-user-management/*','http://localhost:4200/*','/ui/*' ,'/auth/*' ]
|
||||
kc-role-mapping:
|
||||
unmappedPermissions: [ "red-get-tables", "red-unarchive-dossier", "red-update-license", "fforesight-create-tenant", "fforesight-update-tenant", "red-experimental" ]
|
||||
compositeRoles:
|
||||
- name: RED_MANAGER
|
||||
composites:
|
||||
- name: RED_USER
|
||||
- name: RED_ADMIN
|
||||
composites:
|
||||
- name: RED_USER_ADMIN
|
||||
|
||||
|
||||
roles:
|
||||
- name: KNECON_ADMIN
|
||||
set-by-default: false
|
||||
rank: 1000
|
||||
permissions: [ "red-read-license","red-update-license","fforesight-get-tenants", "fforesight-create-tenant", "fforesight-update-tenant", "fforesight-delete-tenant","fforesight-read-users", "fforesight-read-all-users", "fforesight-write-users","fforesight-read-smtp-configuration", "fforesight-write-smtp-configuration", "fforesight-read-identity-provider-config","fforesight-write-identity-provider-config", "red-unarchive-dossier", "red-use-support-controller", "red-import-files", "red-process-download", "red-read-download-status" ]
|
||||
- name: KNECON_SUPPORT
|
||||
set-by-default: false
|
||||
rank: 1000
|
||||
permissions: [ "red-read-license","red-update-license","fforesight-get-tenants", "fforesight-create-tenant", "fforesight-update-tenant", "fforesight-delete-tenant","fforesight-read-users", "fforesight-read-all-users", "fforesight-write-users","fforesight-read-smtp-configuration", "fforesight-write-smtp-configuration", "fforesight-read-identity-provider-config","fforesight-write-identity-provider-config", "red-unarchive-dossier", "red-use-support-controller", "red-process-download", "red-read-download-status" ]
|
||||
- name: RED_USER
|
||||
set-by-default: true
|
||||
rank: 100
|
||||
permissions: [ "red-get-rss", "red-add-comment", "red-get-similar-images", "red-read-license", "red-read-app-configuration", "red-read-dossier-status", "red-add-dossier-dictionary-entry", "red-add-redaction", "red-add-update-dossier-dictionary-type",
|
||||
"red-delete-comment", "red-delete-dossier-dictionary-entry", "red-delete-dossier-dictionary-type", "red-delete-file", "red-delete-manual-redaction", "red-download-annotated-file",
|
||||
"red-download-original-file", "red-download-redacted-file", "red-download-redaction-preview-file", "red-download-report-template", "red-exclude-include-file",
|
||||
"red-exclude-include-pages", "red-get-report-templates", "fforesight-manage-user-preferences", "red-manage-viewed-pages", "red-process-download", "red-process-manual-redaction-request",
|
||||
"red-read-colors", "red-read-dictionary-types", "red-read-digital-signature", "red-read-dossier", "red-read-dossier-attributes", "red-read-dossier-attributes-config",
|
||||
"red-read-dossier-templates", "red-read-download-status", "red-read-file-attributes-config", "red-read-file-status", "fforesight-read-general-configuration", "red-read-legal-basis",
|
||||
"red-read-manual-redactions", "red-read-notification", "red-read-redaction-log", "red-read-rules", "red-read-data-formats", "fforesight-read-users", "red-read-versions", "red-reanalyze-dossier",
|
||||
"red-reanalyze-file", "red-request-redaction", "red-rotate-page", "red-search", "red-search-audit-log", "red-set-reviewer", "red-set-status-approved", "red-set-status-under-approval",
|
||||
"fforesight-update-my-profile", "red-update-notification", "red-upload-file", "red-write-file-attributes", "red-process-texthighlights", "red-get-highlights", "red-convert-highlights", "red-delete-highlights", "red-delete-imported-redactions" ]
|
||||
- name: RED_ADMIN
|
||||
set-by-default: false
|
||||
rank: 800
|
||||
permissions: [ "red-add-dictionary-entry", "red-get-similar-images","red-add-update-dictionary-type", "red-write-dossier-status", "red-read-dossier-status", "red-delete-dictionary-entry", "red-delete-dictionary-type",
|
||||
"red-delete-report-template", "red-download-report-template", "red-get-report-templates", "fforesight-manage-user-preferences", "red-read-colors", "red-read-dictionary-types",
|
||||
"red-read-digital-signature", "red-read-dossier-attributes", "red-read-dossier-attributes-config", "red-read-dossier-templates", "red-read-file-attributes-config",
|
||||
"red-read-legal-basis", "red-read-license-report", "red-read-notification", "red-read-rules", "red-read-data-formats", "fforesight-read-smtp-configuration", "fforesight-read-identity-provider-config", "red-read-versions", "red-reindex", "red-search-audit-log", "red-update-notification", "red-upload-report-template", "red-write-colors", "red-write-digital-signature", "red-write-dossier-attributes-config",
|
||||
"red-write-dossier-templates", "red-write-file-attributes-config", "fforesight-write-general-configuration", "red-write-legal-basis", "red-write-rules", "red-write-data-formats", "fforesight-write-smtp-configuration", "fforesight-write-identity-provider-config", "red-write-app-configuration", "red-manage-acl-permissions", "fforesight-create-tenant", "fforesight-get-tenants", "fforesight-update-tenant", "fforesight-deployment-info" ]
|
||||
- name: RED_MANAGER
|
||||
set-by-default: false
|
||||
rank: 200
|
||||
permissions: [ "red-add-update-dossier", "red-archived-dossier", "red-delete-dossier", "red-write-dossier-attributes" ]
|
||||
- name: RED_USER_ADMIN
|
||||
set-by-default: false
|
||||
rank: 400
|
||||
permissions: [ "fforesight-manage-user-preferences", "fforesight-read-all-users", "red-read-app-configuration", "fforesight-read-general-configuration",
|
||||
"red-read-notification", "fforesight-read-users", "fforesight-update-my-profile", "red-update-notification", "fforesight-write-users", "red-read-license" ]
|
||||
clarifynd:
|
||||
application-client-id: 'fforesight'
|
||||
application-name: 'Clarifynd'
|
||||
accessTokenLifeSpan: 3600
|
||||
ssoSessionIdleTimeout: 86400
|
||||
default-theme: 'clarifynd'
|
||||
valid-redirect-uris: [ '/search/*', '/bdr-connector/*', '/sdi/*', '/tenant-user-management/*','http://localhost:4200/*', 'http://localhost:4300/*', '/ui/*' ,'/auth/*','/persistence/*', '/audit/*', '/contextual-query/*' ]
|
||||
kc-role-mapping:
|
||||
roles:
|
||||
- name: FF_USER
|
||||
set-by-default: true
|
||||
rank: 100
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-search'
|
||||
- 'fforesight-view-document'
|
||||
- 'fforesight-user-upload-files'
|
||||
- 'fforesight-user-manage-files'
|
||||
- 'fforesight-user-view-files'
|
||||
- 'fforesight-user-manage-analysis'
|
||||
- 'fforesight-user-view-analysis'
|
||||
- 'fforesight-user-view-favourites'
|
||||
- 'fforesight-user-add-to-favourites'
|
||||
- 'fforesight-user-delete-from-favourites'
|
||||
- 'fforesight-user-view-paragraph-tags'
|
||||
- 'fforesight-user-add-to-paragraph-tags'
|
||||
- 'fforesight-user-delete-from-paragraph-tags'
|
||||
- 'fforesight-read-tag'
|
||||
- 'fforesight-write-tag'
|
||||
- 'fforesight-download-file'
|
||||
- name: KNECON_ADMIN
|
||||
set-by-default: false
|
||||
rank: 1000
|
||||
permissions:
|
||||
- "red-read-license"
|
||||
- "red-update-license"
|
||||
- "red-get-similiar-images"
|
||||
- "fforesight-get-tenants"
|
||||
- "fforesight-create-tenant"
|
||||
- "fforesight-update-tenant"
|
||||
- "fforesight-delete-tenant"
|
||||
- "fforesight-read-users"
|
||||
- "fforesight-read-all-users"
|
||||
- "fforesight-write-users"
|
||||
- "fforesight-read-smtp-configuration"
|
||||
- "fforesight-write-smtp-configuration"
|
||||
- "fforesight-read-identity-provider-config"
|
||||
- "fforesight-write-identity-provider-config"
|
||||
- "red-unarchive-dossier"
|
||||
- name: KNECON_SUPPORT
|
||||
set-by-default: false
|
||||
rank: 1000
|
||||
permissions:
|
||||
- "red-read-license"
|
||||
- "red-update-license"
|
||||
- "red-get-similiar-images"
|
||||
- "fforesight-get-tenants"
|
||||
- "fforesight-create-tenant"
|
||||
- "fforesight-update-tenant"
|
||||
- "fforesight-delete-tenant"
|
||||
- "fforesight-read-users"
|
||||
- "fforesight-read-all-users"
|
||||
- "fforesight-write-users"
|
||||
- "fforesight-read-smtp-configuration"
|
||||
- "fforesight-write-smtp-configuration"
|
||||
- "fforesight-read-identity-provider-config"
|
||||
- "fforesight-write-identity-provider-config"
|
||||
- "red-unarchive-dossier"
|
||||
- name: FF_ADMIN
|
||||
set-by-default: true
|
||||
rank: 100
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- "fforesight-read-identity-provider-config"
|
||||
- "fforesight-write-identity-provider-config"
|
||||
- 'fforesight-search'
|
||||
- 'fforesight-search-audit-log'
|
||||
- 'fforesight-view-document'
|
||||
- 'fforesight-user-upload-files'
|
||||
- 'fforesight-user-manage-files'
|
||||
- 'fforesight-user-view-files'
|
||||
- 'fforesight-user-manage-analysis'
|
||||
- 'fforesight-user-view-analysis'
|
||||
- 'fforesight-user-view-favourites'
|
||||
- 'fforesight-user-add-to-favourites'
|
||||
- 'fforesight-user-view-paragraph-tags'
|
||||
- 'fforesight-user-add-to-paragraph-tags'
|
||||
- 'fforesight-user-delete-from-paragraph-tags'
|
||||
- 'fforesight-user-delete-from-favourites'
|
||||
- 'fforesight-system-upload-files'
|
||||
- 'fforesight-system-manage-files'
|
||||
- 'fforesight-system-view-files'
|
||||
- 'fforesight-system-manage-analysis'
|
||||
- 'fforesight-system-view-analysis'
|
||||
- 'fforesight-download-file'
|
||||
- 'fforesight-sdi-view-task'
|
||||
- 'fforesight-sdi-start-task'
|
||||
- 'fforesight-sdi-stop-task'
|
||||
- 'fforesight-read-tag'
|
||||
- 'fforesight-write-tag'
|
||||
- 'taas-bdr-connector-view-task'
|
||||
- 'taas-bdr-connector-start-task'
|
||||
- 'taas-bdr-connector-stop-task'
|
||||
springdoc:
|
||||
swagger-ui:
|
||||
path: ${fforesight.springdoc.base-path}/docs/swagger-ui
|
||||
|
||||
@ -15,3 +15,7 @@ databaseChangeLog:
|
||||
file: db/changelog/master/8-tenant-connection-data-string-length.changelog.yaml
|
||||
- include:
|
||||
file: db/changelog/master/9-add-mongodb-connection-columns.yaml
|
||||
- include:
|
||||
file: db/changelog/master/10-add-application-type-to-tenant.yaml
|
||||
- include:
|
||||
file: db/changelog/master/11-add-global-smtp-config.yaml
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
databaseChangeLog:
|
||||
- property: # this will be used as a default if no environment variable is present
|
||||
name: FFORESIGHT_TENANT_USER_MANAGEMENT_APPLICATION_NAME
|
||||
value: "RedactManager"
|
||||
- changeSet:
|
||||
id: add-application-type-to-tenant
|
||||
author: maverick
|
||||
changes:
|
||||
- addColumn:
|
||||
columns:
|
||||
- column:
|
||||
name: application_type
|
||||
type: VARCHAR(255)
|
||||
tableName: tenant
|
||||
- update:
|
||||
tableName: tenant
|
||||
columns:
|
||||
- column:
|
||||
name: application_type
|
||||
value: ${FFORESIGHT_TENANT_USER_MANAGEMENT_APPLICATION_NAME}
|
||||
@ -0,0 +1,51 @@
|
||||
databaseChangeLog:
|
||||
- changeSet:
|
||||
id: add-global-smtp-config-table
|
||||
author: dom
|
||||
changes:
|
||||
- createTable:
|
||||
tableName: global_smtp_configuration
|
||||
columns:
|
||||
- column:
|
||||
name: id
|
||||
type: VARCHAR(255)
|
||||
constraints:
|
||||
nullable: false
|
||||
primaryKey: true
|
||||
primaryKeyName: global_smtp_configuration_pkey
|
||||
- column:
|
||||
name: auth
|
||||
type: BOOLEAN
|
||||
- column:
|
||||
name: envelope_from
|
||||
type: VARCHAR(255)
|
||||
- column:
|
||||
name: from_email
|
||||
type: VARCHAR(255)
|
||||
- column:
|
||||
name: from_display_name
|
||||
type: VARCHAR(255)
|
||||
- column:
|
||||
name: host
|
||||
type: VARCHAR(255)
|
||||
- column:
|
||||
name: password
|
||||
type: VARCHAR(255)
|
||||
- column:
|
||||
name: port
|
||||
type: INTEGER
|
||||
- column:
|
||||
name: reply_to
|
||||
type: VARCHAR(255)
|
||||
- column:
|
||||
name: reply_to_display_name
|
||||
type: VARCHAR(255)
|
||||
- column:
|
||||
name: ssl
|
||||
type: BOOLEAN
|
||||
- column:
|
||||
name: starttls
|
||||
type: BOOLEAN
|
||||
- column:
|
||||
name: user_name
|
||||
type: VARCHAR(255)
|
||||
@ -1,6 +1,14 @@
|
||||
package com.knecon.fforesight.tenantusermanagement;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.amqp.rabbit.core.RabbitAdmin;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
|
||||
@ -16,6 +24,12 @@ import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.Feature;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.FeatureType;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.License;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.RedactionLicenseModel;
|
||||
import com.knecon.fforesight.tenantcommons.queue.TenantMessagingConfiguration;
|
||||
import com.knecon.fforesight.tenantusermanagement.client.LicenseClient;
|
||||
import com.knecon.fforesight.tenantusermanagement.feigntestclients.external.TenantsClient;
|
||||
import com.knecon.fforesight.tenantusermanagement.feigntestclients.internal.InternalTenantsClient;
|
||||
import com.knecon.fforesight.tenantusermanagement.testcontainers.KeyCloakTestContainer;
|
||||
@ -29,11 +43,8 @@ import com.knecon.fforesight.tenantusermanagement.utils.TokenService;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@EnableFeignClients(basePackageClasses = {TenantsClient.class, InternalTenantsClient.class})
|
||||
@EnableFeignClients(basePackageClasses = {TenantsClient.class, InternalTenantsClient.class, LicenseClient.class})
|
||||
@Import(AbstractTenantUserManagementIntegrationTest.TestConfiguration.class)
|
||||
@ContextConfiguration(initializers = {AbstractTenantUserManagementIntegrationTest.Initializer.class})
|
||||
@SpringBootTest(classes = TenantUserManagementServiceApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
|
||||
@ -47,12 +58,37 @@ public class AbstractTenantUserManagementIntegrationTest {
|
||||
protected TestTenantService testTenantService;
|
||||
@Autowired
|
||||
protected TokenService tokenService;
|
||||
@MockBean
|
||||
protected LicenseClient licenseClient;
|
||||
@MockBean
|
||||
protected RabbitAdmin rabbitAdmin;
|
||||
@MockBean
|
||||
protected RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry;
|
||||
@MockBean
|
||||
protected TenantMessagingConfiguration tenantMessagingConfiguration;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void createTestTenant() {
|
||||
|
||||
testTenantService.createTestTenantIfNotExists(TEST_TENANT_ID, minioPort);
|
||||
prepareLicense();
|
||||
}
|
||||
|
||||
|
||||
private void prepareLicense() {
|
||||
|
||||
RedactionLicenseModel redactionLicenseModel = new RedactionLicenseModel();
|
||||
redactionLicenseModel.setActiveLicense("1");
|
||||
License license = new License();
|
||||
license.setId("1");
|
||||
Feature feature = new Feature();
|
||||
feature.setName("configurableSMTPServer");
|
||||
feature.setType(FeatureType.BOOLEAN);
|
||||
feature.setValue(true);
|
||||
license.setFeatures(List.of(feature));
|
||||
redactionLicenseModel.setLicenses(List.of(license));
|
||||
when(licenseClient.getLicense()).thenReturn(redactionLicenseModel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,15 +1,27 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.tests;
|
||||
|
||||
import static com.knecon.fforesight.tenantusermanagement.service.EnvironmentSMTPConfigurationProvider.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.Feature;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.FeatureType;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.License;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.license.RedactionLicenseModel;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantusermanagement.AbstractTenantUserManagementIntegrationTest;
|
||||
import com.knecon.fforesight.tenantusermanagement.feigntestclients.external.SMTPConfigurationClient;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SMTPConfiguration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import feign.FeignException;
|
||||
|
||||
public class SMTPConfigurationTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
|
||||
@ -17,6 +29,22 @@ public class SMTPConfigurationTest extends AbstractTenantUserManagementIntegrati
|
||||
private SMTPConfigurationClient smtpConfigurationClient;
|
||||
|
||||
|
||||
private void prepareLicense() {
|
||||
|
||||
RedactionLicenseModel redactionLicenseModel = new RedactionLicenseModel();
|
||||
redactionLicenseModel.setActiveLicense("1");
|
||||
License license = new License();
|
||||
license.setId("1");
|
||||
Feature feature = new Feature();
|
||||
feature.setName("configurableSMTPServer");
|
||||
feature.setType(FeatureType.BOOLEAN);
|
||||
feature.setValue(false);
|
||||
license.setFeatures(List.of(feature));
|
||||
redactionLicenseModel.setLicenses(List.of(license));
|
||||
when(licenseClient.getLicense()).thenReturn(redactionLicenseModel);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSMTPConfiguration() {
|
||||
|
||||
@ -59,6 +87,58 @@ public class SMTPConfigurationTest extends AbstractTenantUserManagementIntegrati
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDefaultSMTPConfiguration() {
|
||||
|
||||
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
|
||||
|
||||
smtpConfigurationClient.clearSMTPConfiguration();
|
||||
|
||||
System.setProperty(SMTP_DEFAULT_HOST, "smtp.example.com");
|
||||
System.setProperty(SMTP_DEFAULT_PORT, "587");
|
||||
System.setProperty(SMTP_DEFAULT_SENDER_EMAIL, "no-reply@example.com");
|
||||
System.setProperty(SMTP_DEFAULT_SENDER_NAME, "No Reply");
|
||||
System.setProperty(SMTP_DEFAULT_REPLY_EMAIL, "support@example.com");
|
||||
System.setProperty(SMTP_DEFAULT_REPLY_NAME, "Support Team");
|
||||
System.setProperty(SMTP_DEFAULT_SENDER_ENVELOPE, "envelope@example.com");
|
||||
System.setProperty(SMTP_DEFAULT_SSL, "true");
|
||||
System.setProperty(SMTP_DEFAULT_STARTTLS, "true");
|
||||
System.setProperty(SMTP_DEFAULT_AUTH, "true");
|
||||
|
||||
String newTenant = "NEW_TENANT";
|
||||
testTenantService.createTestTenantWithoutStorageIfNotExist(newTenant);
|
||||
TenantContext.setTenantId(newTenant);
|
||||
|
||||
var currentSMTPConfiguration = smtpConfigurationClient.getCurrentSMTPConfiguration();
|
||||
|
||||
assertThat(currentSMTPConfiguration.getHost()).isEqualTo("smtp.example.com");
|
||||
assertThat(currentSMTPConfiguration.getPort()).isEqualTo(587);
|
||||
assertThat(currentSMTPConfiguration.getReplyTo()).isEqualTo("support@example.com");
|
||||
assertThat(currentSMTPConfiguration.getReplyToDisplayName()).isEqualTo("Support Team");
|
||||
assertThat(currentSMTPConfiguration.getFrom()).isEqualTo("no-reply@example.com");
|
||||
assertThat(currentSMTPConfiguration.getFromDisplayName()).isEqualTo("No Reply");
|
||||
assertThat(currentSMTPConfiguration.getEnvelopeFrom()).isEqualTo("envelope@example.com");
|
||||
assertThat(currentSMTPConfiguration.isAuth()).isTrue();
|
||||
assertThat(currentSMTPConfiguration.isSsl()).isTrue();
|
||||
assertThat(currentSMTPConfiguration.isStarttls()).isTrue();
|
||||
|
||||
TenantContext.clear();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testChangeSMTPConfigurationWhenLicenseFlagIsFalse() {
|
||||
|
||||
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
|
||||
|
||||
prepareLicense();
|
||||
var error = assertThrows(FeignException.class, () -> smtpConfigurationClient.updateSMTPConfiguration(provideTestSMTPConfiguration()));
|
||||
assertTrue(error.getMessage().contains("Current license does not allow updating the SMTP configuration!"));
|
||||
|
||||
TenantContext.clear();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSMTPConnection() {
|
||||
|
||||
@ -72,4 +152,23 @@ public class SMTPConfigurationTest extends AbstractTenantUserManagementIntegrati
|
||||
TenantContext.clear();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSMTPwithoutPassword() {
|
||||
|
||||
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
|
||||
|
||||
SMTPConfiguration smtpConfiguration = new SMTPConfiguration();
|
||||
smtpConfiguration.setFrom("from@knecon.com");
|
||||
smtpConfiguration.setHost("test.knecon.com");
|
||||
|
||||
smtpConfigurationClient.updateSMTPConfiguration(smtpConfiguration);
|
||||
|
||||
var current = smtpConfigurationClient.getCurrentSMTPConfiguration();
|
||||
|
||||
assertThat(current.getPassword()).matches("\\**");
|
||||
|
||||
TenantContext.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,353 @@
|
||||
package com.knecon.fforesight.tenantusermanagement.tests;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.quality.Strictness.LENIENT;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService;
|
||||
import com.knecon.fforesight.tenantusermanagement.entity.GlobalSMTPConfigurationEntity;
|
||||
import com.knecon.fforesight.tenantusermanagement.entity.TenantEntity;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SMTPConfiguration;
|
||||
import com.knecon.fforesight.tenantusermanagement.repository.TenantRepository;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.EnvironmentSMTPConfigurationProvider;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.GlobalSMTPConfigurationPersistenceService;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.RealmService;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.SMTPService;
|
||||
|
||||
@MockitoSettings(strictness = LENIENT)
|
||||
@ExtendWith(org.mockito.junit.jupiter.MockitoExtension.class)
|
||||
public class SMTPServiceTest {
|
||||
|
||||
public static final String NEW_SMTP_HOST = "new.smtp.host";
|
||||
public static final int NEW_SMTP_PORT = 465;
|
||||
public static final String NEW_SMTP_USER = "newUser";
|
||||
public static final String NEW_SMTP_PASSWORD = "newPassword";
|
||||
public static final String OLD_SMTP_HOST = "old.smtp.host";
|
||||
public static final int OLD_SMTP_PORT = 587;
|
||||
public static final String OLD_SMTP_USER = "globalUser";
|
||||
public static final String OLD_SMTP_PASSWORD = "oldPassword";
|
||||
public static final String FFORESIGHT_SMTP_PASSWORD = "FFORESIGHT_SMTP_PASSWORD";
|
||||
|
||||
@Mock
|
||||
private GlobalSMTPConfigurationPersistenceService smtpConfigurationPersistenceService;
|
||||
|
||||
@Mock
|
||||
private EnvironmentSMTPConfigurationProvider environmentSMTPConfigurationProvider;
|
||||
|
||||
@Mock
|
||||
private RealmService realmService;
|
||||
|
||||
@Mock
|
||||
private TenantRepository tenantRepository;
|
||||
|
||||
@Mock
|
||||
private EncryptionDecryptionService encryptionDecryptionService;
|
||||
|
||||
@InjectMocks
|
||||
private SMTPService smtpService;
|
||||
|
||||
private SMTPConfiguration oldGlobalConfig;
|
||||
private SMTPConfiguration overriddenConfig;
|
||||
private List<TenantEntity> tenantEntities;
|
||||
private final static String DEFAULT_PASSWORD = "**********";
|
||||
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
|
||||
smtpService = new SMTPService(smtpConfigurationPersistenceService,
|
||||
environmentSMTPConfigurationProvider,
|
||||
null,
|
||||
realmService,
|
||||
tenantRepository,
|
||||
encryptionDecryptionService,
|
||||
new ObjectMapper());
|
||||
|
||||
oldGlobalConfig = new SMTPConfiguration();
|
||||
oldGlobalConfig.setId("singleton");
|
||||
oldGlobalConfig.setHost(OLD_SMTP_HOST);
|
||||
oldGlobalConfig.setPort(OLD_SMTP_PORT);
|
||||
oldGlobalConfig.setUser(OLD_SMTP_USER);
|
||||
oldGlobalConfig.setPassword(OLD_SMTP_PASSWORD);
|
||||
|
||||
overriddenConfig = new SMTPConfiguration();
|
||||
overriddenConfig.setHost("custom.smtp.host");
|
||||
overriddenConfig.setPort(2525);
|
||||
overriddenConfig.setUser("customUser");
|
||||
overriddenConfig.setPassword("encrypted_customPassword");
|
||||
|
||||
TenantEntity tenant1 = new TenantEntity();
|
||||
tenant1.setTenantId("tenant1");
|
||||
|
||||
TenantEntity tenant2 = new TenantEntity();
|
||||
tenant2.setTenantId("tenant2");
|
||||
|
||||
TenantEntity tenant3 = new TenantEntity();
|
||||
tenant3.setTenantId("tenant3");
|
||||
|
||||
tenantEntities = Arrays.asList(tenant1, tenant2, tenant3);
|
||||
when(tenantRepository.findAll()).thenReturn(tenantEntities);
|
||||
|
||||
GlobalSMTPConfigurationEntity globalEntity = new GlobalSMTPConfigurationEntity();
|
||||
globalEntity.setHost(oldGlobalConfig.getHost());
|
||||
globalEntity.setPort(oldGlobalConfig.getPort());
|
||||
globalEntity.setUserName(oldGlobalConfig.getUser());
|
||||
globalEntity.setPassword(oldGlobalConfig.getPassword());
|
||||
when(smtpConfigurationPersistenceService.get()).thenReturn(Optional.of(globalEntity));
|
||||
|
||||
for (TenantEntity tenant : tenantEntities) {
|
||||
RealmResource tenantRealmResource = mock(RealmResource.class);
|
||||
when(realmService.realm(tenant.getTenantId())).thenReturn(tenantRealmResource);
|
||||
}
|
||||
|
||||
when(encryptionDecryptionService.encrypt(ArgumentMatchers.<String>any())).thenAnswer(invocation -> {
|
||||
String argument = invocation.getArgument(0);
|
||||
return argument != null ? "encrypted_" + argument : null;
|
||||
});
|
||||
|
||||
when(encryptionDecryptionService.decrypt(anyString())).thenAnswer(invocation -> {
|
||||
String encrypted = invocation.getArgument(0);
|
||||
if (encrypted.startsWith("encrypted_")) {
|
||||
return encrypted.substring("encrypted_".length());
|
||||
}
|
||||
return encrypted;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSynchronizeSMTPConfigurations() {
|
||||
|
||||
for (TenantEntity tenant : tenantEntities) {
|
||||
RealmResource tenantRealmResource = mock(RealmResource.class);
|
||||
when(realmService.realm(tenant.getTenantId())).thenReturn(tenantRealmResource);
|
||||
// for this test also mock toRepresentation
|
||||
RealmRepresentation realm = getRealmRepresentation(tenant, overriddenConfig, oldGlobalConfig);
|
||||
when(tenantRealmResource.toRepresentation()).thenReturn(realm);
|
||||
}
|
||||
|
||||
SMTPConfiguration newEnvConfig = new SMTPConfiguration();
|
||||
newEnvConfig.setId("singleton");
|
||||
newEnvConfig.setHost(NEW_SMTP_HOST);
|
||||
newEnvConfig.setPort(NEW_SMTP_PORT);
|
||||
newEnvConfig.setUser(NEW_SMTP_USER);
|
||||
newEnvConfig.setPassword(NEW_SMTP_PASSWORD);
|
||||
when(environmentSMTPConfigurationProvider.get()).thenReturn(newEnvConfig);
|
||||
|
||||
smtpService.synchronizeSMTPConfigurations();
|
||||
|
||||
ArgumentCaptor<GlobalSMTPConfigurationEntity> globalConfigCaptor = ArgumentCaptor.forClass(GlobalSMTPConfigurationEntity.class);
|
||||
verify(smtpConfigurationPersistenceService).createUpdate(globalConfigCaptor.capture());
|
||||
|
||||
GlobalSMTPConfigurationEntity updatedGlobalConfig = globalConfigCaptor.getValue();
|
||||
assertEquals(NEW_SMTP_HOST, updatedGlobalConfig.getHost());
|
||||
assertEquals(NEW_SMTP_PORT, updatedGlobalConfig.getPort());
|
||||
assertEquals(NEW_SMTP_USER, updatedGlobalConfig.getUserName());
|
||||
assertEquals("encrypted_" + NEW_SMTP_PASSWORD, updatedGlobalConfig.getPassword());
|
||||
|
||||
// Verify that tenant1 and tenant3 were not updated, and tenant2 was
|
||||
for (TenantEntity tenant : tenantEntities) {
|
||||
RealmResource tenantRealmResource = realmService.realm(tenant.getTenantId());
|
||||
|
||||
if ("tenant1".equals(tenant.getTenantId()) || "tenant3".equals(tenant.getTenantId())) {
|
||||
// Verify that update() was called once for tenant1 and tenant3
|
||||
verify(tenantRealmResource, times(1)).update(any(RealmRepresentation.class));
|
||||
|
||||
ArgumentCaptor<RealmRepresentation> realmCaptor = ArgumentCaptor.forClass(RealmRepresentation.class);
|
||||
verify(tenantRealmResource).update(realmCaptor.capture());
|
||||
|
||||
RealmRepresentation updatedRealm = realmCaptor.getValue();
|
||||
Map<String, String> smtpServer = updatedRealm.getSmtpServer();
|
||||
smtpServer.putAll(updatedRealm.getAttributes());
|
||||
assertEquals(NEW_SMTP_HOST, smtpServer.get("host"));
|
||||
assertEquals(String.valueOf(NEW_SMTP_PORT), smtpServer.get("port"));
|
||||
assertEquals(NEW_SMTP_USER, smtpServer.get("user"));
|
||||
assertEquals("encrypted_" + NEW_SMTP_PASSWORD, smtpServer.get(FFORESIGHT_SMTP_PASSWORD));
|
||||
assertEquals(NEW_SMTP_PASSWORD, smtpServer.get("password"));
|
||||
} else if ("tenant2".equals(tenant.getTenantId())) {
|
||||
// Verify that update() was never called for tenant2
|
||||
verify(tenantRealmResource, never()).update(any(RealmRepresentation.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSynchronizeSMTPConfigurationsWithoutGlobalChanges() {
|
||||
|
||||
SMTPConfiguration newEnvConfig = new SMTPConfiguration();
|
||||
newEnvConfig.setId("singleton");
|
||||
newEnvConfig.setHost(OLD_SMTP_HOST);
|
||||
newEnvConfig.setPort(OLD_SMTP_PORT);
|
||||
newEnvConfig.setUser(OLD_SMTP_USER);
|
||||
newEnvConfig.setPassword(OLD_SMTP_PASSWORD);
|
||||
when(environmentSMTPConfigurationProvider.get()).thenReturn(newEnvConfig);
|
||||
|
||||
smtpService.synchronizeSMTPConfigurations();
|
||||
|
||||
verify(smtpConfigurationPersistenceService, never()).createUpdate(any(GlobalSMTPConfigurationEntity.class));
|
||||
|
||||
// Verify that all tenants are unchanged
|
||||
for (TenantEntity tenant : tenantEntities) {
|
||||
RealmResource tenantRealmResource = realmService.realm(tenant.getTenantId());
|
||||
|
||||
verify(tenantRealmResource, never()).update(any(RealmRepresentation.class));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testInitializeGlobalSMTPConfiguration() {
|
||||
|
||||
|
||||
TenantEntity tenant1 = new TenantEntity();
|
||||
tenant1.setTenantId("tenant1");
|
||||
|
||||
TenantEntity tenant2 = new TenantEntity();
|
||||
tenant2.setTenantId("tenant2");
|
||||
|
||||
List<TenantEntity> tenantEntities = Arrays.asList(tenant1, tenant2);
|
||||
|
||||
when(tenantRepository.findAll()).thenReturn(tenantEntities);
|
||||
|
||||
when(smtpConfigurationPersistenceService.get()).thenReturn(Optional.empty());
|
||||
|
||||
String host = "global.smtp.host";
|
||||
int port = 25;
|
||||
String globalUser = "globalUser";
|
||||
String globalPassword = "globalPassword";
|
||||
|
||||
SMTPConfiguration currentGlobalConfig = new SMTPConfiguration();
|
||||
currentGlobalConfig.setId("singleton");
|
||||
currentGlobalConfig.setHost(host);
|
||||
currentGlobalConfig.setPort(port);
|
||||
currentGlobalConfig.setUser(globalUser);
|
||||
currentGlobalConfig.setPassword(globalPassword);
|
||||
|
||||
when(environmentSMTPConfigurationProvider.get()).thenReturn(currentGlobalConfig);
|
||||
|
||||
// Tenant1: Predefined SMTP configuration
|
||||
RealmResource tenantRealmResource1 = mock(RealmResource.class);
|
||||
when(realmService.realm("tenant1")).thenReturn(tenantRealmResource1);
|
||||
RealmRepresentation realmRepresentation1 = getRealmRepresentationPredefined();
|
||||
|
||||
when(tenantRealmResource1.toRepresentation()).thenReturn(realmRepresentation1);
|
||||
|
||||
// Tenant2: No SMTP configuration
|
||||
RealmResource tenantRealmResource2 = mock(RealmResource.class);
|
||||
when(realmService.realm("tenant2")).thenReturn(tenantRealmResource2);
|
||||
RealmRepresentation realmRepresentation2 = new RealmRepresentation();
|
||||
|
||||
Map<String, String> smtpServer2 = new HashMap<>();
|
||||
smtpServer2.put("host", "");
|
||||
realmRepresentation2.setSmtpServer(smtpServer2);
|
||||
realmRepresentation2.setAttributes(new HashMap<>());
|
||||
|
||||
when(tenantRealmResource2.toRepresentation()).thenReturn(realmRepresentation2);
|
||||
|
||||
smtpService.synchronizeSMTPConfigurations();
|
||||
|
||||
ArgumentCaptor<GlobalSMTPConfigurationEntity> globalConfigCaptor = ArgumentCaptor.forClass(GlobalSMTPConfigurationEntity.class);
|
||||
verify(smtpConfigurationPersistenceService).createUpdate(globalConfigCaptor.capture());
|
||||
|
||||
GlobalSMTPConfigurationEntity updatedGlobalConfig = globalConfigCaptor.getValue();
|
||||
assertEquals(host, updatedGlobalConfig.getHost());
|
||||
assertEquals(port, updatedGlobalConfig.getPort());
|
||||
assertEquals(globalUser, updatedGlobalConfig.getUserName());
|
||||
String encryptedGlobalPassword = "encrypted_" + globalPassword;
|
||||
assertEquals(encryptedGlobalPassword, updatedGlobalConfig.getPassword());
|
||||
|
||||
// Verify that tenant1's SMTP configuration remains unchanged
|
||||
verify(tenantRealmResource1, never()).update(any(RealmRepresentation.class));
|
||||
|
||||
// Verify that tenant2's SMTP configuration is updated
|
||||
ArgumentCaptor<RealmRepresentation> realmCaptor2 = ArgumentCaptor.forClass(RealmRepresentation.class);
|
||||
verify(tenantRealmResource2, times(1)).update(realmCaptor2.capture());
|
||||
|
||||
RealmRepresentation updatedRealm2 = realmCaptor2.getValue();
|
||||
Map<String, String> updatedSmtpServer2 = updatedRealm2.getSmtpServer();
|
||||
|
||||
assertEquals(host, updatedSmtpServer2.get("host"));
|
||||
assertEquals(String.valueOf(port), updatedSmtpServer2.get("port"));
|
||||
assertEquals(globalUser, updatedSmtpServer2.get("user"));
|
||||
assertEquals(globalPassword, updatedSmtpServer2.get("password"));
|
||||
|
||||
Map<String, String> updatedAttributes2 = updatedRealm2.getAttributes();
|
||||
assertEquals(encryptedGlobalPassword, updatedAttributes2.get(FFORESIGHT_SMTP_PASSWORD));
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
private static RealmRepresentation getRealmRepresentationPredefined() {
|
||||
|
||||
RealmRepresentation realmRepresentation1 = new RealmRepresentation();
|
||||
|
||||
Map<String, String> smtpServer1 = new HashMap<>();
|
||||
smtpServer1.put("host", "predefined.smtp.host");
|
||||
smtpServer1.put("port", "587");
|
||||
smtpServer1.put("user", "user1");
|
||||
smtpServer1.put("password", DEFAULT_PASSWORD);
|
||||
Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put(FFORESIGHT_SMTP_PASSWORD, "encrypted_predefined_pass");
|
||||
|
||||
realmRepresentation1.setSmtpServer(smtpServer1);
|
||||
realmRepresentation1.setAttributes(attributes);
|
||||
return realmRepresentation1;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
private static RealmRepresentation getRealmRepresentation(TenantEntity tenant, SMTPConfiguration overriddenConfig, SMTPConfiguration oldGlobalConfig) {
|
||||
|
||||
RealmRepresentation realm = new RealmRepresentation();
|
||||
Map<String, String> smtpMap = new HashMap<>();
|
||||
smtpMap.put("password", DEFAULT_PASSWORD);
|
||||
Map<String, String> attributes = new HashMap<>();
|
||||
|
||||
if ("tenant2".equals(tenant.getTenantId())) {
|
||||
// tenant2 has overridden SMTP config
|
||||
smtpMap.put("host", overriddenConfig.getHost());
|
||||
smtpMap.put("port", String.valueOf(overriddenConfig.getPort()));
|
||||
smtpMap.put("user", overriddenConfig.getUser());
|
||||
attributes.put(FFORESIGHT_SMTP_PASSWORD, overriddenConfig.getPassword());
|
||||
|
||||
} else {
|
||||
// tenant1 and tenant3 have SMTP config matching global
|
||||
smtpMap.put("host", oldGlobalConfig.getHost());
|
||||
smtpMap.put("port", String.valueOf(oldGlobalConfig.getPort()));
|
||||
smtpMap.put("user", oldGlobalConfig.getUser());
|
||||
attributes.put(FFORESIGHT_SMTP_PASSWORD, oldGlobalConfig.getPassword());
|
||||
|
||||
}
|
||||
realm.setSmtpServer(smtpMap);
|
||||
|
||||
realm.setAttributes(attributes);
|
||||
return realm;
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,8 +17,8 @@ public class StartupTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
@Test
|
||||
public void testStartup() {
|
||||
|
||||
var simpleTenants = internalTenantsClient.getSimpleTenants();
|
||||
assertThat(simpleTenants).isNotEmpty();
|
||||
var tenants = internalTenantsClient.getTenants();
|
||||
assertThat(tenants).isNotEmpty();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,8 @@ import com.knecon.fforesight.tenantcommons.model.SearchConnection;
|
||||
import com.knecon.fforesight.tenantusermanagement.AbstractTenantUserManagementIntegrationTest;
|
||||
import com.knecon.fforesight.tenantusermanagement.feigntestclients.external.TenantsClient;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SearchConnectionRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.CreateTenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.UpdateTenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.RealmService;
|
||||
import com.knecon.fforesight.tenantusermanagement.utils.TestTenantService;
|
||||
|
||||
@ -68,8 +69,7 @@ public class TenantsTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
testTenantService.createTestTenantIfNotExists(tenantId, minioPort);
|
||||
TenantContext.setTenantId(tenantId);
|
||||
|
||||
var tenantRequest = TenantRequest.builder()
|
||||
.tenantId(tenantId)
|
||||
var tenantRequest = UpdateTenantRequest.builder()
|
||||
.displayName("updated_display_name")
|
||||
.searchConnection(SearchConnectionRequest.builder()
|
||||
.numberOfReplicas("1")
|
||||
@ -159,8 +159,7 @@ public class TenantsTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
testTenantService.createTestTenantIfNotExists("new_tenant", minioPort);
|
||||
TenantContext.setTenantId("new_tenant");
|
||||
|
||||
var tenantRequest = TenantRequest.builder()
|
||||
.tenantId("new_tenant")
|
||||
var tenantRequest = UpdateTenantRequest.builder()
|
||||
.s3StorageConnection(S3StorageConnection.builder()
|
||||
.key("updated_key")
|
||||
.bucketName("updated_bucket")
|
||||
@ -184,8 +183,7 @@ public class TenantsTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
testTenantService.createTestTenantWithoutStorageIfNotExist("new_tenant_without_storage");
|
||||
TenantContext.setTenantId("new_tenant_without_storage");
|
||||
|
||||
var tenantRequest = TenantRequest.builder()
|
||||
.tenantId("new_tenant_without_storage")
|
||||
var tenantRequest = UpdateTenantRequest.builder()
|
||||
.azureStorageConnection(AzureStorageConnection.builder().connectionString("updated_connection").containerName("updated_container").build())
|
||||
.build();
|
||||
|
||||
@ -202,8 +200,7 @@ public class TenantsTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
testTenantService.createTestTenantIfNotExists("new_tenant", minioPort);
|
||||
TenantContext.setTenantId("new_tenant");
|
||||
|
||||
var tenantRequest = TenantRequest.builder()
|
||||
.tenantId("new_tenant")
|
||||
var tenantRequest = UpdateTenantRequest.builder()
|
||||
.azureStorageConnection(AzureStorageConnection.builder().connectionString("updated_connection").containerName("updated_container").build())
|
||||
.s3StorageConnection(S3StorageConnection.builder()
|
||||
.key("updated_key")
|
||||
@ -228,8 +225,7 @@ public class TenantsTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
testTenantService.createTestTenantIfNotExists("new_tenant_with_s3", minioPort);
|
||||
TenantContext.setTenantId("new_tenant_with_s3");
|
||||
|
||||
var tenantRequest = TenantRequest.builder()
|
||||
.tenantId("new_tenant_with_s3")
|
||||
var tenantRequest = UpdateTenantRequest.builder()
|
||||
.azureStorageConnection(AzureStorageConnection.builder().connectionString("updated_connection").containerName("updated_container").build())
|
||||
.build();
|
||||
|
||||
|
||||
@ -9,11 +9,13 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.admin.client.resource.UsersResource;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
@ -26,8 +28,12 @@ import com.knecon.fforesight.tenantusermanagement.model.UpdateProfileRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.User;
|
||||
import com.knecon.fforesight.tenantusermanagement.permissions.ApplicationRoles;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.RealmService;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.TenantApplicationTypeService;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.UserService;
|
||||
|
||||
import feign.FeignException;
|
||||
import lombok.NonNull;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
@ -35,9 +41,18 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
@Autowired
|
||||
private UserClient userClient;
|
||||
|
||||
@Autowired
|
||||
private RealmService realmService;
|
||||
|
||||
@Autowired
|
||||
private TenantUserManagementProperties tenantUserManagementProperties;
|
||||
|
||||
@Autowired
|
||||
private TenantApplicationTypeService tenantApplicationTypeService;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
|
||||
@Test
|
||||
public void testUsers() {
|
||||
@ -72,7 +87,7 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
assertThat(testUser.getLastName()).isEqualTo("updateTestLastName");
|
||||
assertThat(testUser.getFirstName()).isEqualTo("updateTestFirstName");
|
||||
|
||||
Set<String> allButKneconRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles()
|
||||
Set<String> allButKneconRoles = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getAllRoles()
|
||||
.stream()
|
||||
.filter(ApplicationRoles::isNoKneconRole)
|
||||
.collect(Collectors.toSet());
|
||||
@ -290,7 +305,7 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
createUserRequest.setFirstName("Test");
|
||||
createUserRequest.setLastName("New User");
|
||||
createUserRequest.setUsername("TestUserName");
|
||||
createUserRequest.setRoles(tenantUserManagementProperties.getKcRoleMapping().getAllRoles());
|
||||
createUserRequest.setRoles(tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getAllRoles());
|
||||
FeignException e = assertThrows(FeignException.class, () -> userClient.createUser(createUserRequest));
|
||||
assertEquals(400, e.status());
|
||||
|
||||
@ -301,7 +316,7 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
public void testCreateUserWithExistingUser() {
|
||||
|
||||
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
|
||||
Set<String> allButKneconRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles()
|
||||
Set<String> allButKneconRoles = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getAllRoles()
|
||||
.stream()
|
||||
.filter(ApplicationRoles::isNoKneconRole)
|
||||
.collect(Collectors.toSet());
|
||||
@ -371,7 +386,7 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
tokenService.setUser("admin@knecon.com", "secret");
|
||||
|
||||
// different role sets and subsets
|
||||
var allRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles();
|
||||
var allRoles = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getAllRoles();
|
||||
Set<String> allButKneconRoles = allRoles.stream()
|
||||
.filter(ApplicationRoles::isNoKneconRole)
|
||||
.collect(Collectors.toSet());
|
||||
@ -386,24 +401,24 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
createUserRequest.setFirstName("All");
|
||||
createUserRequest.setLastName("Roles");
|
||||
createUserRequest.setUsername("AllRoles");
|
||||
createUserRequest.setRoles(allRoles);
|
||||
User user = userClient.createUser(createUserRequest);
|
||||
addRoles(user.getUserId(), allRoles);
|
||||
|
||||
var createUserRequest2 = new CreateUserRequest();
|
||||
createUserRequest2.setEmail("nokneconroles@notknecon.com");
|
||||
createUserRequest2.setFirstName("No Knecon");
|
||||
createUserRequest2.setLastName("Roles");
|
||||
createUserRequest2.setUsername("NoKneconRoles");
|
||||
createUserRequest2.setRoles(allButKneconRoles);
|
||||
User noKneconUser = userClient.createUser(createUserRequest2);
|
||||
addRoles(noKneconUser.getUserId(), allButKneconRoles);
|
||||
|
||||
var createUserRequest3 = new CreateUserRequest();
|
||||
createUserRequest3.setEmail("onlykneconroles@notknecon.com");
|
||||
createUserRequest3.setFirstName("Only Knecon");
|
||||
createUserRequest3.setLastName("Roles");
|
||||
createUserRequest3.setUsername("OnlyKneconRoles");
|
||||
createUserRequest3.setRoles(onlyKneconRoles);
|
||||
User onlyKneconUser = userClient.createUser(createUserRequest3);
|
||||
addRoles(onlyKneconUser.getUserId(), onlyKneconRoles);
|
||||
|
||||
var allUsers = userClient.getAllUsers(true);
|
||||
|
||||
@ -480,9 +495,13 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
tokenService.setUser("red-user-admin@knecon.com", "Secret@secured!23");
|
||||
|
||||
// we should not be able to set roles of this user at all as it is not visible to us resulting in a 404
|
||||
e = assertThrows(FeignException.class, () -> userClient.setRoles(user.getUserId(), onlyKneconRoles));
|
||||
e = assertThrows(FeignException.class, () -> userClient.setRoles(onlyKneconUser.getUserId(), allButKneconRoles));
|
||||
assertEquals(404, e.status());
|
||||
|
||||
// we can not assign a knecon rule as it is not visible to us
|
||||
e = assertThrows(FeignException.class, () -> userClient.setRoles(user.getUserId(), onlyKneconRoles));
|
||||
assertEquals(400, e.status());
|
||||
|
||||
// we should not be able to assign ourselves a knecon role as it is not visible to us
|
||||
e = assertThrows(FeignException.class, () -> userClient.setRoles(redUserAdmin.getUserId(), allRoles));
|
||||
assertEquals(400, e.status());
|
||||
@ -490,59 +509,103 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
// authenticate as knecon admin again
|
||||
tokenService.setUser("admin@knecon.com", "secret");
|
||||
|
||||
// this should be possible because we now have knecon roles
|
||||
userClient.setRoles(onlyKneconUser.getUserId(), allRoles);
|
||||
assertEquals(userClient.getUserById(onlyKneconUser.getUserId()).getRoles().size(), 2);
|
||||
// this should still not be possible
|
||||
e = assertThrows(FeignException.class, () -> userClient.setRoles(onlyKneconUser.getUserId(), allRoles));
|
||||
assertEquals(404, e.status());
|
||||
|
||||
// and this as well
|
||||
userClient.setRoles(user.getUserId(), allRoles);
|
||||
// and also not this
|
||||
e = assertThrows(FeignException.class, () -> userClient.setRoles(user.getUserId(), allRoles));
|
||||
assertEquals(400, e.status());
|
||||
|
||||
// we can also poll the user
|
||||
userClient.getUserById(user.getUserId());
|
||||
|
||||
e = assertThrows(FeignException.class, () -> userClient.getUserById(onlyKneconUser.getUserId()));
|
||||
assertEquals(404, e.status());
|
||||
|
||||
// back to having no rights
|
||||
tokenService.setUser("red-user-admin@knecon.com", "Secret@secured!23");
|
||||
|
||||
// we can not call update profile
|
||||
e = assertThrows(FeignException.class, () -> userClient.updateProfile(user.getUserId(), new UpdateProfileRequest()));
|
||||
e = assertThrows(FeignException.class, () -> userClient.updateProfile(onlyKneconUser.getUserId(), new UpdateProfileRequest()));
|
||||
assertEquals(404, e.status());
|
||||
|
||||
// or reset password
|
||||
e = assertThrows(FeignException.class, () -> userClient.resetPassword(user.getUserId(), new ResetPasswordRequest()));
|
||||
e = assertThrows(FeignException.class, () -> userClient.resetPassword(onlyKneconUser.getUserId(), new ResetPasswordRequest()));
|
||||
assertEquals(404, e.status());
|
||||
|
||||
// now as a knecon admin again
|
||||
tokenService.setUser("admin@knecon.com", "secret");
|
||||
|
||||
// we can also not see another knecon account and change their password
|
||||
e = assertThrows(FeignException.class, () -> userClient.resetPassword(user.getUserId(), new ResetPasswordRequest()));
|
||||
e = assertThrows(FeignException.class, () -> userClient.resetPassword(onlyKneconUser.getUserId(), new ResetPasswordRequest()));
|
||||
assertEquals(404, e.status());
|
||||
|
||||
// or activate the profile
|
||||
e = assertThrows(FeignException.class, () -> userClient.activateProfile(user.getUserId(), true));
|
||||
e = assertThrows(FeignException.class, () -> userClient.activateProfile(onlyKneconUser.getUserId(), true));
|
||||
assertEquals(404, e.status());
|
||||
|
||||
// but the user with all roles can be processed
|
||||
userClient.resetPassword(user.getUserId(), new ResetPasswordRequest("Secret@secured!23", false));
|
||||
User activated = userClient.activateProfile(user.getUserId(), true);
|
||||
activated.getRoles()
|
||||
.stream()
|
||||
.noneMatch(ApplicationRoles::isKneconRole);
|
||||
|
||||
// we create a new user with all roles
|
||||
var createUserRequest4 = new CreateUserRequest();
|
||||
createUserRequest4.setEmail("allroles2@knecon.com");
|
||||
createUserRequest4.setFirstName("All");
|
||||
createUserRequest4.setLastName("Roles2");
|
||||
createUserRequest4.setUsername("AllRoles2");
|
||||
createUserRequest4.setRoles(allRoles);
|
||||
User user4 = userClient.createUser(createUserRequest4);
|
||||
addRoles(user4.getUserId(), allRoles);
|
||||
|
||||
// we attempt to delete it
|
||||
userClient.deleteUser(user4.getUserId());
|
||||
// we attempt to delete it, should not be possible but still return 204
|
||||
userClient.deleteUser(onlyKneconUser.getUserId());
|
||||
|
||||
// and again using the bulk call
|
||||
userClient.deleteUsers(List.of(user4.getUserId()));
|
||||
userClient.deleteUsers(List.of(onlyKneconUser.getUserId()));
|
||||
|
||||
// no rights again ...
|
||||
tokenService.setUser("red-user-admin@knecon.com", "Secret@secured!23");
|
||||
|
||||
// with this user we expect a 204 as well
|
||||
userClient.deleteUser(onlyKneconUser.getUserId());
|
||||
|
||||
userClient.deleteUsers(List.of(onlyKneconUser.getUserId()));
|
||||
|
||||
// check users as knecon admin again
|
||||
tokenService.setUser("admin@knecon.com", "secret");
|
||||
|
||||
// with this user we expect a 204 as well but the user should have removed red roles
|
||||
userClient.deleteUser(user4.getUserId());
|
||||
|
||||
addRoles(onlyKneconUser.getUserId(), allRoles);
|
||||
allUsers = userClient.getAllUsers(true);
|
||||
assertTrue(allUsers.stream()
|
||||
.anyMatch(u -> u.getUserId().equals(user4.getUserId())));
|
||||
// and should not have changed
|
||||
var user5 = userClient.getUserById(user4.getUserId());
|
||||
assertEquals(user4, user5);
|
||||
.anyMatch(u -> u.getUserId().equals(onlyKneconUser.getUserId())));
|
||||
|
||||
// hence, 404 when trying to get the user now
|
||||
e = assertThrows(FeignException.class, () -> userClient.getUserById(user4.getUserId()));
|
||||
assertEquals(404, e.status());
|
||||
// give the user the old roles back
|
||||
addRoles(user4.getUserId(), allButKneconRoles);
|
||||
|
||||
allUsers = userClient.getAllUsers(true);
|
||||
var user4AfterShenanigansOpt = allUsers.stream()
|
||||
.filter(u -> u.getUserId().equals(user4.getUserId()))
|
||||
.findFirst();
|
||||
assertTrue(user4AfterShenanigansOpt.isPresent());
|
||||
user4AfterShenanigansOpt.get().setRoles(new HashSet<>());
|
||||
assertEquals(user4AfterShenanigansOpt.get(), user4);
|
||||
|
||||
var stillOnlyKneconUserOpt = allUsers.stream()
|
||||
.filter(u -> u.getUserId().equals(onlyKneconUser.getUserId()))
|
||||
.findFirst();
|
||||
assertTrue(stillOnlyKneconUserOpt.isPresent());
|
||||
stillOnlyKneconUserOpt.get().setRoles(new HashSet<>());
|
||||
assertEquals(stillOnlyKneconUserOpt.get(), onlyKneconUser);
|
||||
|
||||
}
|
||||
|
||||
@ -555,7 +618,7 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
tokenService.setUser("admin@knecon.com", "secret");
|
||||
|
||||
// different role sets and subsets
|
||||
var allRoles = tenantUserManagementProperties.getKcRoleMapping().getAllRoles();
|
||||
var allRoles = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getAllRoles();
|
||||
|
||||
// create several users with different roles for testing
|
||||
var createUserRequest = new CreateUserRequest();
|
||||
@ -563,8 +626,8 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
createUserRequest.setFirstName("Some Other");
|
||||
createUserRequest.setLastName("User");
|
||||
createUserRequest.setUsername("SomeOtherUser");
|
||||
createUserRequest.setRoles(allRoles);
|
||||
User user = userClient.createUser(createUserRequest);
|
||||
addRoles(user.getUserId(), allRoles);
|
||||
|
||||
var createUserRequest2 = new CreateUserRequest();
|
||||
createUserRequest2.setEmail("noroles@notknecon.com");
|
||||
@ -587,6 +650,36 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testOperationsOnUserWithoutRoles() {
|
||||
|
||||
// set context and user
|
||||
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
|
||||
tokenService.setUser("admin@knecon.com", "secret");
|
||||
|
||||
var createUserRequest = new CreateUserRequest();
|
||||
createUserRequest.setEmail("noroles@notknecon.com");
|
||||
createUserRequest.setFirstName("No");
|
||||
createUserRequest.setLastName("Roles");
|
||||
createUserRequest.setUsername("NoRolesAtAll");
|
||||
createUserRequest.setRoles(new HashSet<>());
|
||||
User noRolesUser = userClient.createUser(createUserRequest);
|
||||
|
||||
userClient.resetPassword(noRolesUser.getUserId(), ResetPasswordRequest.builder().password("SuperSecret42!!").build());
|
||||
|
||||
userClient.activateProfile(noRolesUser.getUserId(), false);
|
||||
noRolesUser = userClient.getUserById(noRolesUser.getUserId());
|
||||
assertFalse(noRolesUser.isActive());
|
||||
|
||||
var allUsers = userClient.getAllUsers(true);
|
||||
var sizeBefore = allUsers.size();
|
||||
userClient.deleteUser(noRolesUser.getUserId());
|
||||
allUsers = userClient.getAllUsers(true);
|
||||
assertThat(allUsers).hasSize(sizeBefore - 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCreateUserWithInvalidEmailFormat() {
|
||||
|
||||
@ -623,4 +716,141 @@ public class UserTest extends AbstractTenantUserManagementIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUpdateProfileForUserWithAllRoles() {
|
||||
|
||||
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
|
||||
tokenService.setUser("admin@knecon.com", "secret");
|
||||
|
||||
var allRoles = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getAllRoles();
|
||||
Set<String> allButKneconRoles = allRoles.stream()
|
||||
.filter(ApplicationRoles::isNoKneconRole)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
CreateUserRequest createUserRequest = new CreateUserRequest();
|
||||
createUserRequest.setEmail("all.roles.user@knecon.com");
|
||||
createUserRequest.setUsername("all.roles.user@knecon.com");
|
||||
createUserRequest.setFirstName("All");
|
||||
createUserRequest.setLastName("Roles");
|
||||
|
||||
var allRolesuser = userClient.createUser(createUserRequest);
|
||||
addRoles(allRolesuser.getUserId(), allRoles);
|
||||
assertThat(allRolesuser).isNotNull();
|
||||
|
||||
UpdateProfileRequest updateProfileRequest = UpdateProfileRequest.builder()
|
||||
.email("all.roles.user@knecon.com")
|
||||
.firstName("All")
|
||||
.lastName("NewLastName")
|
||||
.roles(allButKneconRoles)
|
||||
.build();
|
||||
|
||||
var updatedUser = userClient.updateProfile(allRolesuser.getUserId(), updateProfileRequest);
|
||||
|
||||
assertThat(updatedUser).isNotNull();
|
||||
assertThat(updatedUser.getLastName()).isEqualTo("NewLastName");
|
||||
|
||||
tokenService.setUser("test@fforesight.com", "secret");
|
||||
|
||||
updateProfileRequest.setLastName("AnotherNewLastName");
|
||||
updatedUser = userClient.updateProfile(allRolesuser.getUserId(), updateProfileRequest);
|
||||
|
||||
assertThat(updatedUser).isNotNull();
|
||||
assertThat(updatedUser.getLastName()).isEqualTo("AnotherNewLastName");
|
||||
|
||||
createUserRequest.setEmail("less.super.user.1@knecon.com");
|
||||
createUserRequest.setUsername(createUserRequest.getEmail());
|
||||
createUserRequest.setRoles(Set.of("LESS_SUPER_USER"));
|
||||
var lessSuperUser = userClient.createUser(createUserRequest);
|
||||
|
||||
userClient.resetPassword(lessSuperUser.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!23").build());
|
||||
tokenService.setUser("less.super.user.1@knecon.com", "Secret@secured!23");
|
||||
|
||||
FeignException feignException = assertThrows(FeignException.class, () -> userClient.updateProfile(allRolesuser.getUserId(), updateProfileRequest));
|
||||
assertEquals(400, feignException.status());
|
||||
assertTrue(feignException.getMessage().contains("Cannot assign this role to that user. Insufficient rights"));
|
||||
|
||||
tokenService.setUser("admin@knecon.com", "secret");
|
||||
userClient.deleteUser(lessSuperUser.getUserId());
|
||||
userClient.deleteUser(allRolesuser.getUserId());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeleteKneconRolesUserAsNormalAdmin() {
|
||||
|
||||
TenantContext.setTenantId(AbstractTenantUserManagementIntegrationTest.TEST_TENANT_ID);
|
||||
tokenService.setUser("admin@knecon.com", "secret");
|
||||
|
||||
var allRoles = tenantApplicationTypeService.getCurrentProperties().getKcRoleMapping().getAllRoles();
|
||||
Set<String> allButKneconRoles = allRoles.stream()
|
||||
.filter(ApplicationRoles::isNoKneconRole)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
CreateUserRequest createUserRequest = new CreateUserRequest();
|
||||
createUserRequest.setEmail("normalAdmin@knecon.com");
|
||||
createUserRequest.setUsername("normalAdmin@knecon.com");
|
||||
createUserRequest.setFirstName("Mister");
|
||||
createUserRequest.setLastName("Admin");
|
||||
|
||||
var adminUser = userClient.createUser(createUserRequest);
|
||||
addRoles(adminUser.getUserId(), allButKneconRoles);
|
||||
assertThat(adminUser).isNotNull();
|
||||
|
||||
createUserRequest = new CreateUserRequest();
|
||||
createUserRequest.setEmail("kneconAdmin@knecon.com");
|
||||
createUserRequest.setUsername("kneconAdmin@knecon.com");
|
||||
createUserRequest.setFirstName("Knecon");
|
||||
createUserRequest.setLastName("Admin");
|
||||
|
||||
var kneconAdminuser = userClient.createUser(createUserRequest);
|
||||
addRoles(kneconAdminuser.getUserId(), allRoles);
|
||||
assertThat(kneconAdminuser).isNotNull();
|
||||
|
||||
userClient.resetPassword(adminUser.getUserId(), ResetPasswordRequest.builder().password("Secret@secured!23").build());
|
||||
tokenService.setUser("normalAdmin@knecon.com", "Secret@secured!23");
|
||||
|
||||
userClient.deleteUser(kneconAdminuser.getUserId());
|
||||
|
||||
List<User> allUsers = userClient.getAllUsers(true);
|
||||
assertTrue(allUsers.stream()
|
||||
.noneMatch(u -> u.getUserId().equals(kneconAdminuser.getUserId())));
|
||||
List<User> unfilteredUsers = userService.getAllUsers();
|
||||
assertTrue(unfilteredUsers.stream()
|
||||
.anyMatch(u -> u.getUserId().equals(kneconAdminuser.getUserId())));
|
||||
|
||||
tokenService.setUser("admin@knecon.com", "secret");
|
||||
userClient.deleteUser(adminUser.getUserId());
|
||||
}
|
||||
|
||||
|
||||
private UsersResource getTenantUsersResource() {
|
||||
|
||||
return realmService.realm(TenantContext.getTenantId()).users();
|
||||
}
|
||||
|
||||
|
||||
private UserResource getUserResource(String userId) {
|
||||
|
||||
return this.getTenantUsersResource()
|
||||
.get(userId);
|
||||
}
|
||||
|
||||
|
||||
private RoleRepresentation getRoleRepresentation(String role) {
|
||||
|
||||
return realmService.realm(TenantContext.getTenantId()).roles()
|
||||
.get(role).toRepresentation();
|
||||
}
|
||||
|
||||
|
||||
private void addRoles(String userId, Set<String> roles) {
|
||||
|
||||
getUserResource(userId).roles()
|
||||
.realmLevel()
|
||||
.add(roles.stream()
|
||||
.map(this::getRoleRepresentation)
|
||||
.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -4,6 +4,8 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
@ -13,18 +15,21 @@ import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.TenantApplicationType;
|
||||
import com.knecon.fforesight.tenantusermanagement.AbstractTenantUserManagementIntegrationTest;
|
||||
import com.knecon.fforesight.tenantusermanagement.feigntestclients.external.TenantsClient;
|
||||
import com.knecon.fforesight.tenantusermanagement.feigntestclients.internal.InternalTenantsClient;
|
||||
import com.knecon.fforesight.tenantusermanagement.TenantUserManagementServiceApplication;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.KeyCloakRoleManagerService;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.RealmService;
|
||||
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
|
||||
@Disabled
|
||||
@ActiveProfiles(profiles = "taas")
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@EnableFeignClients(basePackageClasses = {TenantsClient.class, InternalTenantsClient.class})
|
||||
@ -47,8 +52,7 @@ public class TenantSyncUtils {
|
||||
KeyCloakRoleManagerService keyCloakRoleManagerService;
|
||||
|
||||
|
||||
// @Test
|
||||
// @Disabled
|
||||
@Test
|
||||
public void syncTenant() {
|
||||
|
||||
var adminClient = KeycloakBuilder.builder()
|
||||
@ -58,17 +62,17 @@ public class TenantSyncUtils {
|
||||
.clientSecret(CLIENT_SECRET)
|
||||
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
|
||||
.resteasyClient(new ResteasyClientBuilderImpl().connectionTTL(2, TimeUnit.SECONDS)
|
||||
.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY)
|
||||
.connectionPoolSize(10)
|
||||
.disableTrustManager()
|
||||
.build())
|
||||
.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY)
|
||||
.connectionPoolSize(10)
|
||||
.disableTrustManager()
|
||||
.build())
|
||||
.build();
|
||||
|
||||
var realm = adminClient.realm(REALM);
|
||||
|
||||
when(realmService.realm(REALM)).thenReturn(realm);
|
||||
|
||||
keyCloakRoleManagerService.updateRoles(REALM);
|
||||
keyCloakRoleManagerService.updateRoles(REALM, TenantApplicationType.RedactManager);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import java.util.UUID;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.TenantApplicationType;
|
||||
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
|
||||
import com.knecon.fforesight.tenantusermanagement.feigntestclients.external.TenantsClient;
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
@ -18,7 +19,7 @@ import com.knecon.fforesight.tenantcommons.model.DatabaseConnection;
|
||||
import com.knecon.fforesight.tenantcommons.model.S3StorageConnection;
|
||||
import com.knecon.fforesight.tenantusermanagement.api.internal.InternalTenantsResource;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.SearchConnectionRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.CreateTenantRequest;
|
||||
import com.knecon.fforesight.tenantusermanagement.model.TenantUser;
|
||||
import com.knecon.fforesight.tenantusermanagement.permissions.ApplicationRoles;
|
||||
import com.knecon.fforesight.tenantusermanagement.testcontainers.MongoDBTestContainer;
|
||||
@ -45,16 +46,16 @@ public class TestTenantService {
|
||||
|
||||
} catch (Exception e) {
|
||||
// not found
|
||||
createUser(testTenantId, actualPort, true);
|
||||
createTenant(testTenantId, actualPort, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void createUser(String testTenantId, int actualPort, boolean withStorage) {
|
||||
private void createTenant(String testTenantId, int actualPort, boolean withStorage) {
|
||||
// not found
|
||||
TenantRequest tenantRequest;
|
||||
var tenantRequestBuilder = TenantRequest.builder()
|
||||
CreateTenantRequest tenantRequest;
|
||||
var tenantRequestBuilder = CreateTenantRequest.builder()
|
||||
.tenantId(testTenantId)
|
||||
.displayName(testTenantId)
|
||||
.guid(UUID.randomUUID().toString())
|
||||
@ -70,6 +71,7 @@ public class TestTenantService {
|
||||
.password("secret")
|
||||
.email("admin@knecon.com")
|
||||
.build()))
|
||||
.applicationType(TenantApplicationType.RedactManager)
|
||||
.databaseConnection(DatabaseConnection.builder()
|
||||
.driver("postgresql")
|
||||
.host(SpringPostgreSQLTestContainer.getInstance().getHost())
|
||||
@ -119,7 +121,7 @@ public class TestTenantService {
|
||||
|
||||
} catch (Exception e) {
|
||||
// not found
|
||||
createUser(testTenantId, 0, false);
|
||||
createTenant(testTenantId, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,8 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||
import com.knecon.fforesight.tenantusermanagement.properties.TenantUserManagementProperties;
|
||||
import com.knecon.fforesight.tenantusermanagement.service.TenantApplicationTypeService;
|
||||
|
||||
import jakarta.ws.rs.BadRequestException;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -24,6 +26,8 @@ public class TokenService {
|
||||
|
||||
@Autowired
|
||||
private TenantUserManagementProperties tenantUserManagementProperties;
|
||||
@Autowired
|
||||
private TenantApplicationTypeService tenantApplicationTypeService;
|
||||
private String username;
|
||||
private String password;
|
||||
private String accessToken;
|
||||
@ -54,7 +58,7 @@ public class TokenService {
|
||||
.realm(TenantContext.getTenantId())
|
||||
.username(username)
|
||||
.password(password)
|
||||
.clientId(tenantUserManagementProperties.getApplicationClientId())
|
||||
.clientId(tenantApplicationTypeService.getCurrentProperties().getApplicationClientId())
|
||||
.grantType(OAuth2Constants.PASSWORD)
|
||||
.resteasyClient(new ResteasyClientBuilderImpl().connectionTTL(2, TimeUnit.SECONDS)
|
||||
.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY)
|
||||
|
||||
@ -1,196 +0,0 @@
|
||||
server:
|
||||
port: 28181
|
||||
|
||||
management:
|
||||
endpoint:
|
||||
metrics.enabled: ${monitoring.enabled:false}
|
||||
prometheus.enabled: ${monitoring.enabled:false}
|
||||
health.enabled: true
|
||||
endpoints.web.exposure.include: prometheus, health, metrics
|
||||
metrics.export.prometheus.enabled: ${monitoring.enabled:false}
|
||||
|
||||
info:
|
||||
description: Tenant User Management Service
|
||||
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:postgresql://${PSQL_HOST:localhost}:${PSQL_PORT:5432}/${PSQL_DATABASE:master}?cachePrepStmts=true&useServerPrepStmts=true&rewriteBatchedStatements=true
|
||||
driverClassName: org.postgresql.Driver
|
||||
username: ${PSQL_USERNAME:fforesight}
|
||||
password: ${PSQL_PASSWORD:fforesight}
|
||||
platform: org.hibernate.dialect.PostgreSQL95Dialect
|
||||
hikari:
|
||||
maximumPoolSize: 10
|
||||
minimum-idle: 2
|
||||
data-source-properties:
|
||||
cachePrepStmts: true
|
||||
prepStmtCacheSize: 1000
|
||||
prepStmtCacheSqlLimit: 2048
|
||||
jackson:
|
||||
serialization:
|
||||
write-dates-as-timestamps: false
|
||||
deserialization:
|
||||
accept-single-value-as-array: true
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
allow-circular-references: true
|
||||
jpa:
|
||||
open-in-view: true
|
||||
database-platform: org.hibernate.dialect.PostgreSQL95Dialect
|
||||
hibernate:
|
||||
ddl-auto: none
|
||||
naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
|
||||
properties:
|
||||
hibernate:
|
||||
jdbc:
|
||||
batch_size: 1000
|
||||
order_inserts: true
|
||||
order_updates: true
|
||||
cache:
|
||||
type: redis
|
||||
mvc:
|
||||
pathmatch:
|
||||
matching-strategy: ant-path-matcher
|
||||
redis:
|
||||
host: ${REDIS_HOST:localhost}
|
||||
port: ${REDIS_PORT:6379}
|
||||
password: ${REDIS_PASSWORD:}
|
||||
|
||||
|
||||
rabbitmq:
|
||||
host: ${RABBITMQ_HOST:localhost}
|
||||
port: ${RABBITMQ_PORT:5672}
|
||||
username: ${RABBITMQ_USERNAME:user}
|
||||
password: ${RABBITMQ_PASSWORD:rabbitmq}
|
||||
listener:
|
||||
simple:
|
||||
acknowledge-mode: AUTO
|
||||
concurrency: 5
|
||||
retry:
|
||||
enabled: true
|
||||
max-attempts: 3
|
||||
max-interval: 15000
|
||||
prefetch: 1
|
||||
|
||||
liquibase:
|
||||
change-log: classpath:/db/changelog/db.changelog-master.yaml
|
||||
enabled: true
|
||||
application:
|
||||
name: tenant-user-management
|
||||
data:
|
||||
redis:
|
||||
host: ${REDIS_HOST:localhost}
|
||||
port: ${REDIS_PORT:6379}
|
||||
password: ${REDIS_PASSWORD:}
|
||||
fforesight:
|
||||
keycloak:
|
||||
ignored-endpoints: [ '/actuator/health', '/tenant-user-management','/internal/**','/tenant-user-management/docs/**','/tenant-user-management/docs','/tenant-user-management/tenants/simple' ]
|
||||
enabled: true
|
||||
springdoc:
|
||||
base-path: '/tenant-user-management'
|
||||
auth-server-url: '/auth'
|
||||
enabled: true
|
||||
default-client-id: 'swagger-ui-client'
|
||||
default-tenant: 'fforesight'
|
||||
tenant-exchange:
|
||||
name: 'tenants-exchange'
|
||||
user-exchange:
|
||||
name: 'users-exchange'
|
||||
tenant-user-management:
|
||||
base-path: '/tenant-user-management'
|
||||
realm: master
|
||||
server-url: http://localhost:28181
|
||||
client-secret: adminClientSecret
|
||||
client-id: adminClient
|
||||
login-theme: redaction
|
||||
kc-role-mapping:
|
||||
roles:
|
||||
- name: SUPER_USER
|
||||
set-by-default: true
|
||||
rank: 100
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
- name: LESS_SUPER_USER
|
||||
set-by-default: true
|
||||
rank: 10
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
- name: KNECON_ADMIN
|
||||
set-by-default: true
|
||||
rank: 1000
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
- name: KNECON_SUPPORT
|
||||
set-by-default: true
|
||||
rank: 1000
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
access-token-life-span: 86400
|
||||
application-name: tenant-user-management
|
||||
application-client-id: tenant-user-management
|
||||
swagger-client-secret: 'testSecret123!'
|
||||
app-prefix: 'fforesight'
|
||||
|
||||
storage:
|
||||
backend: both
|
||||
|
||||
cors.enabled: true
|
||||
springdoc:
|
||||
packages-to-scan: [ 'com.knecon.fforesight.tenantusermanagement.controller.external' ]
|
||||
203
src/test/resources/application.yml
Normal file
203
src/test/resources/application.yml
Normal file
@ -0,0 +1,203 @@
|
||||
server:
|
||||
port: 28181
|
||||
|
||||
persistence-service.url: "http://persistence-service-v1:8090"
|
||||
|
||||
management:
|
||||
endpoint:
|
||||
metrics.enabled: ${monitoring.enabled:false}
|
||||
prometheus.enabled: ${monitoring.enabled:false}
|
||||
health.enabled: true
|
||||
endpoints.web.exposure.include: prometheus, health, metrics
|
||||
metrics.export.prometheus.enabled: ${monitoring.enabled:false}
|
||||
|
||||
info:
|
||||
description: Tenant User Management Service
|
||||
|
||||
lifecycle:
|
||||
base-package: com.knecon.fforesight.tenantusermanagement
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:postgresql://${PSQL_HOST:localhost}:${PSQL_PORT:5432}/${PSQL_DATABASE:master}?cachePrepStmts=true&useServerPrepStmts=true&rewriteBatchedStatements=true
|
||||
driverClassName: org.postgresql.Driver
|
||||
username: ${PSQL_USERNAME:fforesight}
|
||||
password: ${PSQL_PASSWORD:fforesight}
|
||||
platform: org.hibernate.dialect.PostgreSQL10Dialect
|
||||
hikari:
|
||||
maximumPoolSize: 10
|
||||
minimum-idle: 2
|
||||
data-source-properties:
|
||||
cachePrepStmts: true
|
||||
prepStmtCacheSize: 1000
|
||||
prepStmtCacheSqlLimit: 2048
|
||||
jackson:
|
||||
serialization:
|
||||
write-dates-as-timestamps: false
|
||||
deserialization:
|
||||
accept-single-value-as-array: true
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
allow-circular-references: true
|
||||
jpa:
|
||||
open-in-view: true
|
||||
database-platform: org.hibernate.dialect.PostgreSQL10Dialect
|
||||
hibernate:
|
||||
ddl-auto: none
|
||||
naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
|
||||
properties:
|
||||
hibernate:
|
||||
jdbc:
|
||||
batch_size: 1000
|
||||
order_inserts: true
|
||||
order_updates: true
|
||||
cache:
|
||||
type: redis
|
||||
mvc:
|
||||
pathmatch:
|
||||
matching-strategy: ant-path-matcher
|
||||
redis:
|
||||
host: ${REDIS_HOST:localhost}
|
||||
port: ${REDIS_PORT:6379}
|
||||
password: ${REDIS_PASSWORD:}
|
||||
|
||||
|
||||
rabbitmq:
|
||||
host: ${RABBITMQ_HOST:localhost}
|
||||
port: ${RABBITMQ_PORT:5672}
|
||||
username: ${RABBITMQ_USERNAME:user}
|
||||
password: ${RABBITMQ_PASSWORD:rabbitmq}
|
||||
listener:
|
||||
simple:
|
||||
acknowledge-mode: AUTO
|
||||
concurrency: 5
|
||||
retry:
|
||||
enabled: true
|
||||
max-attempts: 3
|
||||
max-interval: 15000
|
||||
prefetch: 1
|
||||
|
||||
liquibase:
|
||||
change-log: classpath:/db/changelog/db.changelog-master.yaml
|
||||
enabled: true
|
||||
application:
|
||||
name: tenant-user-management
|
||||
data:
|
||||
redis:
|
||||
host: ${REDIS_HOST:localhost}
|
||||
port: ${REDIS_PORT:6379}
|
||||
password: ${REDIS_PASSWORD:}
|
||||
|
||||
fforesight:
|
||||
keycloak:
|
||||
ignored-endpoints: [ '/actuator/health', '/tenant-user-management','/internal/**','/tenant-user-management/docs/**','/tenant-user-management/docs' ]
|
||||
enabled: true
|
||||
springdoc:
|
||||
base-path: '/tenant-user-management'
|
||||
auth-server-url: '/auth'
|
||||
enabled: true
|
||||
default-client-id: 'swagger-ui-client'
|
||||
default-tenant: 'fforesight'
|
||||
tenant-exchange:
|
||||
name: 'tenants-exchange'
|
||||
user-exchange:
|
||||
name: 'users-exchange'
|
||||
tenant-user-management:
|
||||
base-path: '/tenant-user-management'
|
||||
server-url: http://localhost:28181
|
||||
realm: master
|
||||
client-secret: adminClientSecret
|
||||
client-id: adminClient
|
||||
swagger-client-secret: 'testSecret123!'
|
||||
application-types:
|
||||
redactmanager:
|
||||
login-theme: redaction
|
||||
kc-role-mapping:
|
||||
roles:
|
||||
- name: SUPER_USER
|
||||
set-by-default: true
|
||||
rank: 100
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
- name: LESS_SUPER_USER
|
||||
set-by-default: true
|
||||
rank: 10
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
- name: KNECON_ADMIN
|
||||
set-by-default: true
|
||||
rank: 1000
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
- name: KNECON_SUPPORT
|
||||
set-by-default: true
|
||||
rank: 1000
|
||||
permissions:
|
||||
- 'fforesight-read-general-configuration'
|
||||
- 'fforesight-write-general-configuration'
|
||||
- 'fforesight-manage-user-preferences'
|
||||
- 'fforesight-read-users'
|
||||
- 'fforesight-read-all-users'
|
||||
- 'fforesight-write-users'
|
||||
- 'fforesight-update-my-profile'
|
||||
- 'fforesight-create-tenant'
|
||||
- 'fforesight-get-tenants'
|
||||
- 'fforesight-update-tenant'
|
||||
- 'fforesight-deployment-info'
|
||||
- 'fforesight-read-smtp-configuration'
|
||||
- 'fforesight-write-smtp-configuration'
|
||||
- 'fforesight-read-identity-provider-config'
|
||||
- 'fforesight-write-identity-provider-config'
|
||||
access-token-life-span: 86400
|
||||
application-name: tenant-user-management
|
||||
application-client-id: tenant-user-management
|
||||
app-prefix: 'fforesight'
|
||||
|
||||
storage:
|
||||
backend: both
|
||||
|
||||
cors.enabled: true
|
||||
springdoc:
|
||||
packages-to-scan: [ 'com.knecon.fforesight.tenantusermanagement.controller.external' ]
|
||||
Loading…
x
Reference in New Issue
Block a user