Explorar el Código

Dockerized, removed hardcoded values

Riccardo Balbo hace 4 años
padre
commit
245b22639a
Se han modificado 31 ficheros con 355 adiciones y 150 borrados
  1. 17 0
      .dockerignore
  2. 16 0
      .gitignore
  3. 51 0
      Dockerfile
  4. 11 0
      build-docker.sh
  5. 2 2
      build.gradle
  6. 12 0
      build.sh
  7. 29 0
      config/test-environment-config.json
  8. 6 4
      src/main/java/com/jayfella/website/config/EmailConfig.java
  9. 5 1
      src/main/java/com/jayfella/website/config/ThymeLeafConfig.java
  10. 3 3
      src/main/java/com/jayfella/website/config/external/DatabaseConfig.java
  11. 50 3
      src/main/java/com/jayfella/website/config/external/ServerConfig.java
  12. 1 1
      src/main/java/com/jayfella/website/controller/SitemapController.java
  13. 1 1
      src/main/java/com/jayfella/website/controller/api/ApiCategoryController.java
  14. 3 3
      src/main/java/com/jayfella/website/controller/api/ApiSearchController.java
  15. 1 1
      src/main/java/com/jayfella/website/controller/api/ApiValidationController.java
  16. 3 2
      src/main/java/com/jayfella/website/controller/http/IndexPageController.java
  17. 1 0
      src/main/java/com/jayfella/website/core/JsonMapper.java
  18. 14 14
      src/main/java/com/jayfella/website/service/EmailService.java
  19. 17 14
      src/main/java/com/jayfella/website/service/SitemapService.java
  20. 72 0
      testing-environment.sh
  21. 0 0
      www/images/database/.keep
  22. 8 9
      www/legal/cookies.html
  23. 17 17
      www/legal/tos.html
  24. 2 2
      www/mail/html/account-validation.html
  25. 2 2
      www/mail/html/page-approved.html
  26. 1 1
      www/mail/html/page-rejected.html
  27. 1 1
      www/mail/html/page-under-review.html
  28. 3 3
      www/mail/html/registration.html
  29. 4 4
      www/mail/html/reset-lost-password.html
  30. 2 2
      www/mail/html/review-requested.html
  31. 0 60
      www/sitemap.xml

+ 17 - 0
.dockerignore

@@ -0,0 +1,17 @@
+www/images/database/*
+dist/
+.gradle
+gradle
+gradlew
+gradlew.bat
+bin
+build
+**/sitemap.xml
+.project
+.settings
+.classpath
+test_environment
+dist
+config/server-config.json
+.git
+x.*

+ 16 - 0
.gitignore

@@ -0,0 +1,16 @@
+www/images/database/*
+!.keep
+.gradle
+gradle
+gradlew
+gradlew.bat
+bin
+build
+.project
+.settings
+.classpath
+test_environment
+dist
+config/server-config.json
+x.*
+deps.txt

+ 51 - 0
Dockerfile

@@ -0,0 +1,51 @@
+FROM azul/zulu-openjdk:8
+
+RUN apt update -y && apt upgrade -y && apt dist-upgrade -y
+
+RUN apt install -y curl unzip && apt clean
+
+
+RUN groupadd --gid 1000 nonroot 
+RUN useradd --uid 1000 -r --gid 1000 nonroot 
+
+COPY www /app_build/www
+COPY build-docker.sh /app_build
+COPY build.sh /app_build
+COPY src /app_build/src
+COPY build.gradle /app_build
+COPY settings.gradle /app_build
+
+# Install gradle
+RUN curl https://downloads.gradle-dn.com/distributions/gradle-6.7-bin.zip -o /tmp/gradle.zip
+RUN if [ "`sha256sum /tmp/gradle.zip | cut -d' ' -f1`" != "8ad57759019a9233dc7dc4d1a530cefe109dc122000d57f7e623f8cf4ba9dfc4" ];\
+    then \
+        echo "Error. This version of gradle is corrupted."; \
+        exit 1;\
+    fi && \
+    mkdir -p /tmp/gradle && \
+    unzip -q -d /tmp/gradle /tmp/gradle.zip &&\
+    cp -Rf /tmp/gradle/gradle-*/* / &&\
+    rm -Rf /tmp/gradle && rm -f /tmp/gradle.zip && \
+    echo "Installed gradle `gradle -v`"
+
+# Build
+RUN cd /app_build &&\
+    ./build.sh  && \
+    mv dist /app && \
+    cd / && \
+    rm -Rf /app_build
+
+RUN  chown 1000:1000 /app
+USER nonroot
+WORKDIR /app
+ENTRYPOINT [ "java","-Djava.io.tmpdir=/tmp/apptmp","-jar","SoftwareStore.jar" ]
+
+# Writable volumes
+VOLUME /app/www/images/database
+VOLUME /app/config
+
+# tmpfs
+VOLUME /app/sitemap
+
+# tmpfs
+VOLUME /tmp/apptmp

+ 11 - 0
build-docker.sh

@@ -0,0 +1,11 @@
+#!/bin/bash
+if [ "$RUNTIME" = "" ];
+then
+    export RUNTIME="`which podman`"
+    if [ "$RUNTIME" = "" ];
+    then
+        export RUNTIME="`which docker`"
+    fi
+fi
+$RUNTIME rmi jmestore
+$RUNTIME build -t jmestore .

+ 2 - 2
build.gradle

@@ -22,8 +22,8 @@ repositories {
 group 'com.jayfella'
 version '1.0.56'
 
-sourceCompatibility = 11
-targetCompatibility = 11
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
 
 mainClassName = "com.jayfella.website.Main"
 

+ 12 - 0
build.sh

@@ -0,0 +1,12 @@
+#!/bin/bash
+rm -Rf dist
+mkdir -p dist
+if [ "$GRADLE" = "" ];
+then
+    export GRADLE="`which gradle`"
+fi
+$GRADLE build
+cp build/libs/SoftwareStore-*.jar dist/SoftwareStore.jar
+cp -Rf www dist/
+
+

+ 29 - 0
config/test-environment-config.json

@@ -0,0 +1,29 @@
+{
+    "port" : 8080,
+    "site-name" : "jMonkeyEngine Store",
+    "site-hostname" : "store.jmonkeyengine.org",
+    "site-scheme" : "https",
+    "email" : "[email protected]",
+    "smtp-user" : "",
+    "smtp-password" : "",
+    "https-enabled" : false,
+    "database" : {
+      "type" : "mysql",
+      "address" : "jmestore-testing-mysql ",
+      "port" : 3306,
+      "name" : "jmestore",
+      "username" : "root",
+      "password" : "oEZi1nIeZwpS"
+    },
+    "security" : {
+      "pbkdfIterations" : 80000,
+      "passwordHashLength" : 512,
+      "saltHashLength" : 512
+    },
+    "website" : {
+      "registrationDisabled" : false,
+      "email-enabled" : false
+    },
+    "smtp-port" : 587,
+    "smtp-host" : "smtp.zoho.eu"
+  }

+ 6 - 4
src/main/java/com/jayfella/website/config/EmailConfig.java

@@ -15,6 +15,8 @@ import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.Properties;
 
+import com.jayfella.website.config.external.ServerConfig;
+
 @Configuration
 public class EmailConfig {
 
@@ -24,11 +26,11 @@ public class EmailConfig {
     public JavaMailSender getJavaMailSender() {
 
         JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
-        mailSender.setHost("smtp.zoho.eu");
-        mailSender.setPort(587);
+        mailSender.setHost(ServerConfig.getInstance().getSmtpHost());
+        mailSender.setPort(ServerConfig.getInstance().getSmtpPort());
 
-        mailSender.setUsername("[email protected]");
-        mailSender.setPassword("1MNMQDEVT3HS");
+        mailSender.setUsername(ServerConfig.getInstance().getSmtpUser());
+        mailSender.setPassword(ServerConfig.getInstance().getSmtpPassword());
 
         Properties props = mailSender.getJavaMailProperties();
         props.put("mail.transport.protocol", "smtp");

+ 5 - 1
src/main/java/com/jayfella/website/config/ThymeLeafConfig.java

@@ -17,6 +17,8 @@ import org.thymeleaf.templateresolver.ITemplateResolver;
 
 import java.nio.charset.StandardCharsets;
 
+import com.jayfella.website.config.external.ServerConfig;
+
 @Configuration
 @EnableWebMvc
 public class ThymeLeafConfig implements WebMvcConfigurer {
@@ -36,6 +38,7 @@ public class ThymeLeafConfig implements WebMvcConfigurer {
         templateResolver.setTemplateMode(TemplateMode.HTML);
         templateResolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
         templateResolver.setOrder(1);
+        
 
         return templateResolver;
     }
@@ -59,7 +62,8 @@ public class ThymeLeafConfig implements WebMvcConfigurer {
 
         viewResolver.setTemplateEngine(templateEngine());
         viewResolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
-
+        viewResolver.addStaticVariable("siteName", ServerConfig.getInstance().getSiteName());
+        viewResolver.addStaticVariable("websiteFullUrl", ServerConfig.getInstance().getFullUrl());
         return viewResolver;
     }
 

+ 3 - 3
src/main/java/com/jayfella/website/config/external/DatabaseConfig.java

@@ -7,9 +7,9 @@ public class DatabaseConfig {
     private String type = "mysql";
     private String address = "127.0.0.1";
     private int port = 3306;
-    private String name;
-    private String username;
-    private String password;
+    private String name="jmestore";
+    private String username="root";
+    private String password="oEZi1nIeZwpS";
 
     DatabaseConfig() {
     }

+ 50 - 3
src/main/java/com/jayfella/website/config/external/ServerConfig.java

@@ -1,5 +1,6 @@
 package com.jayfella.website.config.external;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.jayfella.website.core.JsonMapper;
 import org.slf4j.Logger;
@@ -18,7 +19,17 @@ public class ServerConfig {
     private static ServerConfig INSTANCE;
 
     private int port = 8080;
-    private String siteName = "My Website";
+    private String siteName = "jMonkeyEngine Store";
+    private String siteHostName="store.jmonkeyengine.org";
+    private String siteScheme="https";
+    private String email="[email protected]";
+
+
+    private String smtpUser="";
+    private String smtpPassword="";
+    private int smptPort=587;
+    private String smptHost="";
+
 
     // we use an nginx proxy on the server because it's easier to deal with SSL certificates.
     // this setting only sets the cookie values currently.
@@ -36,17 +47,53 @@ public class ServerConfig {
         return INSTANCE;
     }
 
-    private ServerConfig() {
+    public ServerConfig() {
     }
 
+    @JsonProperty("smtp-user")
+    public String getSmtpUser() { return smtpUser; }
+    public void setSmtpUser(String smtpUser) { this.smtpUser = smtpUser; }
+
+    @JsonProperty("smtp-password")
+    public String getSmtpPassword() { return smtpPassword; }
+    public void setSmtpPassword(String smtpPassword) { this.smtpPassword = smtpPassword; }
+
+    @JsonProperty("smtp-port")
+    public int getSmtpPort() { return smptPort; }
+    public void setSmtpPort(int smptPort) { this.smptPort = smptPort; }
+
+    @JsonProperty("smtp-host")
+    public String getSmtpHost() { return smptHost; }
+    public void setSmtpHost(String smptHost) { this.smptHost = smptHost; }
+
     @JsonProperty("port")
     public int getPort() { return port; }
     public void setPort(int port) { this.port = port; }
 
-    @JsonProperty("site-name")
+    @JsonProperty("site-name")       
     public String getSiteName() { return siteName; }
     public void setSiteName(String siteName) { this.siteName = siteName; }
 
+    @JsonProperty("site-hostname")   
+    public String getSiteHostName() { return siteHostName; }
+    public void setSiteHostName(String siteHostName) { this.siteHostName = siteHostName; }
+
+    @JsonProperty("site-scheme")  
+    public String getSiteScheme() { return siteScheme; }
+    public void setSiteScheme(String siteScheme) { this.siteScheme = siteScheme; }
+
+    @JsonIgnore
+    public String getFullUrl() {
+        return ServerConfig.getInstance().getSiteScheme() + "://" + ServerConfig.getInstance().getSiteHostName();
+    }
+
+
+
+
+    @JsonProperty("email")
+    public String getEmail() { return email; }
+    public void setEmail(String email) { this.email = email; }
+
     @JsonProperty("https-enabled")
     public boolean isHttpsEnabled() { return httpsEnabled; }
     public void setHttpsEnabled(boolean httpsEnabled) { this.httpsEnabled = httpsEnabled; }

+ 1 - 1
src/main/java/com/jayfella/website/controller/SitemapController.java

@@ -21,7 +21,7 @@ public class SitemapController {
     @RequestMapping(path = "/sitemap.xml", produces = APPLICATION_XML_VALUE)
     public @ResponseBody String get() throws IOException {
 
-        String sitemap = Files.readString(SitemapService.SITEMAP_FULL_FILE.toPath());
+        String sitemap = new String(Files.readAllBytes(SitemapService.SITEMAP_FULL_FILE.toPath()));
         return sitemap;
 
     }

+ 1 - 1
src/main/java/com/jayfella/website/controller/api/ApiCategoryController.java

@@ -42,7 +42,7 @@ public class ApiCategoryController {
             return ApiResponses.insufficientPermission();
         }
 
-        if (request.getName().isBlank()) {
+        if (request.getName()==null||request.getName().trim().isEmpty()) {
             return ResponseEntity.badRequest()
                     .body(new SimpleApiResponse("You must provide a name."));
         }

+ 3 - 3
src/main/java/com/jayfella/website/controller/api/ApiSearchController.java

@@ -67,9 +67,9 @@ public class ApiSearchController {
         Pageable pageable = PageRequest.of(pageNum, itemsPerPage, Sort.by(sortDir, orderBy));
 
         boolean useCategory = categoryId > 0;
-        boolean useTitle = !title.isBlank();
-        boolean useTag = !tag.isBlank();
-        boolean useAuthor = !author.isBlank();
+        boolean useTitle = !(title==null||title.trim().isEmpty());
+        boolean useTag = !(tag==null||tag.trim().isEmpty());
+        boolean useAuthor = !(author==null||author.trim().isEmpty());
 
         Page<LivePage> page = null;
 

+ 1 - 1
src/main/java/com/jayfella/website/controller/api/ApiValidationController.java

@@ -319,7 +319,7 @@ public class ApiValidationController {
 
             String ipAddress = getClientIp(request);
 
-            if (ipAddress.isBlank()) {
+            if (ipAddress==null||ipAddress.trim().isEmpty()) {
                 ipAddress = "UNKNOWN";
             }
 

+ 3 - 2
src/main/java/com/jayfella/website/controller/http/IndexPageController.java

@@ -1,5 +1,6 @@
 package com.jayfella.website.controller.http;
 
+import com.jayfella.website.config.external.ServerConfig;
 import com.jayfella.website.core.StoreHtmlFilePaths;
 import com.jayfella.website.core.page.PageState;
 import com.jayfella.website.database.entity.page.stages.LivePage;
@@ -54,8 +55,8 @@ public class IndexPageController {
         // for previews, we need to transfer the preview data.
         model.addAttribute("previewTitle", livePage.getDetails().getTitle());
         model.addAttribute("previewDescription", livePage.getDetails().getShortDescription());
-        model.addAttribute("previewUrl", "https://jmonkeystore.com/" + livePage.getId());
-        model.addAttribute("previewImage", "https://jmonkeystore.com/image/" + previewImageId + ".jpg");
+        model.addAttribute("previewUrl", ServerConfig.getInstance().getFullUrl()+"/" + livePage.getId());
+        model.addAttribute("previewImage", ServerConfig.getInstance().getFullUrl()+"/image/" + previewImageId + ".jpg");
 
         return StoreHtmlFilePaths.Store.VIEW_PAGE.getHtmlFilePath();
     }

+ 1 - 0
src/main/java/com/jayfella/website/core/JsonMapper.java

@@ -44,6 +44,7 @@ public class JsonMapper {
 
     public static boolean writeFile(File file, Object value) {
         try {
+            if(!file.getParentFile().exists()) file.getParentFile().mkdirs();            
             objectMapper.writeValue(file, value);
             return true;
         } catch (IOException ex) {

+ 14 - 14
src/main/java/com/jayfella/website/service/EmailService.java

@@ -58,8 +58,8 @@ public class EmailService {
         final MimeMessage mimeMessage = javaMailSender.createMimeMessage();
         final MimeMessageHelper message =
                 new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart
-        message.setSubject("JmonkeyStore");
-        message.setFrom(new InternetAddress("[email protected]", "JmonkeyStore"));
+        message.setSubject(ServerConfig.getInstance().getSiteName());
+        message.setFrom(new InternetAddress(ServerConfig.getInstance().getEmail(), ServerConfig.getInstance().getSiteName()));
         message.setTo(user.getEmail());
 
         // Create the HTML body using Thymeleaf
@@ -94,8 +94,8 @@ public class EmailService {
         final MimeMessage mimeMessage = javaMailSender.createMimeMessage();
         final MimeMessageHelper message =
                 new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart
-        message.setSubject("JmonkeyStore");
-        message.setFrom(new InternetAddress("[email protected]", "JmonkeyStore"));
+        message.setSubject(ServerConfig.getInstance().getSiteName());
+        message.setFrom(new InternetAddress(ServerConfig.getInstance().getEmail(), ServerConfig.getInstance().getSiteName()));
         message.setTo(user.getEmail());
 
         // Create the HTML body using Thymeleaf
@@ -127,8 +127,8 @@ public class EmailService {
         final MimeMessage mimeMessage = javaMailSender.createMimeMessage();
         final MimeMessageHelper message =
                 new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart
-        message.setSubject("JmonkeyStore");
-        message.setFrom(new InternetAddress("[email protected]", "JmonkeyStore"));
+        message.setSubject(ServerConfig.getInstance().getSiteName());
+        message.setFrom(new InternetAddress(ServerConfig.getInstance().getEmail(), ServerConfig.getInstance().getSiteName()));
         message.setTo(storePage.getOwner().getEmail());
 
         // Create the HTML body using Thymeleaf
@@ -159,8 +159,8 @@ public class EmailService {
         final MimeMessage mimeMessage = javaMailSender.createMimeMessage();
         final MimeMessageHelper message =
                 new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart
-        message.setSubject("JmonkeyStore");
-        message.setFrom(new InternetAddress("[email protected]", "JmonkeyStore"));
+        message.setSubject(ServerConfig.getInstance().getSiteName());
+        message.setFrom(new InternetAddress(ServerConfig.getInstance().getEmail(), ServerConfig.getInstance().getSiteName()));
         message.setTo(storePage.getOwner().getEmail());
 
         // Create the HTML body using Thymeleaf
@@ -192,8 +192,8 @@ public class EmailService {
         final MimeMessage mimeMessage = javaMailSender.createMimeMessage();
         final MimeMessageHelper message =
                 new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart
-        message.setSubject("JmonkeyStore");
-        message.setFrom(new InternetAddress("[email protected]", "JmonkeyStore"));
+        message.setSubject(ServerConfig.getInstance().getSiteName());
+        message.setFrom(new InternetAddress(ServerConfig.getInstance().getEmail(), ServerConfig.getInstance().getSiteName()));
         message.setTo(page.getOwner().getEmail());
 
         // Create the HTML body using Thymeleaf
@@ -224,8 +224,8 @@ public class EmailService {
         final MimeMessage mimeMessage = javaMailSender.createMimeMessage();
         final MimeMessageHelper message =
                 new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart
-        message.setSubject("JmonkeyStore");
-        message.setFrom(new InternetAddress("[email protected]", "JmonkeyStore"));
+        message.setSubject(ServerConfig.getInstance().getSiteName());
+        message.setFrom(new InternetAddress(ServerConfig.getInstance().getEmail(), ServerConfig.getInstance().getSiteName()));
         message.setTo(user.getEmail());
 
         // Create the HTML body using Thymeleaf
@@ -259,8 +259,8 @@ public class EmailService {
                 final MimeMessageHelper message =
                         new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart
 
-                message.setSubject("JmonkeyStore - Review Requested");
-                message.setFrom(new InternetAddress("[email protected]", "JmonkeyStore"));
+                message.setSubject(ServerConfig.getInstance().getSiteName()+" - Review Requested");
+                message.setFrom(new InternetAddress(ServerConfig.getInstance().getEmail(), ServerConfig.getInstance().getSiteName()));
                 message.setTo(user.getEmail());
 
                 // Create the HTML body using Thymeleaf

+ 17 - 14
src/main/java/com/jayfella/website/service/SitemapService.java

@@ -1,5 +1,6 @@
 package com.jayfella.website.service;
 
+import com.jayfella.website.config.external.ServerConfig;
 import com.jayfella.website.database.entity.page.stages.LivePage;
 import com.jayfella.website.database.repository.page.LivePageRepository;
 import com.redfin.sitemapgenerator.WebSitemapGenerator;
@@ -25,12 +26,12 @@ public class SitemapService {
 
     private static final Logger log = LoggerFactory.getLogger(SitemapService.class);
 
-    private static final String HOST = "https://jmonkeystore.com";
+    private static final String HOST = ServerConfig.getInstance().getFullUrl();
 
-    private static final File SITEMAP_BASEDIR = new File("./www/");
-    private static final File SITEMAP_FILE = new File("sitemap.xml");
+    private static final File SITEMAP_BASEDIR = new File("./sitemap/");
+    // private static final File SITEMAP_FILE = new File("./sitemap/sitemap.xml");
 
-    public static final File SITEMAP_FULL_FILE = new File("./www/sitemap.xml");
+    public static final File SITEMAP_FULL_FILE = new File("./sitemap/sitemap.xml");
 
     @Autowired
     private LivePageRepository livePageRepository;
@@ -40,15 +41,15 @@ public class SitemapService {
 
         // this method is called every time a new software page is created by a user.
         // it generates a new sitemap and pings google.
-
+        if(!SITEMAP_BASEDIR.exists())SITEMAP_BASEDIR.mkdirs();
         WebSitemapGenerator sitemapGenerator = new WebSitemapGenerator(HOST, SITEMAP_BASEDIR);
 
         // static pages
-        sitemapGenerator.addUrl("https://jmonkeystore.com/");
-        sitemapGenerator.addUrl("https://jmonkeystore.com/blog/");
+        sitemapGenerator.addUrl(ServerConfig.getInstance().getFullUrl()+"/");
+        sitemapGenerator.addUrl(ServerConfig.getInstance().getFullUrl()+"/blog/");
 
-        sitemapGenerator.addUrl("https://jmonkeystore.com/legal/terms/");
-        sitemapGenerator.addUrl("https://jmonkeystore.com/legal/cookies/");
+        sitemapGenerator.addUrl(ServerConfig.getInstance().getFullUrl()+"/legal/terms/");
+        sitemapGenerator.addUrl(ServerConfig.getInstance().getFullUrl()+"/legal/cookies/");
 
         // software pages
         List<LivePage> software = livePageRepository.findAll();
@@ -56,8 +57,8 @@ public class SitemapService {
         software.forEach(page -> {
 
             String url = new URIBuilder()
-                    .setScheme("https")
-                    .setHost("jmonkeystore.com")
+                    .setScheme(ServerConfig.getInstance().getSiteScheme())
+                    .setHost(ServerConfig.getInstance().getSiteHostName())
                     .setPath("/" + page.getId())
                     .toString();
 
@@ -65,7 +66,9 @@ public class SitemapService {
         });
 
         sitemapGenerator.write();
-        sitemapGenerator.writeSitemapsWithIndex(SITEMAP_FILE);
+
+        // if(!SITEMAP_FILE.getParentFile().exists())SITEMAP_FILE.getParentFile().mkdirs();
+        // sitemapGenerator.writeSitemapsWithIndex(SITEMAP_FILE);
 
         pingGoogle();
 
@@ -74,13 +77,13 @@ public class SitemapService {
     private void pingGoogle() throws IOException {
 
         // http://www.google.com/ping?sitemap=<complete_url_of_sitemap>
-        String url = "http://www.google.com/ping?sitemap=" + "https://jmonkeystore.com/sitemap.xml";
+        String url = "http://www.google.com/ping?sitemap=" + ServerConfig.getInstance().getFullUrl()+"/sitemap.xml";
 
         HttpClient client = HttpClientBuilder.create().build();
         HttpGet request = new HttpGet(url);
 
         // add request header
-        request.addHeader("User-Agent", "jMonkeyStore");
+        request.addHeader("User-Agent", ServerConfig.getInstance().getSiteName());
         HttpResponse response = client.execute(request);
 
         log.info("Google SiteMap Pinger Responded : " + response.getStatusLine().getStatusCode());

+ 72 - 0
testing-environment.sh

@@ -0,0 +1,72 @@
+#!/bin/bash
+if [ "$RUNTIME" = "" ];
+then
+    export RUNTIME="`which podman`"
+    if [ "$RUNTIME" = "" ];
+    then
+        export RUNTIME="`which docker`"
+    fi
+fi
+
+echo "Use runtime $RUNTIME"
+
+function stop {
+    echo "Stop!"
+    $RUNTIME stop  jmestore-testing-mysql  ||true
+    $RUNTIME stop  jmestore-testing-pma  ||true
+    $RUNTIME stop jmestore-testing-store  ||true
+    $RUNTIME rm   jmestore-testing-mysql   ||true
+    $RUNTIME rm   jmestore-testing-pma ||true
+    $RUNTIME rm   jmestore-testing-store ||true
+    $RUNTIME network rm jmestore_testing_net|| true
+
+}
+
+
+function start {
+    stop    
+    echo "Start!"
+    mkdir -p "$PWD/test_environment"
+    mkdir -p "$PWD/test_environment/mysql"
+    $RUNTIME network create -d bridge   jmestore_testing_net
+
+    $RUNTIME run --rm  -d   \
+        --name jmestore-testing-mysql \
+        -v "$PWD/test_environment/mysql":/var/lib/mysql \
+        -e MYSQL_ROOT_PASSWORD="oEZi1nIeZwpS"  \
+        -p 3306:3306 \
+        mariadb 
+    $RUNTIME network connect --alias  mysql jmestore_testing_net  jmestore-testing-mysql   
+
+    $RUNTIME run -d --rm --name jmestore-testing-pma \
+    -e PMA_HOST=jmestore-testing-mysql  \
+    -p 8081:80 \
+    phpmyadmin/phpmyadmin
+    $RUNTIME network connect --alias  phpmyadmin.mysql jmestore_testing_net  jmestore-testing-pma   
+
+
+    if [ "$RUN_STORE" != "" ];
+    then
+        mkdir -p "$PWD/test_environment/store_config"
+        mkdir -p "$PWD/test_environment/store_images"
+
+        rm -f "$PWD/test_environment/store_config/server-config.json" || true
+        cp "config/test-environment-config.json" "$PWD/test_environment/store_config/server-config.json"
+    
+        $RUNTIME create --rm --name jmestore-testing-store \
+            --read-only \
+            -v"$PWD/test_environment/store_config":/app/config \
+            -v"$PWD/test_environment/store_images":/app/www/images/database \
+            --tmpfs  /app/sitemap \
+            --tmpfs  /tmp/apptmp \
+            -p 8080:8080 \
+            jmestore
+
+        $RUNTIME network connect --alias  store.docker jmestore_testing_net  jmestore-testing-store   
+
+        $RUNTIME start  jmestore-testing-store
+        $RUNTIME logs --follow  jmestore-testing-store
+    fi
+}
+
+$1

+ 0 - 0
www/images/database/.keep


+ 8 - 9
www/legal/cookies.html

@@ -9,19 +9,19 @@
 			<h2>Cookies Policy</h2>
 
 			<p>
-				This website, <span class="website_url">https://jmonkeystore.com</span> (the "Website"), is operated by
-				<span class="website_name">JmonkeyStore</span>.
+				This website, <span class="website_url" th:text="${websiteFullUrl}"></span> (the "Website"), is operated by
+				<span class="website_name"  th:text="${siteName}"></span>.
 			</p>
 
 			<h3>What are cookies?</h3>
 
 			<p>
-				Cookies are a small text files that are stored in your web browser that allows <span class="website_name">JmonkeyStore</span> or a third party
+				Cookies are a small text files that are stored in your web browser that allows <span class="website_name"  th:text="${siteName}"></span> or a third party
 				to recognize you. Cookies can be used to collect, store and share bits of information about your activities across websites, including on
-				<span class="website_name">JmonkeyStore</span> website. This Cookies Policy was created by
+				<span class="website_name"  th:text="${siteName}"></span> website. This Cookies Policy was created by
 				<a href="https://www.cookiespolicytemplate.com">GDPR Cookies Policy Template Generator</a> and the
 				<a href="https://www.termsandcondiitionssample.com">Terms and Conditions Template</a> for
-				<span class="website_url">https://jmonkeystore.com</span>
+				<span class="website_url" th:text="${websiteFullUrl}"></span>
 			</p>
 
 			<p>Cookies might be used for the following purposes:</p>
@@ -33,7 +33,7 @@
 				<li>To enable ad delivery and behavioral advertising</li>
 			</ul>
 
-			<p><span class="website_name">JmonkeyStore</span> uses both session cookies and persistent cookies.</p>
+			<p><span class="website_name"  th:text="${siteName}"></span> uses both session cookies and persistent cookies.</p>
 
 			<p>
 				A session cookie is used to identify a particular visit to our Website. These cookies expire after a short time, or when you close your web
@@ -45,11 +45,10 @@
 				you over a longer period of time. For example, we would use a persistent cookie if you asked that we keep you signed in.
 			</p>
 
-			<h3>How do third parties use cookies on the <span class="website_name">JmonkeyStore</span> Website?</h3>
-
+			<h3>How do third parties use cookies on the <span class="website_name"  th:text="${siteName}"></span> Website?</h3>
 			<p>
 				Third party companies like analytics companies and ad networks generally use cookies to collect user information on an anonymous basis. They may
-				use that information to build a profile of your activities on the <span class="website_name">JmonkeyStore</span> Website and other websites that
+				use that information to build a profile of your activities on the <span class="website_name"  th:text="${siteName}"></span> Website and other websites that
 				you've visited.
 			</p>
 

+ 17 - 17
www/legal/tos.html

@@ -20,7 +20,7 @@
 			</p>
 
 			<p>
-				JmonkeyStore shall have the right, at its sole discretion, to modify, add or remove any terms or conditions of these Terms of Use without notice
+				<span th:text="${siteName}"></span> shall have the right, at its sole discretion, to modify, add or remove any terms or conditions of these Terms of Use without notice
 				or liability to you. Any changes to these Terms of Use shall be effectively immediately following the posting of such changes on this website.
 				The most recent version of these Terms of Use may always be found at /terms_of_use/. You agree to review these Terms of Use from time to time
 				and agree that any subsequent use by you of this website following changes to these Terms of Use shall constitute your acceptance of all such
@@ -62,7 +62,7 @@
 				</div>
 				<div class="item">
 					Sell access to or the use of this website, including any content contained on, downloaded or accessed from this website, except as
-					specifically permitted in writing by JmonkeyStore
+					specifically permitted in writing by <span th:text="${siteName}"></span>
 				</div>
 				<div class="item">
 					Redistribute any content, including data, provided by us in any manner whatsoever including by means of printed publication, fax broadcast,
@@ -73,7 +73,7 @@
 				</div>
 				<div class="item">
 					Embed or import any site data provided by us into any information services (whether or not web-based), data files or application software,
-					including without limitation episode index systems, except as except as specifically permitted in writing by JmonkeyStore.
+					including without limitation episode index systems, except as except as specifically permitted in writing by <span th:text="${siteName}"></span>.
 				</div>
 			</div>
 
@@ -85,37 +85,37 @@
 
 			<p>
 				You agree not to post any abusive, obscene, vulgar, slanderous, hateful, threatening, sexually-orientated or any other material that may violate
-				any laws be it of your country, the country where "JmonkeyStore" is hosted, USA, or International Law. Doing so may lead to you being
+				any laws be it of your country, the country where "<span th:text="${siteName}"></span>" is hosted, USA, or International Law. Doing so may lead to you being
 				immediately and permanently banned, with notification of your Internet Service Provider if deemed required by us. The IP address of all posts
-				are recorded to aid in enforcing these conditions. You agree that "JmonkeyStore" have the right to remove, edit, move or close any topic at any
+				are recorded to aid in enforcing these conditions. You agree that "<span th:text="${siteName}"></span>" have the right to remove, edit, move or close any topic at any
 				time should we see fit. As a user you agree to any information you have entered to being stored in a database. While this information will not
-				be disclosed to any third party without your consent, "JmonkeyStore" shall not be held responsible for any hacking attempt that may lead to the
+				be disclosed to any third party without your consent, "<span th:text="${siteName}"></span>" shall not be held responsible for any hacking attempt that may lead to the
 				data being compromised
 			</p>
 
 			<p>
-				By accessing "JmonkeyStore", you agree to be legally bound by the following terms. If you do not agree to be legally bound by all of the
-				following terms then please do not access and/or use "JmonkeyStore". We may change these at any time and we’ll do our utmost in informing you,
-				though it would be prudent to review this regularly yourself as your continued usage of "JmonkeyStore" after changes mean you agree to be
+				By accessing "<span th:text="${siteName}"></span>", you agree to be legally bound by the following terms. If you do not agree to be legally bound by all of the
+				following terms then please do not access and/or use "<span th:text="${siteName}"></span>". We may change these at any time and we’ll do our utmost in informing you,
+				though it would be prudent to review this regularly yourself as your continued usage of "<span th:text="${siteName}"></span>" after changes mean you agree to be
 				legally bound by these terms as they are updated and/or amended.
 			</p>
 
 			<h2 class="ui dividing header">Disclaimer and Limitation of Liability</h2>
 			<p>
 				The Services and all information, content, materials, products (including software), and other services included on or otherwise made available
-				to you through the Services are provided by JmonkeyStore on an "as is" and "as available" basis. JmonkeyStore makes no representations or
+				to you through the Services are provided by <span th:text="${siteName}"></span> on an "as is" and "as available" basis. <span th:text="${siteName}"></span> makes no representations or
 				warranties of any kind, express or implied, as to the operation of the Services, or the information, content, materials, products (including
 				software), or other services included on or otherwise made available to you through the Services. You expressly agree that your use of the
-				Services is at your sole risk. To the full extent permissible by law, JmonkeyStore disclaims all warranties, express or implied, including, but
-				not limited to, implied warranties of merchantability and fitness for a particular purpose. JmonkeyStore does not warrant that the Services,
+				Services is at your sole risk. To the full extent permissible by law, <span th:text="${siteName}"></span> disclaims all warranties, express or implied, including, but
+				not limited to, implied warranties of merchantability and fitness for a particular purpose. <span th:text="${siteName}"></span> does not warrant that the Services,
 				information, content, materials, products (including software) or other services included on or otherwise made available to you through the
-				Services, JmonkeyStore’s servers, or electronic communications sent from JmonkeyStore are free of viruses or other harmful components.
+				Services, <span th:text="${siteName}"></span> servers, or electronic communications sent from <span th:text="${siteName}"></span> are free of viruses or other harmful components.
 			</p>
 
 			<p>
-				To the full extent permissible by law, JmonkeyStore will not be liable for any loss of profits or any indirect, incidental, punitive, special or
-				consequential damages arising out of or in connection with this these Terms. Further, to the full extent permissible by law, JmonkeyStore’s
-				aggregate liability arising out of or in connection with these Terms will not exceed the total amounts you have paid (if any) to JmonkeyStore
+				To the full extent permissible by law, <span th:text="${siteName}"></span> will not be liable for any loss of profits or any indirect, incidental, punitive, special or
+				consequential damages arising out of or in connection with this these Terms. Further, to the full extent permissible by law, <span th:text="${siteName}"></span>’s
+				aggregate liability arising out of or in connection with these Terms will not exceed the total amounts you have paid (if any) to <span th:text="${siteName}"></span>
 				under this Agreement during the twelve (12) months immediately preceding the events giving rise to such liability. These limitations and
 				exclusions regarding damages apply even if any remedy fails to provide adequate compensation.
 			</p>
@@ -129,7 +129,7 @@
 			</p>
 
 			<p>
-				You agree to defend, indemnify, and hold harmless JmonkeyStore, its affiliates, and licensors, and their respective officers, directors,
+				You agree to defend, indemnify, and hold harmless <span th:text="${siteName}"></span>, its affiliates, and licensors, and their respective officers, directors,
 				employees, contractors, agents, licensors, and suppliers from and against any claims, liabilities, damages, judgments, awards, losses, costs,
 				expenses, or fees (including reasonable attorneys’ fees) resulting from your User Contributions or violation of these Terms.
 			</p>

+ 2 - 2
www/mail/html/account-validation.html

@@ -23,12 +23,12 @@
 		<p>To enter this code, navigate to the <b>User Control Panel</b> manually, or click the link below.</p>
 
 		<p>
-			<a href="https://jmonkeystore.com/user/">https://jmonkeystore.com/user/</a>
+			<a  th:href="${websiteFullUrl} + '/user/'"  th:text="${websiteFullUrl} + '/user/'" ></a>
 		</p>
 
 		<p>
 			Regards, <br />
-			The JmonkeyStore Team
+			<span th:text="${siteName}"></span>
 		</p>
 	</body>
 </html>

+ 2 - 2
www/mail/html/page-approved.html

@@ -20,12 +20,12 @@
 		</p>
 
 		<p>
-			<a th:href="'https://jmonkeystore.com/' + ${page.id}" th:text="'https://jmonkeystore.com/' + ${page.id}"></a>
+			<a th:href="${websiteFullUrl}/ + ${page.id}" th:text="${websiteFullUrl}/ + ${page.id}"></a>
 		</p>
 
 		<p>
 			Regards, <br />
-			The JmonkeyStore Team
+			<span th:text="${siteName}"></span>
 		</p>
 	</body>
 </html>

+ 1 - 1
www/mail/html/page-rejected.html

@@ -19,7 +19,7 @@
 
 		<p>
 			Regards, <br />
-			The JmonkeyStore Team
+			<span th:text="${siteName}"></span>
 		</p>
 	</body>
 </html>

+ 1 - 1
www/mail/html/page-under-review.html

@@ -21,7 +21,7 @@
 
 		<p>
 			Regards, <br />
-			The JmonkeyStore Team
+			<span th:text="${siteName}"></span>
 		</p>
 	</body>
 </html>

+ 3 - 3
www/mail/html/registration.html

@@ -6,7 +6,7 @@
 	</head>
 	<body>
 		<p th:inline="text">
-			Hi [[${username}]], thank you for registering at jmonkeystore!
+			Hi [[${username}]], thank you for registering at <span th:text="${siteName}"></span>!
 		</p>
 
 		<p>
@@ -18,12 +18,12 @@
 		<p>To enter this code, navigate to the <b>User Control Panel</b> manually, or click the link below.</p>
 
 		<p>
-			<a href="https://jmonkeystore.com/user/">https://jmonkeystore.com/user/</a>
+			<a  th:href="${websiteFullUrl} + '/user/'"  th:text="${websiteFullUrl} + '/user/'" ></a>
 		</p>
 
 		<p>
 			Regards, <br />
-			The JmonkeyStore Team
+			<span th:text="${siteName}"></span>
 		</p>
 	</body>
 </html>

+ 4 - 4
www/mail/html/reset-lost-password.html

@@ -17,16 +17,16 @@
 
 		<p>
 			<a
-				th:href="'https://jmonkeystore.com/user/reset-password/' + ${validationCode}"
-				th:text="'https://jmonkeystore.com/user/reset-password/' + ${validationCode}"
+				th:href="${websiteFullUrl}+'/user/reset-password/' + ${validationCode}"
+				th:text="${websiteFullUrl}+'/user/reset-password/' + ${validationCode}"
 			></a>
 		</p>
 
-		<p>If you did not request a new password, you can cancel this request in the <a href="https://jmonkeystore.com/user/">User Control Panel.</a></p>
+		<p>If you did not request a new password, you can cancel this request in the <a  th:href="${websiteFullUrl} + '/user/'">User Control Panel.</a></p>
 
 		<p>
 			Regards, <br />
-			The JmonkeyStore Team
+			<span th:text="${siteName}"></span>
 		</p>
 	</body>
 </html>

+ 2 - 2
www/mail/html/review-requested.html

@@ -14,10 +14,10 @@
 			<b th:text="${page.details.title}"></b>.
 		</p>
 
-		<p>Please visit the <a href="https://jmonkeystore.com/admin/pages/">Store Page Moderation</a> area if you wish to review this page.</p>
+		<p>Please visit the <a   th:href="${websiteFullUrl} + '/admin/pages'" >Store Page Moderation</a> area if you wish to review this page.</p>
 
 		<p>
-			This is an automated message sent by JmonkeyStore.
+			This is an automated message sent by <span th:text="${siteName}"></span>.
 		</p>
 	</body>
 </html>

+ 0 - 60
www/sitemap.xml

@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" >
-  <url>
-    <loc>https://jmonkeystore.com/</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/blog/</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/legal/terms/</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/legal/cookies/</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/e6523099-f665-4b65-9b1c-f24a044c4631</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/02e726a8-8de8-49a1-aded-f538a2333f75</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/e7f8410d-656e-4c16-b4de-996e69bad535</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/5f57487e-eb02-443c-9c77-bf69e43a92f8</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/f6aa07d9-49ba-49a1-9405-c8ba6c8deadc</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/daee0868-b2d6-41e2-9975-3a4e223a423a</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/6ed7af21-d4d7-48e3-9614-e0341180eb7c</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/3de43b72-ddd9-4fd1-b653-ac79cc56df4e</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/964eda6d-d33a-4116-ac87-4862b1b8f3d0</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/b8a9a30f-d338-4657-b1f2-d637f8c2e34c</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/beeb3763-8821-4205-9bbd-b095274703f4</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/8e001fc5-f8c7-4567-b307-16c843410865</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/3624e24f-0f6c-4d09-ad6c-c1d23cf9246b</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/47eff34e-1822-423b-9065-d3ab4320ac5e</loc>
-  </url>
-  <url>
-    <loc>https://jmonkeystore.com/98ac60a5-6057-4180-b2aa-e6279ee92248</loc>
-  </url>
-</urlset>