diff --git a/.github/workflows/gradle-build-development.yml b/.github/workflows/gradle-build-development.yml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.github/workflows/gradle-build-poc.yml b/.github/workflows/gradle-build-poc.yml new file mode 100644 index 0000000000..5924d45e3b --- /dev/null +++ b/.github/workflows/gradle-build-poc.yml @@ -0,0 +1,125 @@ +name: Gradle Build & Deploy - POC +on: + push: + branches: + # - 'develop' + - '2486-create-new-pipeline-for-updated-build-deployment' + +jobs: + build: + permissions: + id-token: 'write' + runs-on: ubuntu-latest + environment: + name: DEV-POC + # url: ${{ env.CLOUD_RUN_ADDRESS }}/ + env: + PROJECT_NUMBER : ${{ secrets.PROJECT_NUM }} + PROJECT_ID: ${{ secrets.PROJECT_ID }} + PROJECT_NAME: ${{ secrets.PROJECT_NAME }} + RUN_REGION: us-central1 + SERVICE_NAME: checkins-develop + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - id: 'auth_with_gcp' + uses: 'google-github-actions/auth@v2' + with: + project_id: '${{secrets.PROJECT_NUM}}' + workload_identity_provider: '${{secrets.WORKLOAD_IDENTITY_PROVIDER}}' + service_account: '${{secrets.AUTOMATION_SERVICE_ACCOUNT}}' + - id: 'secrets' + uses: 'google-github-actions/get-secretmanager-secrets@v2' + with: + secrets: |- + cloud_run_address:${{secrets.PROJECT_NUM}}/CLOUD_RUN_ADDRESS + cloud_db_connection_name:${{secrets.PROJECT_NUM}}/CLOUD_DB_CONNECTION_NAME + connector_id:${{secrets.PROJECT_NUM}}/CONNECTOR_ID + - name: Set up Node LTS + uses: actions/setup-node@v4 + with: + node-version: '20' + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: 21 + - name: Cache SonarQube packages + uses: actions/cache@v4 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + restore-keys: ${{ runner.os }}-sonar + - name: Cache Gradle packages + uses: actions/cache@v4 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle + - name: Validate Gradle wrapper + uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b + - name: Build with Gradle + uses: gradle/gradle-build-action@4137be6a8bf7d7133955359dbd952c0ca73b1021 + with: + arguments: assemble + env: + VITE_APP_API_URL: ${{steps.secrets.outputs.cloud_run_address}} + - name: Gradle runs tests + uses: gradle/gradle-build-action@4137be6a8bf7d7133955359dbd952c0ca73b1021 + with: + arguments: check +# - name: Do SonarQube checks +# uses: gradle/gradle-build-action@4137be6a8bf7d7133955359dbd952c0ca73b1021 +# with: +# arguments: sonarqube --info +# env: +# GITHUB_TOKEN: ${{ secrets.GIT_HUB_TOKEN }} +# SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} +# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + - name: Setup python + run: | + sudo apt-get install python2.7 + - name: Export gcloud related env variable + run: export CLOUDSDK_PYTHON="/usr/bin/python2" + # Setup gcloud CLI + - uses: google-github-actions/setup-gcloud@v2 + with: + version: "477.0.0" + # service_account_key: ${{ secrets.RUN_SA_KEY }} + # project_id: ${{ secrets.RUN_PROJECT }} + - name: Auth Configure Docker + run: |- + gcloud --quiet auth configure-docker + - name: Build the Docker image + run: |- + cd server + docker build --tag "gcr.io/$PROJECT_ID/$SERVICE_NAME:$GITHUB_SHA" . + - name: Push the Docker image to Google Container Registry + run: |- + cd server + docker push "gcr.io/$PROJECT_ID/$SERVICE_NAME:$GITHUB_SHA" + - name: Deploy image to Cloud Run + run: |- + gcloud run deploy "$SERVICE_NAME" \ + --project "$PROJECT_ID" \ + --region "$RUN_REGION" \ + --image "gcr.io/$PROJECT_ID/$SERVICE_NAME:$GITHUB_SHA" \ + --memory 1Gi \ + --add-cloudsql-instances ${{steps.secrets.outputs.cloud_db_connection_name }} \ + --vpc-connector ${{steps.secrets.outputs.connector_id}} \ + --set-secrets "CLOUD_DB_CONNECTION_NAME=CLOUD_DB_CONNECTION_NAME:latest" \ + --set-secrets "DB_NAME=DB_NAME:latest" \ + --set-secrets "DATASOURCES_DEFAULT_PASSWORD=DATASOURCES_DEFAULT_PASSWORD:latest" \ + --set-secrets "DATASOURCES_DEFAULT_USERNAME=DATASOURCES_DEFAULT_USERNAME:latest" \ + --set-secrets "AES_KEY=AES_KEY:latest" \ + --set-secrets "OAUTH_CLIENT_ID=OAUTH_CLIENT_ID:latest" \ + --set-secrets "OAUTH_CLIENT_SECRET=OAUTH_CLIENT_SECRET:latest" \ + --set-secrets "GSUITE_SUPER_ADMIN=GSUITE_SUPER_ADMIN:latest" \ + --set-secrets "SERVICE_ACCOUNT_CREDENTIALS=SERVICE_ACCOUNT_CREDENTIALS:latest" \ + --set-secrets "WEB_ADDRESS=CLOUD_RUN_ADDRESS:latest" \ + --set-secrets "MICRONAUT_ENVIRONMENTS=MICRONAUT_ENVIRONMENTS:latest" \ + --platform "managed" \ + --max-instances 2 \ + --allow-unauthenticated + diff --git a/server/src/main/java/com/objectcomputing/checkins/notifications/email/MailJetFactory.java b/server/src/main/java/com/objectcomputing/checkins/notifications/email/MailJetFactory.java index 6e755a2292..b63dee6747 100644 --- a/server/src/main/java/com/objectcomputing/checkins/notifications/email/MailJetFactory.java +++ b/server/src/main/java/com/objectcomputing/checkins/notifications/email/MailJetFactory.java @@ -4,9 +4,13 @@ import com.mailjet.client.MailjetClient; import com.mailjet.client.resource.Emailv31; +import com.objectcomputing.checkins.exceptions.NotFoundException; +import com.objectcomputing.checkins.services.settings.SettingOption; +import com.objectcomputing.checkins.services.settings.SettingsServices; import io.micronaut.context.annotation.Bean; import io.micronaut.context.annotation.Factory; +import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; @@ -17,13 +21,33 @@ public class MailJetFactory { public static final String MJML_FORMAT = "mjml"; public static final String TEXT_FORMAT = "text"; + @Inject + SettingsServices settingsServices; + @Bean MailjetClient getClient() { + + String mj_apikey_public; + String mj_apikey_private; + + try { + mj_apikey_public = settingsServices.findByName(SettingOption.MJ_APIKEY_PUBLIC.name()).getValue(); + } catch (NotFoundException e) { + mj_apikey_public = ""; + } + try { + mj_apikey_private = settingsServices.findByName(SettingOption.MJ_APIKEY_PRIVATE.name()).getValue(); + } catch (NotFoundException e) { + mj_apikey_private = ""; + } + + + return new MailjetClient( ClientOptions .builder() - .apiKey(System.getenv("MJ_APIKEY_PUBLIC")) - .apiSecretKey(System.getenv("MJ_APIKEY_PRIVATE")) + .apiKey(mj_apikey_public) + .apiSecretKey(mj_apikey_private) .build() ); } diff --git a/server/src/main/java/com/objectcomputing/checkins/notifications/email/MailJetSender.java b/server/src/main/java/com/objectcomputing/checkins/notifications/email/MailJetSender.java index 855ea9f48b..0d86dab347 100644 --- a/server/src/main/java/com/objectcomputing/checkins/notifications/email/MailJetSender.java +++ b/server/src/main/java/com/objectcomputing/checkins/notifications/email/MailJetSender.java @@ -7,6 +7,9 @@ import com.mailjet.client.resource.Emailv31; import ch.digitalfondue.mjml4j.Mjml4j; import com.objectcomputing.checkins.exceptions.BadArgException; +import com.objectcomputing.checkins.exceptions.NotFoundException; +import com.objectcomputing.checkins.services.settings.SettingOption; +import com.objectcomputing.checkins.services.settings.SettingsServices; import io.micronaut.context.annotation.Prototype; import io.micronaut.context.annotation.Requires; import org.json.JSONArray; @@ -19,27 +22,40 @@ import java.util.List; @Prototype -@Requires(bean = MailJetConfiguration.class) public class MailJetSender implements EmailSender { public static final String MJMLPART = "MJMLPART"; private static final Logger LOG = LoggerFactory.getLogger(MailJetSender.class); private final MailjetClient client; + private final SettingsServices settingsServices; public static final int MAILJET_RECIPIENT_LIMIT = 49; - private final String fromAddress; - private final String fromName; private String emailFormat; + private String getFromAddress() { + try { + return settingsServices.findByName(SettingOption.FROM_ADDRESS.name()).getValue(); + } catch (NotFoundException e) { + return ""; + } + } + + private String getFromName() { + try { + return settingsServices.findByName(SettingOption.FROM_NAME.name()).getValue(); + } catch (NotFoundException e) { + return ""; + } + } + public MailJetSender( MailjetClient client, - MailJetConfiguration configuration + SettingsServices settingsServices ) { this.client = client; - this.fromAddress = configuration.getFromAddress(); - this.fromName = configuration.getFromName(); this.emailFormat = Emailv31.Message.HTMLPART; + this.settingsServices = settingsServices; } /** @@ -82,10 +98,23 @@ public static List getEmailBatches(String... recipients) { */ @Override public void sendEmail(String fromName, String fromAddress, String subject, String content, String... recipients) { - if(fromName == null) fromName = this.fromName; - if(fromAddress == null) fromAddress = this.fromAddress; + if(fromName == null) fromName = getFromName(); + if(fromAddress == null) fromAddress = getFromAddress(); + + String mj_apikey_public; + String mj_apikey_private; + try { + mj_apikey_public = settingsServices.findByName(SettingOption.MJ_APIKEY_PUBLIC.name()).getValue(); + } catch (NotFoundException e) { + mj_apikey_public = ""; + } + try { + mj_apikey_private = settingsServices.findByName(SettingOption.MJ_APIKEY_PRIVATE.name()).getValue(); + } catch (NotFoundException e) { + mj_apikey_private = ""; + } - if(System.getenv("MJ_APIKEY_PUBLIC") == null || System.getenv("MJ_APIKEY_PRIVATE") == null) { + if(mj_apikey_public == "" || mj_apikey_private == "") { LOG.error("API key(s) are missing for MailJetSender"); return; } @@ -117,7 +146,7 @@ public void sendEmail(String fromName, String fromAddress, String subject, Strin List failedBatches = new ArrayList<>(); final JSONArray to = new JSONArray() - .put(new JSONObject().put("Email", this.fromAddress)); + .put(new JSONObject().put("Email", fromAddress)); emailBatches.forEach((recipientList) -> { try { send(sender, to, recipientList, diff --git a/server/src/main/java/com/objectcomputing/checkins/security/GoogleServiceConfiguration.java b/server/src/main/java/com/objectcomputing/checkins/security/GoogleServiceConfiguration.java index 5a56b2ec5f..b4f3db34fd 100644 --- a/server/src/main/java/com/objectcomputing/checkins/security/GoogleServiceConfiguration.java +++ b/server/src/main/java/com/objectcomputing/checkins/security/GoogleServiceConfiguration.java @@ -7,7 +7,6 @@ import io.micronaut.validation.validator.constraints.ConstraintValidator; import jakarta.inject.Singleton; import jakarta.validation.Constraint; -import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; import org.slf4j.Logger; @@ -29,9 +28,6 @@ public class GoogleServiceConfiguration { private static final Logger LOG = LoggerFactory.getLogger(GoogleServiceConfiguration.class); - @NotNull - private String directoryId; - @ValidEncodedGoogleServiceConfiguration private String encodedValue; diff --git a/server/src/main/java/com/objectcomputing/checkins/services/file/FileServicesImpl.java b/server/src/main/java/com/objectcomputing/checkins/services/file/FileServicesImpl.java index 3193a24c6a..c41c6668cd 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/file/FileServicesImpl.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/file/FileServicesImpl.java @@ -5,6 +5,7 @@ import com.google.api.services.drive.Drive; import com.google.api.services.drive.model.File; import com.google.api.services.drive.model.FileList; +import com.objectcomputing.checkins.exceptions.NotFoundException; import com.objectcomputing.checkins.security.GoogleServiceConfiguration; import com.objectcomputing.checkins.services.checkindocument.CheckinDocument; import com.objectcomputing.checkins.services.checkindocument.CheckinDocumentServices; @@ -14,10 +15,11 @@ import com.objectcomputing.checkins.services.memberprofile.MemberProfileServices; import com.objectcomputing.checkins.services.memberprofile.MemberProfileUtils; import com.objectcomputing.checkins.services.memberprofile.currentuser.CurrentUserServices; +import com.objectcomputing.checkins.services.settings.SettingOption; +import com.objectcomputing.checkins.services.settings.SettingsServices; import com.objectcomputing.checkins.util.googleapiaccess.GoogleApiAccess; import io.micronaut.http.MediaType; import io.micronaut.http.multipart.CompletedFileUpload; - import jakarta.inject.Singleton; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,17 +40,20 @@ public class FileServicesImpl extends FileServicesBaseImpl { private final GoogleApiAccess googleApiAccess; private final GoogleServiceConfiguration googleServiceConfiguration; + private SettingsServices settingsServices; public FileServicesImpl(GoogleApiAccess googleApiAccess, CheckInServices checkInServices, CheckinDocumentServices checkinDocumentServices, MemberProfileServices memberProfileServices, CurrentUserServices currentUserServices, - GoogleServiceConfiguration googleServiceConfiguration) { + GoogleServiceConfiguration googleServiceConfiguration, + SettingsServices settingsServices) { super(checkInServices, checkinDocumentServices, memberProfileServices, currentUserServices); this.googleApiAccess = googleApiAccess; this.googleServiceConfiguration = googleServiceConfiguration; + this.settingsServices = settingsServices; } @Override @@ -58,8 +63,8 @@ protected void getCheckinDocuments( Drive drive = googleApiAccess.getDrive(); validate(drive == null, "Unable to access Google Drive"); - String rootDirId = googleServiceConfiguration.getDirectoryId(); - validate(rootDirId == null, "No destination folder has been configured. Contact your administrator for assistance."); + String rootDirId = getRootDirId(); + validate(rootDirId == null || rootDirId == "", "No destination folder has been configured. Contact your administrator for assistance."); if (checkinDocuments.isEmpty()) { FileList driveIndex = getFoldersInRoot(drive, rootDirId); @@ -87,6 +92,17 @@ protected void getCheckinDocuments( } } + private String getRootDirId() { + String rootDirId; + try { + rootDirId = settingsServices.findByName(SettingOption.DIRECTORY_ID.name()).getValue(); + } + catch (NotFoundException e ) { + rootDirId = ""; + } + return rootDirId; + } + @Override protected void downloadSingleFile(String docId, FileOutputStream myWriter) throws IOException { Drive drive = googleApiAccess.getDrive(); @@ -103,7 +119,7 @@ protected FileInfoDTO uploadSingleFile(CompletedFileUpload file, String director Drive drive = googleApiAccess.getDrive(); validate(drive == null, "Unable to access Google Drive"); - String rootDirId = googleServiceConfiguration.getDirectoryId(); + String rootDirId = getRootDirId(); validate(rootDirId == null, "No destination folder has been configured. Contact your administrator for assistance."); // Check if folder already exists on google drive. If exists, return folderId and name @@ -153,7 +169,7 @@ public FileInfoDTO uploadDocument(String directoryName, String name, String text Drive drive = googleApiAccess.getDrive(); validate(drive == null, "Unable to access Google Drive"); - String rootDirId = googleServiceConfiguration.getDirectoryId(); + String rootDirId = getRootDirId(); validate(rootDirId == null, "No destination folder has been configured. Contact your administrator for assistance."); // Check if folder already exists on google drive. If exists, return folderId and name diff --git a/server/src/main/java/com/objectcomputing/checkins/services/settings/Setting.java b/server/src/main/java/com/objectcomputing/checkins/services/settings/Setting.java index 8d58edfa4a..74798f87cc 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/settings/Setting.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/settings/Setting.java @@ -1,6 +1,7 @@ package com.objectcomputing.checkins.services.settings; import io.micronaut.core.annotation.Introspected; +import io.micronaut.core.annotation.Nullable; import io.micronaut.data.annotation.AutoPopulated; import io.micronaut.data.annotation.TypeDef; import io.micronaut.data.model.DataType; @@ -10,6 +11,7 @@ import jakarta.persistence.Id; import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; +import lombok.Builder; import lombok.Getter; import lombok.Setter; @@ -36,7 +38,7 @@ public class Setting { @Schema(description = "the name of the setting") private String name; - @NotNull + @Nullable @Column(name="value") @TypeDef(type= DataType.STRING) @Schema(description = "the value of the setting") @@ -56,6 +58,10 @@ public Setting(String name, String value) { this.value = value; } + public String getValue() { + return this.value == null ? "" : this.value; + } + @Override public boolean equals(Object o) { if (o == this) diff --git a/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingOption.java b/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingOption.java index 69bb398222..e407b969b8 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingOption.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingOption.java @@ -18,8 +18,14 @@ @JsonDeserialize(using = SettingOptionDeserializer.class) public enum SettingOption { LOGO_URL("The logo url", Category.THEME, Type.FILE), + FROM_NAME("Email From Name", Category.CHECK_INS, Type.STRING), + FROM_ADDRESS("From Address", Category.CHECK_INS, Type.STRING), + DIRECTORY_ID("Google Drive ID", Category.INTEGRATIONS, Type.STRING), + MJ_APIKEY_PUBLIC("MailJet Public API Key", Category.INTEGRATIONS, Type.STRING), + MJ_APIKEY_PRIVATE("MailJet Private API Key", Category.INTEGRATIONS, Type.STRING), PULSE_EMAIL_FREQUENCY("The Pulse Email Frequency", Category.CHECK_INS, Type.STRING, List.of("weekly", "bi-weekly", "monthly")); + private final String description; private final Category category; private final Type type; diff --git a/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingsController.java b/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingsController.java index a96c185a3e..cd35d7a2a2 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingsController.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingsController.java @@ -1,6 +1,8 @@ package com.objectcomputing.checkins.services.settings; import com.objectcomputing.checkins.exceptions.NotFoundException; +import com.objectcomputing.checkins.services.permissions.Permission; +import com.objectcomputing.checkins.services.permissions.RequiredPermission; import io.micronaut.http.HttpResponse; import io.micronaut.http.HttpStatus; import io.micronaut.http.annotation.Body; @@ -44,7 +46,8 @@ public SettingsController(SettingsServices settingsServices) { * @return {@link >} Returned setting */ @ExecuteOn(TaskExecutors.BLOCKING) - @Get + @Get("/") + @RequiredPermission(Permission.CAN_VIEW_SETTINGS) public List findAllSettings() { return settingsServices.findAllSettings().stream() .map(this::fromEntity).toList(); @@ -58,6 +61,7 @@ public List findAllSettings() { */ @ExecuteOn(TaskExecutors.BLOCKING) @Get("/{name}") + @RequiredPermission(Permission.CAN_VIEW_SETTINGS) public SettingsResponseDTO findByName(@PathVariable @NotNull String name) { return fromEntity(settingsServices.findByName(name)); } @@ -68,23 +72,9 @@ public SettingsResponseDTO findByName(@PathVariable @NotNull String name) { * @return {@link } Returned setting options */ @Get("/options") - public List getOptions() { - List options = SettingOption.getOptions(); - return options.stream().map(option -> { - String value = ""; - UUID uuid = null; - try { - Setting s = settingsServices.findByName(option.name()); - uuid = s.getId(); - value = s.getValue(); - } catch(NotFoundException ex) { - } - return new SettingsResponseDTO( - uuid, option.name(), option.getDescription(), - option.getCategory(), option.getType(), - option.getValues(), - value); - }).toList(); + @RequiredPermission(Permission.CAN_VIEW_SETTINGS) + public List getOptions() { + return SettingOption.getOptions(); } /** @@ -95,6 +85,7 @@ public List getOptions() { */ @ExecuteOn(TaskExecutors.BLOCKING) @Post + @RequiredPermission(Permission.CAN_ADMINISTER_SETTINGS) public HttpResponse save(@Body @Valid SettingsDTO settingDTO) { Setting savedSetting = settingsServices.save(fromDTO(settingDTO)); URI location = UriBuilder.of(PATH).path(savedSetting.getId().toString()).build(); @@ -109,6 +100,7 @@ public HttpResponse save(@Body @Valid SettingsDTO settingDT */ @Put @ExecuteOn(TaskExecutors.BLOCKING) + @RequiredPermission(Permission.CAN_ADMINISTER_SETTINGS) public HttpResponse update(@Body @Valid SettingsDTO settingsDTO) { Setting savedSetting = settingsServices.update(settingsDTO.getName(), settingsDTO.getValue()); SettingsResponseDTO settingsResponseDTO = fromEntity(savedSetting); @@ -125,6 +117,7 @@ public HttpResponse update(@Body @Valid SettingsDTO setting */ @Delete("/{id}") @ExecuteOn(TaskExecutors.BLOCKING) + @RequiredPermission(Permission.CAN_ADMINISTER_SETTINGS) public HttpStatus delete(UUID id) { return settingsServices.delete(id) ? HttpStatus.OK : HttpStatus.UNPROCESSABLE_ENTITY; } diff --git a/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingsServicesImpl.java b/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingsServicesImpl.java index 3491b9145f..d170becd82 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingsServicesImpl.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingsServicesImpl.java @@ -6,12 +6,15 @@ import com.objectcomputing.checkins.exceptions.NotFoundException; import jakarta.inject.Singleton; import jakarta.validation.constraints.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.List; import java.util.UUID; @Singleton public class SettingsServicesImpl implements SettingsServices { + private static final Logger LOG = LoggerFactory.getLogger(SettingsServicesImpl.class); private final SettingsRepository settingsRepository; @@ -33,10 +36,14 @@ public Setting save(Setting setting) { @RequiredPermission(Permission.CAN_ADMINISTER_SETTINGS) public Setting update(String name, String value) { validateSettingOption(name); - Setting setting = settingsRepository.findByName(name) - .orElseThrow(() -> new NotFoundException("Setting with name " + name + " not found.")); - setting.setValue(value); - return settingsRepository.update(setting); + try { + Setting setting = settingsRepository.findByName(name).orElseThrow(() -> new NotFoundException("Setting with name " + name + " not found.")); + setting.setValue(value); + return settingsRepository.update(setting); + + } catch (NotFoundException e ){ + return settingsRepository.save(new Setting(name, value)); + } } @Override @@ -49,6 +56,7 @@ public Setting findByName(@NotNull String name) { @Override @RequiredPermission(Permission.CAN_VIEW_SETTINGS) public List findAllSettings() { + LOG.info("In SettingsServicesImpl.findAllSettigs()"); return settingsRepository.findAll(); } diff --git a/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingsUpdatedEvent.java b/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingsUpdatedEvent.java new file mode 100644 index 0000000000..7f1b9bb1ed --- /dev/null +++ b/server/src/main/java/com/objectcomputing/checkins/services/settings/SettingsUpdatedEvent.java @@ -0,0 +1,15 @@ +package com.objectcomputing.checkins.services.settings; + +import lombok.Getter; + +public class SettingsUpdatedEvent { + + @Getter + private final Setting setting; + + public SettingsUpdatedEvent(Setting setting){ + + this.setting = setting; + } + +} diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml index f6ba1a2099..19c7f3da14 100755 --- a/server/src/main/resources/application.yml +++ b/server/src/main/resources/application.yml @@ -49,7 +49,7 @@ micronaut: access-token: expiration: 28800 oauth2: - callback-uri: ${ OAUTH_CALLBACK_URI } +# callback-uri: ${ OAUTH_CALLBACK_URI } clients: google: client-id: ${ OAUTH_CLIENT_ID } @@ -114,13 +114,8 @@ flyway: aeskey: ${ AES_KEY } --- service-account-credentials: - directory-id: ${ DIRECTORY_ID } encoded-value: ${SERVICE_ACCOUNT_CREDENTIALS} --- -mail-jet: - from-address: ${ FROM_ADDRESS } - from-name: ${ FROM_NAME } ---- github-credentials: github-token: ${ GITHUB_TOKEN } github-url: "https://api.github.com/" diff --git a/server/src/main/resources/db/dev/R__Load_testing_data.sql b/server/src/main/resources/db/dev/R__Load_testing_data.sql index 3c3cb5d642..3af19d6dd6 100644 --- a/server/src/main/resources/db/dev/R__Load_testing_data.sql +++ b/server/src/main/resources/db/dev/R__Load_testing_data.sql @@ -55,17 +55,22 @@ VALUES INSERT INTO member_profile -- Terrific Yak (id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) VALUES - ('1c813446-c65a-4f49-b980-0193f7bfff8c', PGP_SYM_ENCRYPT('Terrific','${aeskey}'), PGP_SYM_ENCRYPT('Yak','${aeskey}'), PGP_SYM_ENCRYPT('Senior Developer','${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', PGP_SYM_ENCRYPT('Manchester, UK','${aeskey}'), PGP_SYM_ENCRYPT('yatest@objectcomputing.com','${aeskey}'), 'yak-12345678', '2024-05-08', PGP_SYM_ENCRYPT('Java developer for ages','${aeskey}'), '72655c4f-1fb8-4514-b31e-7f7e19fa9bd7', '1999-12-31', '2024-03-29'); + ('1c813446-c65a-4f49-b980-0193f7bfff8c', PGP_SYM_ENCRYPT('Terrific','${aeskey}'), PGP_SYM_ENCRYPT('Yak','${aeskey}'), PGP_SYM_ENCRYPT('Senior Developer','${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', PGP_SYM_ENCRYPT('Manchester, UK','${aeskey}'), PGP_SYM_ENCRYPT('yatest@objectcomputing.com','${aeskey}'), 'yak-12345678', '2024-05-08', PGP_SYM_ENCRYPT('Java developer for ages','${aeskey}'), '72655c4f-1fb8-4514-b31e-7f7e19fa9bd7', '1999-12-31', '2024-03-29'); + +INSERT INTO member_profile -- Derelict Reindeer + (id, firstName, lastName, title, location, workEmail, employeeid, startdate, biotext, supervisorid, last_seen) +VALUES + ('2b067cbb-45c2-4c3c-a6b2-eea370f9d969', PGP_SYM_ENCRYPT('Derelict','${aeskey}'), PGP_SYM_ENCRYPT('Reindeer','${aeskey}'), PGP_SYM_ENCRYPT('Engineer','${aeskey}'), PGP_SYM_ENCRYPT('St. Louis','${aeskey}'), PGP_SYM_ENCRYPT('rodecapd@objectcomputing.com','${aeskey}'), '122758121', '2012-09-29', PGP_SYM_ENCRYPT('Does stuff. Sometimes well, sometimes not','${aeskey}'), '01b7d769-9fa2-43ff-95c7-f3b950a27bf9', '2012-09-29'); INSERT INTO member_profile -- Unreal Ulysses -(id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) + (id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) VALUES -('dfe2f986-fac0-11eb-9a03-0242ac130003', PGP_SYM_ENCRYPT('Unreal','${aeskey}'), PGP_SYM_ENCRYPT('Ulysses','${aeskey}'), PGP_SYM_ENCRYPT('Test Engineer 2','${aeskey}'), '1c813446-c65a-4f49-b980-0193f7bfff8c', PGP_SYM_ENCRYPT('St. Louis','${aeskey}'), PGP_SYM_ENCRYPT('testing2@objectcomputing.com','${aeskey}'), '010101012', '2021-05-22', PGP_SYM_ENCRYPT('Test user 2','${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', '1950-01-01', '2021-05-22'); + ('dfe2f986-fac0-11eb-9a03-0242ac130003', PGP_SYM_ENCRYPT('Unreal','${aeskey}'), PGP_SYM_ENCRYPT('Ulysses','${aeskey}'), PGP_SYM_ENCRYPT('Test Engineer 2','${aeskey}'), '1c813446-c65a-4f49-b980-0193f7bfff8c', PGP_SYM_ENCRYPT('St. Louis','${aeskey}'), PGP_SYM_ENCRYPT('testing2@objectcomputing.com','${aeskey}'), '010101012', '2021-05-22', PGP_SYM_ENCRYPT('Test user 2','${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', '1950-01-01', '2021-05-22'); INSERT INTO member_profile -- Kazuhira Miller -(id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) + (id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) VALUES -('a90be358-aa3d-49c8-945a-879a93646e45', PGP_SYM_ENCRYPT('Kazuhira','${aeskey}'), PGP_SYM_ENCRYPT('Miller','${aeskey}'), PGP_SYM_ENCRYPT('Unit Coordinator','${aeskey}'), 'dfe2f986-fac0-11eb-9a03-0242ac130003', PGP_SYM_ENCRYPT('Mother Base','${aeskey}'), PGP_SYM_ENCRYPT('millerkaz@objectcomputing.com','${aeskey}'), '012345678', '2022-03-29', PGP_SYM_ENCRYPT('Bff with Big Boss','${aeskey}'), 'dfe2f986-fac0-11eb-9a03-0242ac130003', '1943-07-04', '2022-03-29'); + ('a90be358-aa3d-49c8-945a-879a93646e45', PGP_SYM_ENCRYPT('Kazuhira','${aeskey}'), PGP_SYM_ENCRYPT('Miller','${aeskey}'), PGP_SYM_ENCRYPT('Unit Coordinator','${aeskey}'), 'dfe2f986-fac0-11eb-9a03-0242ac130003', PGP_SYM_ENCRYPT('Mother Base','${aeskey}'), PGP_SYM_ENCRYPT('millerkaz@objectcomputing.com','${aeskey}'), '012345678', '2022-03-29', PGP_SYM_ENCRYPT('Bff with Big Boss','${aeskey}'), 'dfe2f986-fac0-11eb-9a03-0242ac130003', '1943-07-04', '2022-03-29'); INSERT INTO member_profile -- Awesome Baboon (id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, last_seen) @@ -73,9 +78,9 @@ VALUES ('67dc3a3b-5bfa-4759-997a-fb6bac98dcf3', PGP_SYM_ENCRYPT('Awesome','${aeskey}'), PGP_SYM_ENCRYPT('Baboon','${aeskey}'), PGP_SYM_ENCRYPT('System Administrator','${aeskey}'), 'a90be358-aa3d-49c8-945a-879a93646e45', PGP_SYM_ENCRYPT('St. Louis, MO','${aeskey}'), PGP_SYM_ENCRYPT('barbagliaa@objectcomputing.com','${aeskey}'), '123123450', '2012-09-29', PGP_SYM_ENCRYPT('Awesome Administrator','${aeskey}'), null, '2012-09-29'); INSERT INTO member_profile -- Huey Emmerich -(id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) + (id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) VALUES -('8d75c07e-6adc-437a-8659-7dd953ce6600', PGP_SYM_ENCRYPT('Huey','${aeskey}'), PGP_SYM_ENCRYPT('Emmerich','${aeskey}'), PGP_SYM_ENCRYPT('Head of R&D','${aeskey}'), 'dfe2f986-fac0-11eb-9a03-0242ac130003', PGP_SYM_ENCRYPT('Mother Base','${aeskey}'), PGP_SYM_ENCRYPT('emmerichh@objectcomputing.com','${aeskey}'), '657483498', '2022-03-29', PGP_SYM_ENCRYPT('Waiting for love to bloom on the battlefield','${aeskey}'), 'dfe2f986-fac0-11eb-9a03-0242ac130003', '1943-07-04', '2022-03-29'); + ('8d75c07e-6adc-437a-8659-7dd953ce6600', PGP_SYM_ENCRYPT('Huey','${aeskey}'), PGP_SYM_ENCRYPT('Emmerich','${aeskey}'), PGP_SYM_ENCRYPT('Head of R&D','${aeskey}'), 'dfe2f986-fac0-11eb-9a03-0242ac130003', PGP_SYM_ENCRYPT('Mother Base','${aeskey}'), PGP_SYM_ENCRYPT('emmerichh@objectcomputing.com','${aeskey}'), '657483498', '2022-03-29', PGP_SYM_ENCRYPT('Waiting for love to bloom on the battlefield','${aeskey}'), 'dfe2f986-fac0-11eb-9a03-0242ac130003', '1943-07-04', '2022-03-29'); INSERT INTO member_profile -- Jacked Vulture (id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, last_seen) @@ -93,25 +98,25 @@ VALUES ('5b90beb2-0e96-438b-bfd6-1487a89b339b', PGP_SYM_ENCRYPT('Alice','${aeskey}'), PGP_SYM_ENCRYPT('Admin','${aeskey}'), PGP_SYM_ENCRYPT('System Administrator','${aeskey}'), 'a90be358-aa3d-49c8-945a-879a93646e45', PGP_SYM_ENCRYPT('St. Louis, MO','${aeskey}'), PGP_SYM_ENCRYPT('admina@objectcomputing.com','${aeskey}'), '123123451', '2012-09-29', PGP_SYM_ENCRYPT('Amazing Administrator','${aeskey}'), '72655c4f-1fb8-4514-b31e-7f7e19fa9bd7', '2012-09-29'); INSERT INTO member_profile -- Faux Freddy -(id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) + (id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) VALUES -('2dee821c-de32-4d9c-9ecb-f73e5903d17a', PGP_SYM_ENCRYPT('Faux','${aeskey}'), PGP_SYM_ENCRYPT('Freddy','${aeskey}'), PGP_SYM_ENCRYPT('Test Engineer','${aeskey}'), '1c813446-c65a-4f49-b980-0193f7bfff8c', PGP_SYM_ENCRYPT('St. Louis','${aeskey}'), PGP_SYM_ENCRYPT('testing@objectcomputing.com','${aeskey}'), '010101011', '2021-05-22', PGP_SYM_ENCRYPT('Test user 1','${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', '1950-01-01', '2021-05-22'); + ('2dee821c-de32-4d9c-9ecb-f73e5903d17a', PGP_SYM_ENCRYPT('Faux','${aeskey}'), PGP_SYM_ENCRYPT('Freddy','${aeskey}'), PGP_SYM_ENCRYPT('Test Engineer','${aeskey}'), '1c813446-c65a-4f49-b980-0193f7bfff8c', PGP_SYM_ENCRYPT('St. Louis','${aeskey}'), PGP_SYM_ENCRYPT('testing@objectcomputing.com','${aeskey}'), '010101011', '2021-05-22', PGP_SYM_ENCRYPT('Test user 1','${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', '1950-01-01', '2021-05-22'); INSERT INTO member_profile -- Revolver Ocelot -(id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) + (id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) VALUES -('105f2968-a182-45a3-892c-eeff76383fe0', PGP_SYM_ENCRYPT('Revolver','${aeskey}'), PGP_SYM_ENCRYPT('Ocelot','${aeskey}'), PGP_SYM_ENCRYPT('Head of Sales, HR, Management','${aeskey}'), 'dfe2f986-fac0-11eb-9a03-0242ac130003', PGP_SYM_ENCRYPT('Mother Base','${aeskey}'), PGP_SYM_ENCRYPT('ocelotr@objectcomputing.com','${aeskey}'), '489102361', '2022-03-29', PGP_SYM_ENCRYPT('Loves to reload during battle','${aeskey}'), 'dfe2f986-fac0-11eb-9a03-0242ac130003', '1943-07-04', '2022-03-29') -; + ('105f2968-a182-45a3-892c-eeff76383fe0', PGP_SYM_ENCRYPT('Revolver','${aeskey}'), PGP_SYM_ENCRYPT('Ocelot','${aeskey}'), PGP_SYM_ENCRYPT('Head of Sales, HR, Management','${aeskey}'), 'dfe2f986-fac0-11eb-9a03-0242ac130003', PGP_SYM_ENCRYPT('Mother Base','${aeskey}'), PGP_SYM_ENCRYPT('ocelotr@objectcomputing.com','${aeskey}'), '489102361', '2022-03-29', PGP_SYM_ENCRYPT('Loves to reload during battle','${aeskey}'), 'dfe2f986-fac0-11eb-9a03-0242ac130003', '1943-07-04', '2022-03-29'); + INSERT INTO member_profile -- Lucky Bear -(id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) + (id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) VALUES -('3455c391-c5dd-4c84-8d00-1e345711987f', PGP_SYM_ENCRYPT('Lucky','${aeskey}'), PGP_SYM_ENCRYPT('Bear','${aeskey}'), PGP_SYM_ENCRYPT('Developer','${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', PGP_SYM_ENCRYPT('South FL','${aeskey}'), PGP_SYM_ENCRYPT('belottol@objectcomputing.com','${aeskey}'), '728364519', '2021-09-07', PGP_SYM_ENCRYPT('You make your own luck','${aeskey}'), '72655c4f-1fb8-4514-b31e-7f7e19fa9bd7', '1950-12-01', '2024-08-28') -; + ('3455c391-c5dd-4c84-8d00-1e345711987f', PGP_SYM_ENCRYPT('Lucky','${aeskey}'), PGP_SYM_ENCRYPT('Bear','${aeskey}'), PGP_SYM_ENCRYPT('Developer','${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', PGP_SYM_ENCRYPT('South FL','${aeskey}'), PGP_SYM_ENCRYPT('belottol@objectcomputing.com','${aeskey}'), '728364519', '2021-09-07', PGP_SYM_ENCRYPT('You make your own luck','${aeskey}'), '72655c4f-1fb8-4514-b31e-7f7e19fa9bd7', '1950-12-01', '2024-08-28'); + INSERT INTO member_profile -- Wiley Tiger -(id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) + (id, firstName, lastName, title, pdlid, location, workEmail, employeeid, startdate, biotext, supervisorid, birthDate, last_seen) VALUES -('a44fc66a-86b0-4f15-8459-e7d4b4ecc330', PGP_SYM_ENCRYPT('Wiley','${aeskey}'), PGP_SYM_ENCRYPT('Tiger','${aeskey}'), PGP_SYM_ENCRYPT('Developer','${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', PGP_SYM_ENCRYPT('St. Louis','${aeskey}'), PGP_SYM_ENCRYPT('thelenw@objectcomputing.com','${aeskey}'), '728364510', '2024-09-23', PGP_SYM_ENCRYPT('You make your own luck','${aeskey}'), '72655c4f-1fb8-4514-b31e-7f7e19fa9bd7', '1950-12-01', '2024-09-23') -; + ('a44fc66a-86b0-4f15-8459-e7d4b4ecc330', PGP_SYM_ENCRYPT('Wiley','${aeskey}'), PGP_SYM_ENCRYPT('Tiger','${aeskey}'), PGP_SYM_ENCRYPT('Developer','${aeskey}'), 'e4b2fe52-1915-4544-83c5-21b8f871f6db', PGP_SYM_ENCRYPT('St. Louis','${aeskey}'), PGP_SYM_ENCRYPT('thelenw@objectcomputing.com','${aeskey}'), '728364510', '2024-09-23', PGP_SYM_ENCRYPT('You make your own luck','${aeskey}'), '72655c4f-1fb8-4514-b31e-7f7e19fa9bd7', '1950-12-01', '2024-09-23'); + -- Roles INSERT INTO role (id, description, role) @@ -135,6 +140,11 @@ INSERT INTO member_roles VALUES ('e8a4fff8-e984-4e59-be84-a713c9fa8d23', 'e4b2fe52-1915-4544-83c5-21b8f871f6db'); -- Mischievous Kangaroo +INSERT INTO member_roles +(roleid, memberid) +VALUES + ('e8a4fff8-e984-4e59-be84-a713c9fa8d23', '2b067cbb-45c2-4c3c-a6b2-eea370f9d969'); -- Derelict Reindeer + INSERT INTO member_roles (roleid, memberid) VALUES @@ -171,6 +181,11 @@ INSERT INTO member_roles VALUES ('d03f5f0b-e29c-4cf4-9ea4-6baa09405c56', 'e4b2fe52-1915-4544-83c5-21b8f871f6db'); -- Mischievous Kangaroo +INSERT INTO member_roles +(roleid, memberid) +VALUES + ('d03f5f0b-e29c-4cf4-9ea4-6baa09405c56', '2b067cbb-45c2-4c3c-a6b2-eea370f9d969'); + INSERT INTO member_roles (roleid, memberid) VALUES @@ -223,6 +238,11 @@ INSERT INTO member_roles VALUES ('8bda2ae9-58c1-4843-a0d5-d0952621f9df', 'c7406157-a38f-4d48-aaed-04018d846727'); -- Crazy Elephant +INSERT INTO member_roles +(roleid, memberid) +VALUES + ('8bda2ae9-58c1-4843-a0d5-d0952621f9df', '2b067cbb-45c2-4c3c-a6b2-eea370f9d969'); -- Derelict Reindeer + INSERT INTO member_roles (roleid, memberid) VALUES diff --git a/server/src/main/resources/logback.xml b/server/src/main/resources/logback.xml index fdc4168a0d..fd7c471b63 100644 --- a/server/src/main/resources/logback.xml +++ b/server/src/main/resources/logback.xml @@ -15,5 +15,7 @@ + + diff --git a/server/src/test/java/com/objectcomputing/checkins/notifications/email/MailJetSenderTest.java b/server/src/test/java/com/objectcomputing/checkins/notifications/email/MailJetSenderTest.java index 94c643264f..a57ab43c41 100644 --- a/server/src/test/java/com/objectcomputing/checkins/notifications/email/MailJetSenderTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/notifications/email/MailJetSenderTest.java @@ -1,6 +1,8 @@ package com.objectcomputing.checkins.notifications.email; import com.objectcomputing.checkins.services.TestContainersSuite; +import io.micronaut.context.annotation.Property; +import io.micronaut.core.util.StringUtils; import io.micronaut.inject.qualifiers.Qualifiers; import org.json.JSONArray; import org.junit.jupiter.api.Test; @@ -14,6 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; +@Property(name = "replace.settingsservicesimpl", value = StringUtils.TRUE) class MailJetSenderTest extends TestContainersSuite { @Test diff --git a/server/src/test/java/com/objectcomputing/checkins/security/GoogleServiceConfigurationTest.java b/server/src/test/java/com/objectcomputing/checkins/security/GoogleServiceConfigurationTest.java index 3f16d3b461..b177425299 100644 --- a/server/src/test/java/com/objectcomputing/checkins/security/GoogleServiceConfigurationTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/security/GoogleServiceConfigurationTest.java @@ -45,9 +45,9 @@ void testConstraintViolation() { GoogleServiceConfiguration googleServiceConfiguration = new GoogleServiceConfiguration(); Set> violations = validator.validate(googleServiceConfiguration); - assertEquals(2, violations.size()); + assertEquals(1, violations.size()); assertEquals( - List.of("directoryId:must not be null", "encodedValue:must be a valid base64 encoded Google Service Configuration"), + List.of("encodedValue:must be a valid base64 encoded Google Service Configuration"), violations.stream().map(v -> v.getPropertyPath() + ":" + v.getMessage()).toList() ); } @@ -55,7 +55,6 @@ void testConstraintViolation() { @Test void testConstraintViolationPasses() { GoogleServiceConfiguration googleServiceConfiguration = new GoogleServiceConfiguration(); - googleServiceConfiguration.setDirectoryId("some.directory.id"); googleServiceConfiguration.setEncodedValue(ENCODED_EXAMPLE_GOOGLE_SERVICE_CONFIGURATION); Set> violations = validator.validate(googleServiceConfiguration); @@ -65,19 +64,14 @@ void testConstraintViolationPasses() { @Test void testConfigurationLoadedCorrectlyFromConfiguration() throws IOException { var values = Map.ofEntries( - Map.entry("directory", "some.directory.id"), Map.entry("encoded-gcp-credentials", ENCODED_EXAMPLE_GOOGLE_SERVICE_CONFIGURATION) ); try (var ctx = ApplicationContext.run(Map.ofEntries( Map.entry("datasources.default.enabled", false), - Map.entry("service-account-credentials.directory-id", values.get("directory")), Map.entry("service-account-credentials.encoded-value", values.get("encoded-gcp-credentials")) ))) { var cfg = ctx.getBean(GoogleServiceConfiguration.class); - assertNotNull(cfg.getDirectoryId()); - assertEquals(values.get("directory"), cfg.getDirectoryId()); - assertNotNull(cfg.getEncodedValue()); assertEquals(values.get("encoded-gcp-credentials"), cfg.getEncodedValue()); } diff --git a/server/src/test/java/com/objectcomputing/checkins/services/SettingsServicesImplReplacement.java b/server/src/test/java/com/objectcomputing/checkins/services/SettingsServicesImplReplacement.java new file mode 100644 index 0000000000..146780c81f --- /dev/null +++ b/server/src/test/java/com/objectcomputing/checkins/services/SettingsServicesImplReplacement.java @@ -0,0 +1,68 @@ +package com.objectcomputing.checkins.services; + +import com.objectcomputing.checkins.exceptions.NotFoundException; +import com.objectcomputing.checkins.services.settings.Setting; +import com.objectcomputing.checkins.services.settings.SettingsServicesImpl; +import com.objectcomputing.checkins.services.settings.SettingsServices; + +import java.util.*; + +import jakarta.inject.Singleton; +import io.micronaut.core.util.StringUtils; +import io.micronaut.context.annotation.Replaces; +import io.micronaut.context.annotation.Requires; + +@Singleton +@Replaces(SettingsServicesImpl.class) +@Requires(property = "replace.settingsservicesimpl", value = StringUtils.TRUE) +public class SettingsServicesImplReplacement implements SettingsServices { + private HashMap map = new HashMap<>(); + + public SettingsServicesImplReplacement() { + } + + // ******************************************************************* + // Test Interface + // ******************************************************************* + public void reset() { + map.clear(); + } + + @Override + public Setting save(Setting setting) { + Setting newSetting = new Setting(UUID.randomUUID(), setting.getName(), setting.getValue()); + map.put(setting.getName(), newSetting); + return newSetting; + } + + @Override + public Setting update(String name, String value) { + Setting found = map.get(name); + if(found != null) found.setValue(value); + else return save(new Setting(name, value)); + return found; + } + + @Override + public Setting findByName(String name) { + Setting found = map.get(name); + if(found == null) throw new NotFoundException("Setting with name " + name + " not found."); + return found; + } + + @Override + public List findAllSettings() { + List settings = Arrays.stream((Setting[]) map.values().toArray()).toList(); + return settings; + } + + @Override + public boolean delete(UUID id) { + Optional found = map.values().stream().filter((current -> current.getId().equals(id))).findFirst(); + if(found.isPresent()) { + map.remove(found.get().getName()); + return true; + } + return false; + } +} diff --git a/server/src/test/java/com/objectcomputing/checkins/services/feedback/suggestions/FeedbackSuggestionsControllerTest.java b/server/src/test/java/com/objectcomputing/checkins/services/feedback/suggestions/FeedbackSuggestionsControllerTest.java index 7b359649f2..e8db228f67 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/feedback/suggestions/FeedbackSuggestionsControllerTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/feedback/suggestions/FeedbackSuggestionsControllerTest.java @@ -10,7 +10,9 @@ import com.objectcomputing.checkins.services.role.RoleType; import com.objectcomputing.checkins.services.team.Team; import com.objectcomputing.checkins.services.team.member.TeamMember; +import io.micronaut.context.annotation.Property; import io.micronaut.core.type.Argument; +import io.micronaut.core.util.StringUtils; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; import io.micronaut.http.HttpStatus; @@ -24,6 +26,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +@Property(name = "replace.settingsservicesimpl", value = StringUtils.TRUE) class FeedbackSuggestionsControllerTest extends TestContainersSuite implements MemberProfileFixture, TeamMemberFixture, TeamFixture, FeedbackFixture, RoleFixture { private final String supervisorReason = "Supervisor of requestee"; diff --git a/server/src/test/java/com/objectcomputing/checkins/services/feedback_answer/question_and_answer/QuestionAndAnswerControllerTest.java b/server/src/test/java/com/objectcomputing/checkins/services/feedback_answer/question_and_answer/QuestionAndAnswerControllerTest.java index 36f4a5a57b..bff9e4a28c 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/feedback_answer/question_and_answer/QuestionAndAnswerControllerTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/feedback_answer/question_and_answer/QuestionAndAnswerControllerTest.java @@ -8,7 +8,9 @@ import com.objectcomputing.checkins.services.fixture.*; import com.objectcomputing.checkins.services.memberprofile.MemberProfile; import com.objectcomputing.checkins.services.role.RoleType; +import io.micronaut.context.annotation.Property; import io.micronaut.core.type.Argument; +import io.micronaut.core.util.StringUtils; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; import io.micronaut.http.HttpStatus; @@ -25,6 +27,7 @@ import static com.objectcomputing.checkins.services.validate.PermissionsValidation.NOT_AUTHORIZED_MSG; import static org.junit.jupiter.api.Assertions.*; +@Property(name = "replace.settingsservicesimpl", value = StringUtils.TRUE) class QuestionAndAnswerControllerTest extends TestContainersSuite implements FeedbackAnswerFixture, TemplateQuestionFixture, MemberProfileFixture, FeedbackTemplateFixture, FeedbackRequestFixture, RoleFixture { @Inject diff --git a/server/src/test/java/com/objectcomputing/checkins/services/file/FileControllerTest.java b/server/src/test/java/com/objectcomputing/checkins/services/file/FileControllerTest.java index 89eec1f0bf..0fa0972ac2 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/file/FileControllerTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/file/FileControllerTest.java @@ -45,6 +45,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @Property(name = "replace.fileservicesimpl", value = StringUtils.TRUE) +@Property(name = "replace.settingsservicesimpl", value = StringUtils.TRUE) class FileControllerTest extends TestContainersSuite implements MemberProfileFixture, CheckInFixture, CheckInDocumentFixture, RoleFixture { diff --git a/server/src/test/java/com/objectcomputing/checkins/services/file/FileServicesImplTest.java b/server/src/test/java/com/objectcomputing/checkins/services/file/FileServicesImplTest.java index 2e55b051b3..79bb81e62b 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/file/FileServicesImplTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/file/FileServicesImplTest.java @@ -3,48 +3,30 @@ import com.objectcomputing.checkins.exceptions.PermissionException; import com.objectcomputing.checkins.exceptions.BadArgException; import com.objectcomputing.checkins.exceptions.NotFoundException; -import com.objectcomputing.checkins.security.GoogleServiceConfiguration; import com.objectcomputing.checkins.services.TestContainersSuite; import com.objectcomputing.checkins.services.checkindocument.CheckinDocument; -import com.objectcomputing.checkins.services.checkindocument.CheckinDocumentServices; import com.objectcomputing.checkins.services.checkins.CheckIn; -import com.objectcomputing.checkins.services.checkins.CheckInServices; import com.objectcomputing.checkins.services.memberprofile.MemberProfile; -import com.objectcomputing.checkins.services.memberprofile.MemberProfileServices; -import com.objectcomputing.checkins.services.memberprofile.MemberProfileUtils; import com.objectcomputing.checkins.services.CurrentUserServicesReplacement; +import com.objectcomputing.checkins.services.SettingsServicesImplReplacement; import com.objectcomputing.checkins.services.FileServicesImplReplacement; import com.objectcomputing.checkins.services.fixture.MemberProfileFixture; import com.objectcomputing.checkins.services.fixture.CheckInFixture; import com.objectcomputing.checkins.services.fixture.CheckInDocumentFixture; import com.objectcomputing.checkins.services.fixture.RoleFixture; -import com.objectcomputing.checkins.services.role.RoleType; import io.micronaut.http.multipart.CompletedFileUpload; import io.micronaut.http.MediaType; -import io.micronaut.security.authentication.Authentication; import io.micronaut.context.annotation.Property; import io.micronaut.core.util.StringUtils; import jakarta.inject.Inject; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.ByteArrayInputStream; -import java.io.OutputStream; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.Optional; @@ -57,6 +39,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @Property(name = "replace.fileservicesimpl", value = StringUtils.TRUE) +@Property(name = "replace.settingsservicesimpl", value = StringUtils.TRUE) @Property(name = "replace.currentuserservices", value = StringUtils.TRUE) class FileServicesImplTest extends TestContainersSuite implements MemberProfileFixture, CheckInFixture, CheckInDocumentFixture, RoleFixture { @@ -125,6 +108,9 @@ public InputStream getInputStream() throws IOException { @Inject private FileServicesImplReplacement services; + @Inject + private SettingsServicesImplReplacement settingsService; + private CheckIn checkIn; private MemberProfile pdl; private MemberProfile member; @@ -132,6 +118,7 @@ public InputStream getInputStream() throws IOException { @BeforeEach void reset() { services.reset(); + settingsService.reset(); createAndAssignRoles(); diff --git a/server/src/test/java/com/objectcomputing/checkins/services/kudos/SlackKudosTest.java b/server/src/test/java/com/objectcomputing/checkins/services/kudos/SlackKudosTest.java index 893b9cf368..e7ca8e5512 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/kudos/SlackKudosTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/kudos/SlackKudosTest.java @@ -48,6 +48,7 @@ @Property(name = "replace.slacksearch", value = StringUtils.TRUE) @Property(name = "replace.slackreader", value = StringUtils.TRUE) @Property(name = "replace.slacksender", value = StringUtils.TRUE) +@Property(name = "replace.settingsservicesimpl", value = StringUtils.TRUE) class SlackKudosTest extends TestContainersSuite implements MemberProfileFixture, AutomatedKudosFixture, RoleFixture { @Inject private SlackReaderReplacement slackReader; diff --git a/server/src/test/java/com/objectcomputing/checkins/services/member_skill/skillsreport/SkillsReportServicesImplTest.java b/server/src/test/java/com/objectcomputing/checkins/services/member_skill/skillsreport/SkillsReportServicesImplTest.java index fd2d6b0d6a..ff7452f685 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/member_skill/skillsreport/SkillsReportServicesImplTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/member_skill/skillsreport/SkillsReportServicesImplTest.java @@ -39,6 +39,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @Property(name = "replace.currentuserservices", value = StringUtils.TRUE) +@Property(name = "replace.settingsservicesimpl", value = StringUtils.TRUE) class SkillsReportServicesImplTest extends TestContainersSuite implements MemberProfileFixture, MemberSkillFixture, SkillFixture, RoleFixture { @Inject diff --git a/server/src/test/java/com/objectcomputing/checkins/services/memberprofile/csvreport/MemberProfileReportServicesImplTest.java b/server/src/test/java/com/objectcomputing/checkins/services/memberprofile/csvreport/MemberProfileReportServicesImplTest.java index 7f8cf00bcd..492e894888 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/memberprofile/csvreport/MemberProfileReportServicesImplTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/memberprofile/csvreport/MemberProfileReportServicesImplTest.java @@ -33,6 +33,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; @Property(name = "replace.currentuserservices", value = StringUtils.TRUE) +@Property(name = "replace.settingsservicesimpl", value = StringUtils.TRUE) class MemberProfileReportServicesImplTest extends TestContainersSuite implements MemberProfileFixture, RoleFixture { @Inject diff --git a/server/src/test/java/com/objectcomputing/checkins/services/memberprofile/currentuser/CurrentUserControllerTest.java b/server/src/test/java/com/objectcomputing/checkins/services/memberprofile/currentuser/CurrentUserControllerTest.java index 69737baef6..69b07437f9 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/memberprofile/currentuser/CurrentUserControllerTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/memberprofile/currentuser/CurrentUserControllerTest.java @@ -6,7 +6,9 @@ import com.objectcomputing.checkins.services.memberprofile.MemberProfile; import com.objectcomputing.checkins.services.role.Role; import com.objectcomputing.checkins.services.role.RoleType; +import io.micronaut.context.annotation.Property; import io.micronaut.core.annotation.NonNull; +import io.micronaut.core.util.StringUtils; import io.micronaut.http.HttpResponse; import io.micronaut.http.HttpStatus; import io.micronaut.security.authentication.Authentication; @@ -22,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +@Property(name = "replace.settingsservicesimpl", value = StringUtils.TRUE) class CurrentUserControllerTest extends TestContainersSuite implements MemberProfileFixture, RoleFixture { private static final Map userAttributes = new HashMap<>(); diff --git a/server/src/test/java/com/objectcomputing/checkins/services/reports/ReportDataControllerTest.java b/server/src/test/java/com/objectcomputing/checkins/services/reports/ReportDataControllerTest.java index 6a5010ff71..36b37273e0 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/reports/ReportDataControllerTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/reports/ReportDataControllerTest.java @@ -47,6 +47,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; @Property(name = "replace.fileservicesimpl", value = StringUtils.TRUE) +@Property(name = "replace.settingsservicesimpl", value = StringUtils.TRUE) class ReportDataControllerTest extends TestContainersSuite implements MemberProfileFixture, RoleFixture, KudosFixture, ReviewPeriodFixture, FeedbackTemplateFixture, FeedbackRequestFixture, TemplateQuestionFixture, FeedbackAnswerFixture, EmployeeHoursFixture { @Inject diff --git a/server/src/test/java/com/objectcomputing/checkins/services/settings/SettingsControllerTest.java b/server/src/test/java/com/objectcomputing/checkins/services/settings/SettingsControllerTest.java index 75b12dab70..5c3032fe3d 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/settings/SettingsControllerTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/settings/SettingsControllerTest.java @@ -119,10 +119,14 @@ void testPUTValidDTOButSettingNotFound() { updatedSetting.setValue("Missing"); final HttpRequest request = HttpRequest. PUT("/", updatedSetting).basicAuth(lucy.getWorkEmail(),ADMIN_ROLE); - HttpClientResponseException responseException = assertThrows(HttpClientResponseException.class, - () -> client.toBlocking().exchange(request, Map.class)); - assertEquals(HttpStatus.NOT_FOUND, responseException.getStatus()); - assertEquals("Setting with name %s not found.".formatted(SettingOption.LOGO_URL.toString()), responseException.getMessage()); + + final HttpResponse response = client.toBlocking().exchange(request,SettingsResponseDTO.class); + + assertNotNull(response); + assertEquals(HttpStatus.OK,response.getStatus()); + assertEquals(updatedSetting.getName(), response.body().getName()); + assertEquals(updatedSetting.getValue(), response.body().getValue()); + } @Test diff --git a/server/src/test/java/com/objectcomputing/checkins/services/today/TodayControllerTest.java b/server/src/test/java/com/objectcomputing/checkins/services/today/TodayControllerTest.java index 2ba2ad0c21..e70fb6c6d5 100644 --- a/server/src/test/java/com/objectcomputing/checkins/services/today/TodayControllerTest.java +++ b/server/src/test/java/com/objectcomputing/checkins/services/today/TodayControllerTest.java @@ -4,6 +4,8 @@ import com.objectcomputing.checkins.services.fixture.MemberProfileFixture; import com.objectcomputing.checkins.services.fixture.RoleFixture; import com.objectcomputing.checkins.services.memberprofile.MemberProfile; +import io.micronaut.context.annotation.Property; +import io.micronaut.core.util.StringUtils; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; import io.micronaut.http.HttpStatus; @@ -15,6 +17,7 @@ import static com.objectcomputing.checkins.services.role.RoleType.Constants.MEMBER_ROLE; import static org.junit.jupiter.api.Assertions.assertEquals; +@Property(name = "replace.settingsservicesimpl", value = StringUtils.TRUE) class TodayControllerTest extends TestContainersSuite implements MemberProfileFixture, RoleFixture { @Inject diff --git a/web-ui/src/pages/SettingsPage.jsx b/web-ui/src/pages/SettingsPage.jsx index 45a17dc9d0..79c9e5bbb5 100644 --- a/web-ui/src/pages/SettingsPage.jsx +++ b/web-ui/src/pages/SettingsPage.jsx @@ -42,7 +42,7 @@ const SettingsPage = () => { const allOptions = selectHasViewSettingsPermission(state) || selectHasAdministerSettingsPermission(state) - ? (await getAllOptions()).payload.data + ? (await getAllOptions(csrf)).payload.data : []; if (allOptions) {