Compare commits
4 Commits
1dbb80e5a2
...
ab74360571
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab74360571 | ||
|
|
fcda4c9e53 | ||
|
|
4a0aebce82 | ||
|
|
47f6eebd8b |
|
|
@ -4,8 +4,11 @@
|
|||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="ce59df2a-8d56-446a-867b-80e627daf479" name="Changes" comment="Add JSON response handling for form activity check Refactor `FormActiveController` to return JSON responses using `BooleanResponse`. Introduce exception handling for JSON processing errors and update `FormActiveData` to allow object initialization without parameters.">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<list default="true" id="ce59df2a-8d56-446a-867b-80e627daf479" name="Changes" comment="Update `toHtml()` method in `Form.java` Simplified the HTML structure for the `toHtml` method by switching from a table layout to paragraph tags. This removes unnecessary table formatting for improved readability and maintainability. Also updated workspace.xml with task tracking and removed outdated comments.">
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/com/alttd/forms/controlers/FormRequestHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/alttd/forms/controlers/FormRequestHandler.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/com/alttd/forms/database/Database.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/alttd/forms/database/Database.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/com/alttd/forms/form/StoreFormQuery.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/alttd/forms/form/StoreFormQuery.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/test/java/TestForm.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/test/java/TestForm.java" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
|
|
@ -50,6 +53,7 @@
|
|||
<option value="package.json" />
|
||||
<option value="Class" />
|
||||
<option value="Record" />
|
||||
<option value="Interface" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
|
|
@ -76,6 +80,14 @@
|
|||
"accountId": "ad9eb076-a98f-40c2-b7e5-9fc28b23038f"
|
||||
}
|
||||
}</component>
|
||||
<component name="HighlightingSettingsPerFile">
|
||||
<setting file="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/javax.mail/mail/1.4/1aa1579ae5ecd41920c4f355b0a9ef40b68315dd/mail-1.4.jar!/javax/mail/Part.class" root0="SKIP_INSPECTION" />
|
||||
</component>
|
||||
<component name="Jenkins.Settings">
|
||||
<option name="jenkinsUrl" value="https://jenkins.alttd.com" />
|
||||
<option name="lastSelectedView" value="all" />
|
||||
<option name="username" value="stijn" />
|
||||
</component>
|
||||
<component name="KubernetesApiProvider">{
|
||||
"isMigrated": true
|
||||
}</component>
|
||||
|
|
@ -117,7 +129,6 @@
|
|||
"RequestMappingsPanelWidth1": "75",
|
||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||
"Spring Boot.Main.executor": "Run",
|
||||
"Tomcat Server.Tomcat 10.1.17.executor": "Run",
|
||||
"git-widget-placeholder": "master",
|
||||
|
|
@ -133,7 +144,7 @@
|
|||
"project.structure.proportion": "0.0",
|
||||
"project.structure.side.proportion": "0.0",
|
||||
"run.code.analysis.last.selected.profile": "pProject Default",
|
||||
"settings.editor.selected.configurable": "preferences.lookFeel",
|
||||
"settings.editor.selected.configurable": "org.codinjutsu.tools.jenkins.servers",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
},
|
||||
"keyToStringList": {
|
||||
|
|
@ -382,6 +393,9 @@
|
|||
<workItem from="1723138548381" duration="1949000" />
|
||||
<workItem from="1723230192640" duration="55000" />
|
||||
<workItem from="1723242314809" duration="9799000" />
|
||||
<workItem from="1723307861750" duration="2179000" />
|
||||
<workItem from="1723392202182" duration="258000" />
|
||||
<workItem from="1723392471077" duration="1301000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="Initial commit for site for forms">
|
||||
<option name="closed" value="true" />
|
||||
|
|
@ -647,7 +661,31 @@
|
|||
<option name="project" value="LOCAL" />
|
||||
<updated>1723249968746</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="34" />
|
||||
<task id="LOCAL-00034" summary="Add branch condition to Discord notification stage The Discord notification stage now runs only on 'main' or 'master' branches. This helps to avoid unnecessary notifications for feature or bugfix branches.">
|
||||
<option name="closed" value="true" />
|
||||
<created>1723392636255</created>
|
||||
<option name="number" value="00034" />
|
||||
<option name="presentableId" value="LOCAL-00034" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1723392636255</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00035" summary="Improve email handling with Mailable interface Added a new Mailable interface for extracting email-related data like receiver and subject. Updated StaffAppFormData and ContactFormData to implement this interface, and refactored MailForm to utilize these details. This enhances flexibility and decouples email details from form classes.">
|
||||
<option name="closed" value="true" />
|
||||
<created>1723393276632</created>
|
||||
<option name="number" value="00035" />
|
||||
<option name="presentableId" value="LOCAL-00035" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1723393276632</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00036" summary="Update `toHtml()` method in `Form.java` Simplified the HTML structure for the `toHtml` method by switching from a table layout to paragraph tags. This removes unnecessary table formatting for improved readability and maintainability. Also updated workspace.xml with task tracking and removed outdated comments.">
|
||||
<option name="closed" value="true" />
|
||||
<created>1723393478027</created>
|
||||
<option name="number" value="00036" />
|
||||
<option name="presentableId" value="LOCAL-00036" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1723393478027</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="37" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
|
|
@ -665,10 +703,6 @@
|
|||
</option>
|
||||
</component>
|
||||
<component name="VcsManagerConfiguration">
|
||||
<MESSAGE value="Configure system property for conditional test execution Added a system property 'doNotRunDatabaseTests' in the test configuration to allow conditional skipping of database tests. This helps in running tests selectively during different build scenarios." />
|
||||
<MESSAGE value="Add CORS support for production server Updated the CORS configuration to include the production server URL. This change ensures that requests from the production environment are properly handled." />
|
||||
<MESSAGE value="Refactor logging for better granularity Updated logging levels in multiple classes to differentiate between debug and trace information. Improved log messages to support parameterized logs, ensuring sensitive or variable information is handled appropriately without concatenation." />
|
||||
<MESSAGE value="Enhance logging for mail verification details Updated logging to provide more detailed information about user credentials and email actions. This helps in debugging and monitoring mail verification processes more effectively. Adjusted trace messages to include username and password for better traceability." />
|
||||
<MESSAGE value="Update URI to point to Discord bot endpoint Changed the URI in VerifyController to use the Discord bot's endpoint for form submission. This adjustment is part of the process to route form data correctly through the specified internal service." />
|
||||
<MESSAGE value="Rename StoreFormQuery package to forms.form Updated the package name for consistency and better categorization. Adjusted imports in related test files to reflect the new package structure." />
|
||||
<MESSAGE value="Refactor HTML generation in ContactFormData Extract the HTML generation logic to a reusable method in the Form class. This change reduces code duplication and enhances maintainability by centralizing the table generation functionality." />
|
||||
|
|
@ -690,6 +724,14 @@
|
|||
<MESSAGE value="Refactor form request handling and add rate limiting. Consolidate email verification logic into FormRequestHandler to simplify code maintenance. Implement a new rate limiting feature to restrict form submissions based on IP and email address, improving server security and performance." />
|
||||
<MESSAGE value="Add form activity checking and global rate limiting Implemented new features to track form activity and enforce global rate limits. Added a `form_active` table and created endpoints to check form activity. Also, introduced a rate-limiting filter to restrict API requests to 30 per minute per IP." />
|
||||
<MESSAGE value="Ensure NOT NULL constraints in SQL tables Refactor SQL table creation scripts to add NOT NULL constraints where necessary. This change ensures data integrity by preventing null values in critical columns across the 'verify_form', 'form', 'rate_limit', and 'form_active' tables." />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Ensure NOT NULL constraints in SQL tables Refactor SQL table creation scripts to add NOT NULL constraints where necessary. This change ensures data integrity by preventing null values in critical columns across the 'verify_form', 'form', 'rate_limit', and 'form_active' tables." />
|
||||
<MESSAGE value="Add JSON response handling for form activity check Refactor `FormActiveController` to return JSON responses using `BooleanResponse`. Introduce exception handling for JSON processing errors and update `FormActiveData` to allow object initialization without parameters." />
|
||||
<MESSAGE value="Add branch condition to Discord notification stage The Discord notification stage now runs only on 'main' or 'master' branches. This helps to avoid unnecessary notifications for feature or bugfix branches." />
|
||||
<MESSAGE value="Improve email handling with Mailable interface Added a new Mailable interface for extracting email-related data like receiver and subject. Updated StaffAppFormData and ContactFormData to implement this interface, and refactored MailForm to utilize these details. This enhances flexibility and decouples email details from form classes." />
|
||||
<MESSAGE value="Update `toHtml()` method in `Form.java` Simplified the HTML structure for the `toHtml` method by switching from a table layout to paragraph tags. This removes unnecessary table formatting for improved readability and maintainability. Also updated workspace.xml with task tracking and removed outdated comments." />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Update `toHtml()` method in `Form.java` Simplified the HTML structure for the `toHtml` method by switching from a table layout to paragraph tags. This removes unnecessary table formatting for improved readability and maintainability. Also updated workspace.xml with task tracking and removed outdated comments." />
|
||||
</component>
|
||||
<component name="XSLT-Support.FileAssociations.UIState">
|
||||
<expand />
|
||||
<select />
|
||||
</component>
|
||||
</project>
|
||||
6
Jenkinsfile
vendored
6
Jenkinsfile
vendored
|
|
@ -12,6 +12,12 @@ pipeline {
|
|||
}
|
||||
}
|
||||
stage('discord') {
|
||||
when {
|
||||
anyOf {
|
||||
branch 'main'
|
||||
branch 'master'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
discordSend description: "Build: ${BUILD_NUMBER}", showChangeset: true, result: currentBuild.currentResult, title: currentBuild.fullProjectName, webhookURL: env.discordwebhook
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public class FormRequestHandler {
|
|||
private static final Logger logger = LoggerFactory.getLogger(FormRequestHandler.class);
|
||||
|
||||
public static CompletableFuture<ResponseEntity<String>> handleRequestWithVerifyMail(Form form, String ip) {
|
||||
CompletableFuture<Integer> storeFormForVerificationCode = new StoreFormQuery().storeFormForVerificationCode(form.getSender(), form);
|
||||
CompletableFuture<Integer> storeFormForVerificationCode = new StoreFormQuery().storeFormForVerificationCode(form.getSender(), form, ip);
|
||||
return storeFormForVerificationCode.thenCompose(code -> Verify.verifyEmail(ip, form.getSender(), code, form).thenApply(verificationResult -> {
|
||||
if (verificationResult == VerificationResult.VERIFICATION_SENT) {
|
||||
//TODO if this is ok tell the user they have x min to verify if they fail to do so they have to remake the form
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.alttd.forms.controlers.apply;
|
||||
|
||||
import com.alttd.forms.form.Form;
|
||||
import com.alttd.forms.mail.mail_forms.Mailable;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.validation.constraints.*;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
|
@ -9,7 +10,7 @@ import org.hibernate.validator.constraints.Range;
|
|||
import java.time.LocalDate;
|
||||
import java.util.Optional;
|
||||
|
||||
public class StaffAppFormData extends Form {
|
||||
public class StaffAppFormData extends Form implements Mailable {
|
||||
|
||||
public StaffAppFormData() {}
|
||||
|
||||
|
|
@ -125,6 +126,12 @@ public class StaffAppFormData extends Form {
|
|||
return "apply@alttd.com";
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public String getSubject() {
|
||||
return "Staff Application: " + username;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public String getSender() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.alttd.forms.controlers.contact;
|
||||
|
||||
import com.alttd.forms.form.Form;
|
||||
import com.alttd.forms.mail.mail_forms.Mailable;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
|
@ -9,7 +10,7 @@ import org.hibernate.validator.constraints.Length;
|
|||
|
||||
import java.util.Optional;
|
||||
|
||||
public class ContactFormData extends Form {
|
||||
public class ContactFormData extends Form implements Mailable {
|
||||
|
||||
public ContactFormData() {}
|
||||
|
||||
|
|
@ -54,6 +55,12 @@ public class ContactFormData extends Form {
|
|||
return "support@alttd.com";
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public String getSubject() {
|
||||
return "Contact form: " + username;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public String getSender() {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import java.sql.SQLException;
|
|||
|
||||
public class Database {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Database.class); //TODO can be replaced with library and that one db file that creates the db
|
||||
private static final Logger logger = LoggerFactory.getLogger(Database.class);
|
||||
|
||||
public static void createTables() {
|
||||
String[] createTables = {
|
||||
|
|
@ -28,6 +28,8 @@ public class Database {
|
|||
creation_date BIGINT NOT NULL,
|
||||
form_json TEXT NOT NULL,
|
||||
form_class VARCHAR(64) NOT NULL,
|
||||
ip VARCHAR(45) not null,
|
||||
time TIMESTAMP default current_timestamp() not null,
|
||||
PRIMARY KEY(formId)
|
||||
)
|
||||
""",
|
||||
|
|
|
|||
|
|
@ -18,25 +18,15 @@ public abstract class Form {
|
|||
|
||||
public String toHtml(String[] fields, String[] values) {
|
||||
StringBuilder htmlOutput = new StringBuilder();
|
||||
//language=HTML
|
||||
htmlOutput.append("<table style='border-collapse: collapse; width: 100%;'>");
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
htmlOutput.append(
|
||||
String.format(
|
||||
//language=HTML
|
||||
"""
|
||||
<tr style='border: 1px solid #ddd;'>
|
||||
<td style='border: 1px solid #ddd; padding: 10px; font-weight: bold;'>
|
||||
%s
|
||||
</td>
|
||||
<td style='border: 1px solid #ddd; padding: 10px;'>
|
||||
%s
|
||||
</td>
|
||||
</tr>
|
||||
<p><strong>%s</strong></p>
|
||||
<p>%s</p>
|
||||
""", fields[i], values[i]));
|
||||
}
|
||||
//language=HTML
|
||||
htmlOutput.append("</table>");
|
||||
return htmlOutput.toString();
|
||||
}
|
||||
|
||||
|
|
@ -45,7 +35,5 @@ public abstract class Form {
|
|||
|
||||
public abstract Optional<String> getDiscordBotUrl();
|
||||
|
||||
public abstract String getReceiver();
|
||||
|
||||
public abstract String getSender();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,29 +21,30 @@ public class StoreFormQuery {
|
|||
return 100000 + random.nextInt(900000);
|
||||
}
|
||||
|
||||
private Optional<Long> insertForm(Connection connection, Form form) {
|
||||
String insertForm = "INSERT INTO form (creation_date, form_json, form_class) VALUES (?, ?, ?)";
|
||||
private Optional<Long> insertForm(Connection connection, Form form, String ip) {
|
||||
String insertForm = "INSERT INTO form (creation_date, form_json, form_class, ip) VALUES (?, ?, ?, ?)";
|
||||
try (PreparedStatement stmt = connection.prepareStatement(insertForm, Statement.RETURN_GENERATED_KEYS)) {
|
||||
stmt.setLong(1, Instant.now().toEpochMilli());
|
||||
stmt.setString(2, form.toJsonString());
|
||||
stmt.setString(3, form.getClass().getSimpleName());
|
||||
stmt.setString(4, ip);
|
||||
int affectedRows = stmt.executeUpdate();
|
||||
if (affectedRows == 0) {
|
||||
logger.error("No rows affected during insert of form: " + form);
|
||||
logger.error("No rows affected during insert of form: {}", form);
|
||||
return Optional.empty();
|
||||
}
|
||||
ResultSet generatedKeys = stmt.getGeneratedKeys();
|
||||
if (generatedKeys.next()) {
|
||||
return Optional.of(generatedKeys.getLong(1));
|
||||
} else {
|
||||
logger.error("No primary key generated when inserting form " + form);
|
||||
logger.error("No primary key generated when inserting form {}", form);
|
||||
return Optional.empty();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
logger.error("Failed insert form query for: " + form, e);
|
||||
logger.error("Failed insert form query for: {}", form, e);
|
||||
return Optional.empty();
|
||||
} catch (JsonProcessingException e) {
|
||||
logger.error("Invalid class for JSON, failed insert form query for: " + form, e);
|
||||
logger.error("Invalid class for JSON, failed insert form query for: {}", form, e);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
|
@ -58,17 +59,17 @@ public class StoreFormQuery {
|
|||
stmt.executeUpdate();
|
||||
return Optional.of(verificationCode);
|
||||
} catch (SQLException e) {
|
||||
logger.error("Failed to insert verification code for form with id: " + formId);
|
||||
logger.error("Failed to insert verification code for form with id: {}", formId);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public CompletableFuture<Integer> storeFormForVerificationCode(String eMail, Form form) {
|
||||
public CompletableFuture<Integer> storeFormForVerificationCode(String eMail, Form form, String ip) {
|
||||
logger.debug("storeFormForVerificationCode");
|
||||
Connection connection = DatabaseConnection.getConnection();
|
||||
logger.trace("Connection: {}", connection);
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
Optional<Long> optionalFormId = insertForm(connection, form);
|
||||
Optional<Long> optionalFormId = insertForm(connection, form, ip);
|
||||
logger.trace("Form id: {}", optionalFormId);
|
||||
if (optionalFormId.isEmpty()) {
|
||||
throw new RuntimeException("Failed to store form");
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ public class MailForm {
|
|||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MailForm.class);
|
||||
|
||||
public static void sendForm(String receiver, Form form) {
|
||||
public static void sendForm(Form form, Mailable mailable) {
|
||||
String receiver = mailable.getReceiver();
|
||||
Properties mailProperties = MailSettings.getMailProperties();
|
||||
Optional<PasswordAuthentication> accountDetails = MailSettings.getAccountDetails();
|
||||
if (accountDetails.isEmpty()) {
|
||||
|
|
@ -32,8 +33,7 @@ public class MailForm {
|
|||
Message.RecipientType.TO,
|
||||
InternetAddress.parse(receiver)
|
||||
);
|
||||
message.setSubject("Altitude Form");
|
||||
//TODO add something above the html form probably
|
||||
message.setSubject(mailable.getSubject());
|
||||
message.setContent(form.toHtml(), "text/html");
|
||||
try {
|
||||
Transport.send(message);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
package com.alttd.forms.mail.mail_forms;
|
||||
|
||||
public interface Mailable {
|
||||
|
||||
String getReceiver();
|
||||
|
||||
String getSubject();
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package com.alttd.forms.verify_mail;
|
||||
|
||||
import com.alttd.forms.controlers.apply.StaffAppFormData;
|
||||
import com.alttd.forms.form.Form;
|
||||
import com.alttd.forms.mail.mail_forms.MailForm;
|
||||
import com.alttd.forms.mail.mail_forms.Mailable;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import jakarta.validation.Valid;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -41,7 +43,8 @@ public class VerifyController {
|
|||
return stringResponseEntity.get();
|
||||
}
|
||||
}
|
||||
MailForm.sendForm(form.getReceiver(), form);
|
||||
if (form instanceof Mailable mailable)
|
||||
MailForm.sendForm(form, mailable);
|
||||
try {
|
||||
return ResponseEntity.ok(form.toJsonString());
|
||||
} catch (JsonProcessingException e) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public class TestForm {
|
|||
Assertions.assertDoesNotThrow(() -> DatabaseConnection.initialize());
|
||||
StoreFormQuery storeFormQuery = new StoreFormQuery();
|
||||
ContactFormData contactFormData = new ContactFormData("akastijn", "akastijn@alttd.com", "This is a test question.");
|
||||
storeFormQuery.storeFormForVerificationCode("akastijn@alttd.com", contactFormData).
|
||||
storeFormQuery.storeFormForVerificationCode("akastijn@alttd.com", contactFormData, "0.0.0.0").
|
||||
thenAccept(code -> {
|
||||
TestForm.code = code;
|
||||
Assertions.assertTrue(code > 999 && code < 10000);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user