Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dockerized v0.1 #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,13 @@ out/
### VS Code ###
.vscode/
/src/main/resources/application-secrets.properties


## Docker
docker/externaljars/TopoLibrary-2.2-SNAPSHOT.jar
docker/externaljars/fit.jar
#docker/volumes/** */
docker/volumes/cubetrek/maps/HGT/*
docker/volumes/cubetrek/maps/HGT_1DEM/*
docker/volumes/cubetrek/logs/*
docker/volumes/cubetrek/db/*
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@ After clicking on the map, Turf.js is used to determine the closest track.
- Consider becoming a Supporter of CubeTrek by getting a [subscription](https://cubetrek.com/subscribe). This helps paying the bills.

## Setting up the dev environment
- See [here](docs/dev-environment.md)
- See [here](docs/dev-environment.md) (Docker currently only proof of concept)
38 changes: 38 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Use a base image with Java and Gradle
FROM debian:bookworm-slim
MAINTAINER pmffromspace

# Install necessary packages and SDKMAN
RUN apt-get update && \
apt-get install -y curl unzip zip && \
curl -s https://get.sdkman.io | bash && \
/bin/bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && sdk list java && sdk install java 21.0.4-tem && sdk install gradle"

# Set the JAVA_HOME environment variable and add Java to the PATH
ENV JAVA_HOME="/root/.sdkman/candidates/java/current"
ENV PATH="$JAVA_HOME/bin:$PATH"

# Set the working directory
WORKDIR /app

# Copy the Gradle files
COPY build.gradle settings.gradle /app/

# Copy the source code
COPY src /app/src

# Copy the TopoLibrary JAR and Garmin FIT SDK JAR
COPY docker/externaljars/TopoLibrary-2.2-SNAPSHOT.jar /app/libs/
COPY docker/externaljars/fit.jar /app/libs/

# Download dependencies
RUN /bin/bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && gradle --no-daemon dependencies"

# Build the application without running tests
RUN /bin/bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && gradle --no-daemon build -x test"

# Expose the port for the application
EXPOSE 8080

# Set the entry point to run the application
ENTRYPOINT ["java", "-jar", "/app/build/libs/cubetrek-1.1-SNAPSHOT.jar"]
32 changes: 32 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
services:

# CubeTrek
cubetrek-dev:
image: cubetrek-dev:local
container_name: cubetrek-dev
restart: no
depends_on:
- cubetrekdb
networks:
- cubetrek
ports:
- 8080:8080
volumes:
- ./volumes/cubetrek/logs:/logs
- ./volumes/cubetrek/maps:/maps

# Database
cubetrekdb:
image: cubetrekdb:local
container_name: cubetrekdb
networks:
- cubetrek
volumes:
- ./volumes/cubetrek/db/postgres_data:/var/lib/postgresql/data
#ports: #the ports dont need to be opened on host because cubetrek can access in the same docker network
# - "5432:5432"
restart: unless-stopped

networks:
cubetrek:
driver: bridge
164 changes: 164 additions & 0 deletions docker/modified.files/RegistrationController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package com.cubetrek.registration;

import com.cubetrek.ExceptionHandling;
import com.cubetrek.database.NewsletterSignup;
import com.cubetrek.database.NewsletterSignupRepository;
import com.cubetrek.database.Users;
import com.cubetrek.database.VerificationToken;
import com.cubetrek.upload.polaraccesslink.PolarAccesslinkService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.WebRequest;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.util.Calendar;

@Controller
public class RegistrationController {
@Autowired
private UserRegistrationService userRegistrationService;

@Autowired
ApplicationEventPublisher eventPublisher;

@Autowired
NewsletterSignupRepository newsletterSignupRepository;

Logger logger = LoggerFactory.getLogger(RegistrationController.class);

@GetMapping("/registration")
public String showRegistrationForm(WebRequest request, Model model) {
UserDto userDto = new UserDto();
model.addAttribute("user", userDto);
return "registration";
}

@PostMapping("/registration")
public String registerUserAccount(
@ModelAttribute("user") @Valid UserDto userDto, BindingResult bindingResult, HttpServletRequest request) {

if (bindingResult.hasErrors()) {
return "registration";
}

try {
// Disabling Cloudflare Turnstile verification
// Commenting out Turnstile verification logic
// String cf_turnstile_response = request.getParameter("cf-turnstile-response");
// if (cf_turnstile_response.equals("none")) {
// logger.error("Error Registration: no Cloudflare Turnstile transferred for Username: " + userDto.getName() + ", email " + userDto.getEmail() + ", IP " + request.getHeader("X-FORWARDED-FOR"));
// throw new ExceptionHandling.UnnamedException("Something went wrong :(", "Could not finalize Registration, you might be a bot. Did you click the Human Verification button?");
// }
// HttpResponse<String> response = verifyCloudflareTurnstile(cf_turnstile_response, request.getHeader("X-FORWARDED-FOR"));
// if (response.statusCode() != 200) {
// logger.error("Error Registration: Cloudflare Turnstile returns not 200: " + response.statusCode() + "; " + response.body());
// throw new ExceptionHandling.UnnamedException("Something went wrong :(", "Could not finalize Registration, please try again later or send an email to [email protected]");
// }
// boolean turnstile_success = (new ObjectMapper()).readTree(response.body()).get("success").asBoolean(false);
// if (!turnstile_success) {
// logger.error("Error Registration: Cloudflare Turnstile returns not true: " + response.body());
// throw new ExceptionHandling.UnnamedException("Something went wrong :(", "Could not finalize Registration, please try again later or send an email to [email protected]");
// }
} catch (Exception e) {
throw new RuntimeException(e);
}

try {
// Register user without email verification
Users registered = userRegistrationService.register(userDto);
registered.setEnabled(true); // Directly enabling the user without email verification
userRegistrationService.saveRegisteredUser(registered); // Ensure the user is saved

// Optionally remove email verification event if not needed
// eventPublisher.publishEvent(new OnRegistrationCompleteEvent(registered));

} catch (ExceptionHandling.UserRegistrationException ex) { // the email address exists already
bindingResult.addError(new FieldError("user", "email", ex.msg));
return "registration";
} catch (RuntimeException ex) {
logger.error("Registration Error", ex);
throw new ExceptionHandling.UnnamedException("Something went wrong :(", "Could not finalize Registration, please try again later or send an email to [email protected]");
}

return "successRegister"; // Registration success page
}

// Removed the verifyCloudflareTurnstile method since Turnstile verification is disabled

@GetMapping("/registrationConfirm")
public String confirmRegistration(WebRequest request, Model model, @RequestParam("token") String token) {
// Removed this method since email verification is disabled
throw new UnsupportedOperationException("Email verification is disabled.");
}

@GetMapping("/successRegisterValidation")
public String successRegistration() {
return "successRegisterValidation";
}

public static class Password {
@Getter
@Setter
String email;
}

@GetMapping("/reset_password")
public String showResetForm(WebRequest request, Model model) {
Password pw = new Password();
model.addAttribute("password", pw);
return "resetPassword";
}

@PostMapping(value = "/reset_password")
public String initiateReset(@ModelAttribute("password") Password password) {
userRegistrationService.requestPasswordReset(password.getEmail());
return "resetPassword2";
}

public static class PasswordReset {
@Getter
@Setter
String token;

@Getter
@Setter
@NotNull
@NotBlank(message = "Password cannot be empty")
@Size(min = 5, message = "Password must be at least 5 characters")
String password;
}

@GetMapping("/reset_password3")
public String resetPasswordVerifyToken(WebRequest request, Model model, @RequestParam("token") String token) {
// Logic for resetting password, keep this as is
return "resetPassword3";
}

@PostMapping("/reset_password3")
public String registerUserAccount(
@ModelAttribute("password") @Valid PasswordReset password, BindingResult bindingResult) {

if (bindingResult.hasErrors())
return "registration";

userRegistrationService.resetPassword(password.getToken(), password.getPassword());
return "resetPasswordSuccess";
}
}
81 changes: 81 additions & 0 deletions docker/modified.files/registration.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3" lang="en">

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<link rel="icon" type="image/svg" href="/assets/logo.svg">
<title>CubeTrek - Registration</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Removed the Turnstile script -->
<!-- <script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script> -->
</head>
<body>

<div class="col-lg-8 mx-auto p-3 py-md-5">
<header class="d-flex align-items-center pb-3 mb-5 border-bottom">
<a href="/" class="d-flex align-items-center text-dark text-decoration-none">
<img class="me-2" width="40" src="../assets/logo.svg">
<span class="fs-4">CubeTrek</span>
</a>
</header>

<main>
<h1 class="fw-light text-center pb-5">Sign Up for a <strong>CubeTrek</strong> Account</h1>
<form action="/registration" th:object="${user}" method="POST" enctype="utf8">

<div class="row g-3">
<div class="col-sm-6">
<label for="name" class="form-label">Name</label>
<input th:field="*{name}" type="text" class="form-control" id="name" placeholder="" value="" required="">
<p class="alert alert-warning" role="alert" th:each="error: ${#fields.errors('name')}"
th:text="${error}">Validation error</p>
<div class="invalid-feedback">
Valid first name is required.
</div>
</div>
<div class="col-6">
<label for="email" class="form-label">Email</label>
<input th:field="*{email}" type="email" class="form-control" id="email" placeholder="[email protected]">
<p class="alert alert-warning" role="alert" th:each="error : ${#fields.errors('email')}"
th:text="${error}">Validation error</p>
<div class="invalid-feedback">
Valid Email is required.
</div>

<input th:field="*{timezone}" type="hidden" id="timezone" value="Etc/UTC">
<input th:field="*{metric}" type="hidden" id="metric" value="true">
</div>

<div class="col-6">
<label for="password" class="form-label">Password</label>
<input th:field="*{password}" type="password" class="form-control" id="password">
<p class="alert alert-warning" role="alert" th:each="error : ${#fields.errors('password')}"
th:text="${error}">Validation error</p>
</div>
</div>
<!-- Removed the Turnstile div -->
<!-- <div class="cf-turnstile mt-3" data-sitekey="0x4AAAAAAACez3IMc0tBVYwV"></div> -->
<div class="mt-5">
Read the <a href="/static/privacy.html">Privacy Policy</a>.
</div>
<div class="mt-2">
Please note that <strong>CubeTrek</strong> is still in Beta, things might break.
</div>
<button class="col-6 btn btn-lg btn-primary mt-2" type="submit">submit</button>
</form>
<div class="pt-3">
Already registered? <a th:href="@{/login.html}">Login</a>
</div>

</main>
</div>
</body>
<script>
document.getElementById("timezone").value = Intl.DateTimeFormat().resolvedOptions().timeZone;
document.getElementById("metric").value = (localStorage.getItem("metric") === null || localStorage.getItem("metric"));
</script>
</html>
20 changes: 20 additions & 0 deletions docker/postgres.database/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Use the official PostgreSQL base image
FROM postgres:15

# Set environment variables for the database and user
ENV POSTGRES_DB=cubetrek
ENV POSTGRES_USER=cubetrek_postgres
ENV POSTGRES_PASSWORD=my-super-secure-password

# Install PostGIS
RUN apt-get update && \
apt-get install -y postgis postgresql-15-postgis-3 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

# Run SQL commands to create the PostGIS extension after the database is ready
COPY ./init-db.sh /docker-entrypoint-initdb.d/init-db.sh
RUN chmod +x /docker-entrypoint-initdb.d/init-db.sh

# Expose the default PostgreSQL port
EXPOSE 5432
16 changes: 16 additions & 0 deletions docker/postgres.database/init-db.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash
set -e

# Modify pg_hba.conf to allow connections for the cubetrek_postgres user
echo "# Allow all connections for the cubetrek_postgres user" >> /var/lib/postgresql/data/pg_hba.conf
echo "host all cubetrek_postgres 0.0.0.0/0 md5" >> /var/lib/postgresql/data/pg_hba.conf

# Modify postgresql.conf to listen on all interfaces
echo "# Listen on all interfaces" >> /var/lib/postgresql/data/postgresql.conf
echo "listen_addresses = '0.0.0.0'" >> /var/lib/postgresql/data/postgresql.conf

# Create the PostGIS extension
psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "CREATE EXTENSION IF NOT EXISTS postgis;"

# Optionally run any additional SQL commands here
# psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -f /path/to/your/sql/file.sql
Loading