diff --git a/buildSrc/src/main/groovy/flexwork.docker-conventions.gradle b/buildSrc/src/main/groovy/flexwork.docker-conventions.gradle index 06de6bfc..1359f2e7 100644 --- a/buildSrc/src/main/groovy/flexwork.docker-conventions.gradle +++ b/buildSrc/src/main/groovy/flexwork.docker-conventions.gradle @@ -7,13 +7,14 @@ jib { image = "eclipse-temurin:17-jre-focal" platforms { platform { - architecture = "${findProperty('jibArchitecture') ?: 'amd64'}" os = "linux" + architecture = "amd64" } } } to { - image = "theflexwork/flexwork-server-community:latest" + image = "theflexwork/flexwork-server" + tags = ['latest', findProperty('projectVersion')] } container { entrypoint = ["bash", "-c", "/entrypoint.sh"] diff --git a/docker/jib/entrypoint.sh b/docker/jib/entrypoint.sh index 6b9e687a..3fc3277b 100644 --- a/docker/jib/entrypoint.sh +++ b/docker/jib/entrypoint.sh @@ -31,8 +31,5 @@ file_env() { file_env 'SPRING_DATASOURCE_URL' file_env 'SPRING_DATASOURCE_USERNAME' file_env 'SPRING_DATASOURCE_PASSWORD' -file_env 'SPRING_LIQUIBASE_URL' -file_env 'SPRING_LIQUIBASE_USER' -file_env 'SPRING_LIQUIBASE_PASSWORD' -exec java ${JAVA_OPTS} -noverify -XX:+AlwaysPreTouch -Djava.security.egd=file:/dev/./urandom -cp /app/resources/:/app/classes/:/app/libs/* "io.flexwork.FlexworkApp" "$@" +exec java ${JAVA_OPTS} -XX:+AlwaysPreTouch -Djava.security.egd=file:/dev/./urandom -cp /app/resources/:/app/classes/:/app/libs/* "io.flexwork.FlexworkApp" "$@" diff --git a/gradle.properties b/gradle.properties index f7283516..ad8444c5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,6 @@ rootProject.name=flexwork-app profile=dev +projectVersion=0.0.1 # gradle plugin version gitPropertiesPluginVersion=2.4.2 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8f8dce9c..63615a6d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,17 +3,17 @@ mapstructVersion = "1.6.2" archunitJunit5Version = "1.3.0" springStateMachineVersion = "4.0.0" lombokVersion = "1.18.34" -liquibaseVersion = "4.29.2" +liquibaseVersion = "4.30.0" assertJVersion = "3.26.3" jcloudsVersion = "2.6.0" -dotEnvVersion = "3.0.0" +dotEnvVersion = "3.0.2" logbackVersion = "1.5.9" junitVersion = "5.11.2" mockitoVersion = "5.2.0" mockitoJunitVersion = "5.14.1" jsonApiVersion = "2.1.3" parssonVersion="1.1.7" -springbootVersion = "3.3.4" +springbootVersion = "3.3.5" springDependencyManagementVersion="1.1.6" jhisterVersion = "8.7.1" diff --git a/scripts/create_secrets.sh b/scripts/create_secrets.sh index 9e2f5044..dc4f7b30 100755 --- a/scripts/create_secrets.sh +++ b/scripts/create_secrets.sh @@ -5,7 +5,7 @@ read -sp "Enter your database password: " db_password echo # Define the output script that will store the sensitive data -output_script="./.env.local" +output_file="./.env.local" # Function to update or add key-value pairs update_or_add() { @@ -24,12 +24,12 @@ update_or_add() { } # Create the file if it doesn't exist -if [ ! -f "$output_script" ]; then - echo "#!/bin/bash" > "$output_script" +if [ ! -f "$output_file" ]; then + echo "#!/bin/bash" > "$output_file" fi # Write the sensitive data to the output script -update_or_add "POSTGRES_PASSWORD" "$db_password" "$output_script" +update_or_add "POSTGRES_PASSWORD" "$db_password" "$output_file" # Generate a random alphanumeric string with a length of 50 random_string=$(LC_CTYPE=C tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 90 | head -n 1) @@ -38,9 +38,9 @@ random_string=$(LC_CTYPE=C tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 90 | head encoded_string=$(echo -n "$random_string" | base64) echo $encoded_string -update_or_add "JWT_BASE64_SECRET" "$encoded_string" "$output_script" +update_or_add "JWT_BASE64_SECRET" "$encoded_string" "$output_file" # Set permissions to restrict access to the file -chmod 644 "$output_script" +chmod 644 "$output_file" -echo "Sensitive data has been written to $output_script with restricted permissions." \ No newline at end of file +echo "Sensitive data has been written to $output_file with restricted permissions." \ No newline at end of file diff --git a/scripts/mail_config.sh b/scripts/mail_config.sh index a84f0eba..356c6f87 100755 --- a/scripts/mail_config.sh +++ b/scripts/mail_config.sh @@ -64,28 +64,27 @@ done # Define the output script that will store the sensitive data -output_script=".env.local" +output_file=".env.local" -# Create a backup if the file already exists -if [ -f "$output_script" ]; then - cp "$output_script" "${output_script}.backup" - echo "Backup of .env.local created as .env.local.backup" +# Check if the file exists; if not, create it +if [ ! -f "$output_file" ]; then + touch "$output_file" fi # Function to add or update a key-value pair in the .env.local file add_or_update_env_var() { local key="$1" local value="$2" - if grep -q "^$key=" "$output_script" 2>/dev/null; then + if grep -q "^$key=" "$output_file" 2>/dev/null; then # If key exists, update its value if [[ "$OSTYPE" == "darwin"* ]]; then - sed -i '' "s|^$key=.*|$key=$value|" "$output_script" # macOS + sed -i '' "s|^$key=.*|$key=$value|" "$output_file" # macOS else - sed -i "s|^$key=.*|$key=$value|" "$output_script" # Linux + sed -i "s|^$key=.*|$key=$value|" "$output_file" # Linux fi else # If key does not exist, add it to the file - echo "$key=$value" >> "$output_script" + echo "$key=$value" >> "$output_file" fi } @@ -99,7 +98,7 @@ add_or_update_env_var "spring.mail.username" "$smtp_username" add_or_update_env_var "spring.mail.password" "$smtp_password" add_or_update_env_var "spring.mail.properties.mail.smtp.auth" "true" add_or_update_env_var "flexwork.mail.from" $sender_email -add_or_update_env_var "flexwork.mail.base-url" $base_url_email +add_or_update_env_var "flexwork.mail.base_url" $base_url_email # Add STARTTLS settings if required if [[ "$requires_starttls" == "y" ]]; then @@ -108,5 +107,5 @@ if [[ "$requires_starttls" == "y" ]]; then fi # Set permissions to restrict access to the file -chmod 644 "$output_script" +chmod 644 "$output_file" echo "Configuration has been saved to .env.local" diff --git a/server/src/main/java/io/flexwork/config/FlexworkProperties.java b/server/src/main/java/io/flexwork/config/FlexworkProperties.java index 0215a697..edb74fc1 100644 --- a/server/src/main/java/io/flexwork/config/FlexworkProperties.java +++ b/server/src/main/java/io/flexwork/config/FlexworkProperties.java @@ -15,6 +15,8 @@ public class FlexworkProperties { private final Cache cache = new Cache(); + private final Security security = new Security(); + private final CorsConfiguration cors = new CorsConfiguration(); @Getter @@ -47,4 +49,22 @@ public static class Cache { private int timeToLiveInDays = 1461; } } + + @Getter + public static class Security { + private final Authentication authentication = new Authentication(); + + @Getter + public static class Authentication { + final Jwt jwt = new Jwt(); + + @Getter + @Setter + public static class Jwt { + private String base64Secret; + private long tokenValidityInSeconds; + private long tokenValidityInSecondsForRememberMe; + } + } + } } diff --git a/server/src/main/java/io/flexwork/health/JWTSetupChecker.java b/server/src/main/java/io/flexwork/health/JWTSetupChecker.java new file mode 100644 index 00000000..a354d57b --- /dev/null +++ b/server/src/main/java/io/flexwork/health/JWTSetupChecker.java @@ -0,0 +1,31 @@ +package io.flexwork.health; + +import io.flexwork.config.FlexworkProperties; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +@Component +public class JWTSetupChecker implements ApplicationRunner { + + private static Logger LOG = LoggerFactory.getLogger(JWTSetupChecker.class); + + private final FlexworkProperties flexworkProperties; + + public JWTSetupChecker(FlexworkProperties flexworkProperties) { + this.flexworkProperties = flexworkProperties; + } + + @Override + public void run(ApplicationArguments args) { + if (StringUtils.isEmpty( + flexworkProperties.getSecurity().getAuthentication().getJwt().getBase64Secret())) { + throw new IllegalArgumentException("JWT secret is missing"); + } else { + LOG.info("JWT secret found and ready to use"); + } + } +} diff --git a/server/src/main/java/io/flexwork/health/MailSetupChecker.java b/server/src/main/java/io/flexwork/health/MailSetupChecker.java new file mode 100644 index 00000000..93329595 --- /dev/null +++ b/server/src/main/java/io/flexwork/health/MailSetupChecker.java @@ -0,0 +1,33 @@ +package io.flexwork.health; + +import io.flexwork.config.FlexworkProperties; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +@Component +@Profile("prod") +public class MailSetupChecker implements ApplicationRunner { + + private static Logger LOG = LoggerFactory.getLogger(MailSetupChecker.class); + + private final FlexworkProperties flexworkProperties; + + public MailSetupChecker(FlexworkProperties flexworkProperties) { + this.flexworkProperties = flexworkProperties; + } + + @Override + public void run(ApplicationArguments args) { + if (StringUtils.isEmpty(flexworkProperties.getMail().getBaseUrl()) + || !flexworkProperties.getMail().isEnabled()) { + LOG.warn("Email provider is not configured yet"); + } else { + LOG.info("Mail settings are found"); + } + } +} diff --git a/server/src/main/resources/config/application-dev.yml b/server/src/main/resources/config/application-dev.yml index a02290a6..a8735ecd 100644 --- a/server/src/main/resources/config/application-dev.yml +++ b/server/src/main/resources/config/application-dev.yml @@ -40,7 +40,7 @@ server: flexwork: mail: from: flexwork-app@localhost.com - base-url: http://127.0.0.1:3000 + base_url: http://127.0.0.1:3000 # CORS is only enabled by default with the "dev" profile cors: # Allow Ionic for JHipster by default (* no longer allowed in Spring Boot 2.4+) diff --git a/server/src/main/resources/config/application-prod.yml b/server/src/main/resources/config/application-prod.yml index ff2239e0..c38b3367 100644 --- a/server/src/main/resources/config/application-prod.yml +++ b/server/src/main/resources/config/application-prod.yml @@ -13,7 +13,7 @@ management: prometheus: metrics: export: - enabled: false + enabled: true spring: devtools: @@ -24,8 +24,8 @@ spring: datasource: type: com.zaxxer.hikari.HikariDataSource url: jdbc:postgresql://localhost:5432/flexApp - username: - password: + username: ${SPRING_DATASOURCE_USERNAME} + password: ${SPRING_DATASOURCE_PASSWORD} hikari: poolName: Hikari auto-commit: false @@ -82,9 +82,8 @@ flexwork: jwt: # This token must be encoded using Base64 and be at least 256 bits long (you can type `openssl rand -base64 64` on your command line to generate a 512 bits one) # As this is the PRODUCTION configuration, you MUST change the default key, and store it securely: - # - In the Consul configserver # - In a separate `application-prod.yml` file, in the same folder as your executable JAR file - base64-secret: + base64-secret: ${JWT_BASE64_SECRET} # Token is valid 24 hours token-validity-in-seconds: 86400 token-validity-in-seconds-for-remember-me: 2592000 diff --git a/server/src/main/resources/config/application.yml b/server/src/main/resources/config/application.yml index 253f3bc8..01550ba6 100644 --- a/server/src/main/resources/config/application.yml +++ b/server/src/main/resources/config/application.yml @@ -31,17 +31,9 @@ management: - env - health - info - - jhimetrics - - jhiopenapigroups - - logfile - - loggers - prometheus - - threaddump - - caches - - liquibase endpoint: health: - show-details: when_authorized roles: 'ROLE_ADMIN' probes: enabled: true diff --git a/server/src/main/resources/logback-spring.xml b/server/src/main/resources/logback-spring.xml index 8740ab60..d694869a 100644 --- a/server/src/main/resources/logback-spring.xml +++ b/server/src/main/resources/logback-spring.xml @@ -20,21 +20,21 @@ - - logs/masked-log.log - - %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - - %mask{%msg}%n - + + + + + + + - - - ERROR - ACCEPT - DENY - - + + + + + + + @@ -49,7 +49,6 @@ - @@ -63,8 +62,8 @@ - - + + @@ -87,7 +86,7 @@ source="logging.level.root" defaultValue="INFO" /> - + - + @@ -189,7 +190,7 @@ + id="00000000000000:02-table-for-tests" context="test"> + id="00000000000000:03-insert-default-authority-data" context="!test"> + + @@ -238,6 +242,10 @@ + + @@ -253,6 +261,9 @@ + + @@ -263,16 +274,28 @@ - + + - - + + - + + + separator=";" tableName="fw_resource" usePreparedStatements="true"> + + + + + - + @@ -357,7 +357,10 @@ - + + - + + @@ -393,7 +398,9 @@ - + + diff --git a/tools/liquibase/src/main/resources/config/liquibase/tenant/data/resource.csv b/tools/liquibase/src/main/resources/config/liquibase/tenant/data/resource.csv index aaeefd10..c396e950 100644 --- a/tools/liquibase/src/main/resources/config/liquibase/tenant/data/resource.csv +++ b/tools/liquibase/src/main/resources/config/liquibase/tenant/data/resource.csv @@ -1,8 +1,8 @@ name;description -User; -File; -Account; -Contact; -Case; -Team; -Organization; \ No newline at end of file +User;User Resource +File;File Resource +Account;Account Resource +Contact;Contact Resource +Case;Case Resource +Team;Team Resource +Organization;Organization Resource \ No newline at end of file