Skip to content
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
9 changes: 7 additions & 2 deletions .example.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_NAME=codebloom
DATABASE_NAME=patchats
DATABASE_USER=postgres
DATABASE_PASSWORD=enterpasswordhere
# With the example values, this gets combined inside of the application.properties to make
# jdbc://postgresql://localhost:5432/codebloom?user=postgres&password=enterpasswordhere
# jdbc://postgresql://localhost:5432/patchats?user=postgres&password=enterpasswordhere

# SMTP — consumed by spring.mail.* in non-dev profiles (the dev profile logs instead of sending)
SMTP_HOST=smtp.example.com
Expand All @@ -16,3 +16,8 @@ SMTP_PASSWORD=enterpasswordhere
# The verified From sender (a real, monitored mailbox on a domain you control)
EMAIL_FROM=coffeechats@patinanetwork.org
EMAIL_FROM_NAME=PatChats

# Auth — public origin of the SPA; magic links point at $APP_BASE_URL/auth/verify?token=...
APP_BASE_URL=http://localhost:5173
# Set to false only when serving over plain HTTP (the dev profile already does this)
AUTH_COOKIE_SECURE=true
9 changes: 9 additions & 0 deletions db/migration/V0004__Relax_members_for_shell_accounts.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-- Magic-link auth creates a minimal "shell" member row at link-verification time,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we sending them a magic link before they fill out the sign up form?

-- before the user has filled in the sign-up form, so full_name can no longer be required.
ALTER TABLE "members" ALTER COLUMN full_name DROP NOT NULL;

-- Set when the member has completed the sign-up form; NULL marks a shell account.
ALTER TABLE "members" ADD COLUMN profile_completed_at TIMESTAMPTZ;

-- Existing rows were created through the full sign-up form; treat them as complete.
UPDATE "members" SET profile_completed_at = created_at WHERE full_name IS NOT NULL;
12 changes: 12 additions & 0 deletions db/migration/V0005__Create_magic_link_tokens_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- Single-use sign-in tokens emailed to users. Keyed by email (not member id)
-- because the member row is only created once the link is verified.
CREATE TABLE IF NOT EXISTS "magic_link_tokens" (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should figure out a style guide for SQL stuff. Should the table names be lowercase or caps or whatever standard?

id UUID PRIMARY KEY,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be uuid? Maybe investigate?

email TEXT NOT NULL,
token_hash TEXT UNIQUE NOT NULL,
expires_at TIMESTAMPTZ NOT NULL,
consumed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_magic_link_tokens_email ON "magic_link_tokens" (email);
26 changes: 26 additions & 0 deletions db/migration/V0006__Create_spring_session_tables.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
-- Spring Session JDBC schema, copied verbatim from spring-session-jdbc's
-- org/springframework/session/jdbc/schema-postgresql.sql so Flyway owns it
-- (spring.session.jdbc.initialize-schema is set to "never" in application.yml).
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
EXPIRY_TIME BIGINT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
);

CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME);
CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);

CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES BYTEA NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID)
REFERENCES SPRING_SESSION (PRIMARY_ID) ON DELETE CASCADE
);
13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,19 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!-- <dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot3</artifactId>
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
app:
auth:
# Dev runs plain HTTP through the Vite proxy; a Secure cookie would be silently dropped.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be the case? Should we be logging in on dev too?

cookie-secure: false
23 changes: 21 additions & 2 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
datasource:
url: jdbc:postgresql://${DATABASE_HOST:localhost}:${DATABASE_PORT:5432}/${DATABASE_NAME:patchats}
username: ${DATABASE_USER:postgres}
password: ${DATABASE_PASSWORD:}
Comment on lines +2 to +5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll look into this and see if we should be leaning towards spring's jdbc or what not.

flyway:
# Migrations run out-of-band via the Flyway Maven plugin (`just migrate`), never at startup.
enabled: false
session:
timeout: 30d
jdbc:
# Schema is owned by Flyway (V0006) so the app never races the migration.
initialize-schema: never
mail:
host: ${SMTP_HOST:}
port: ${SMTP_PORT:587}
Expand All @@ -13,9 +23,18 @@ spring:
starttls:
enable: true

server:
# Trust X-Forwarded-* from the reverse proxy so rate limiting sees real client IPs.
forward-headers-strategy: framework
Comment on lines +26 to +28

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotta investigate what this does.


app:
commit:
sha: "@commit.sha@"
email:
from: ${EMAIL_FROM:coffeechats@patinanetwork.org}
from-name: ${EMAIL_FROM_NAME:PatChats}
auth:
# Public origin of the SPA; magic links point at <base-url>/auth/verify?token=...
base-url: ${APP_BASE_URL:http://localhost:5173}
cookie-secure: ${AUTH_COOKIE_SECURE:true}
magic-link-ttl: 15m
Loading