diff --git a/README.md b/README.md index e38e1de..68fe254 100644 --- a/README.md +++ b/README.md @@ -36,11 +36,18 @@ cd backend ./mvnw quarkus:dev ``` -Default database settings already point to the local Docker PostgreSQL instance: +Default database settings point to the local Docker PostgreSQL instance, including in the `dev` profile: -- database: `timetrack` -- user: `timetrack` -- password: `timetrack` +- database: `beetask` +- user: `beetask` +- password: `beetask` +- JDBC URL: `jdbc:postgresql://localhost:5432/beetask` + +If needed, you can override them with: + +- `DB_URL` +- `DB_USER` +- `DB_PASSWORD` Main API endpoints: diff --git a/backend/pom.xml b/backend/pom.xml index d7ba451..4746dd9 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -51,6 +51,10 @@ io.quarkus quarkus-smallrye-openapi + + io.quarkus + quarkus-smallrye-health + io.quarkus quarkus-flyway diff --git a/backend/src/main/java/net/beetechgroup/beetask/frameworks/persistence/entities/TaskEntity.java b/backend/src/main/java/net/beetechgroup/beetask/frameworks/persistence/entities/TaskEntity.java index 7769d19..da079f0 100644 --- a/backend/src/main/java/net/beetechgroup/beetask/frameworks/persistence/entities/TaskEntity.java +++ b/backend/src/main/java/net/beetechgroup/beetask/frameworks/persistence/entities/TaskEntity.java @@ -3,9 +3,9 @@ package net.beetechgroup.beetask.frameworks.persistence.entities; import java.util.List; import jakarta.persistence.CascadeType; -import jakarta.persistence.CollectionTable; -import jakarta.persistence.ElementCollection; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -23,6 +23,7 @@ public class TaskEntity { private Long id; private String title; private String description; + @Enumerated(EnumType.STRING) private TaskStatus status; private java.time.LocalDateTime finishedAt; diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index d2d6ea4..afcf60d 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -3,22 +3,18 @@ quarkus.http.cors=true quarkus.http.cors.origins=http://localhost:5173 quarkus.datasource.db-kind=postgresql -quarkus.datasource.username=${DB_USER:timetrack} -quarkus.datasource.password=${DB_PASSWORD:timetrack} -quarkus.datasource.jdbc.url=${DB_URL:jdbc:postgresql://localhost:5432/timetrack} +quarkus.datasource.username=${DB_USER:beetask} +quarkus.datasource.password=${DB_PASSWORD:beetask} +quarkus.datasource.jdbc.url=${DB_URL:jdbc:postgresql://localhost:5432/beetask} -%dev.quarkus.datasource.db-kind=h2 -%dev.quarkus.datasource.jdbc.url=jdbc:h2:file:./data/beetask;DB_CLOSE_DELAY=-1;AUTO_SERVER=TRUE -%dev.quarkus.h2.console=true -%dev.quarkus.hibernate-orm.database.generation=update - -quarkus.flyway.migrate-at-start=false +quarkus.flyway.migrate-at-start=true quarkus.hibernate-orm.database.generation=validate # Swagger & OpenAPI quarkus.smallrye-openapi.path=/openapi quarkus.swagger-ui.path=/swagger quarkus.swagger-ui.always-include=true +quarkus.smallrye-health.root-path=/status # JWT Security mp.jwt.verify.issuer=https://beetech.net diff --git a/backend/src/main/resources/db/migration/V1__create_tasks.sql b/backend/src/main/resources/db/migration/V1__create_tasks.sql deleted file mode 100644 index 0895825..0000000 --- a/backend/src/main/resources/db/migration/V1__create_tasks.sql +++ /dev/null @@ -1,13 +0,0 @@ -CREATE TABLE tasks ( - id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, - title VARCHAR(255) NOT NULL, - description VARCHAR(2000), - status VARCHAR(32) NOT NULL, - project VARCHAR(255) -); - -CREATE TABLE task_activities ( - task_id BIGINT NOT NULL, - activity VARCHAR(255), - CONSTRAINT fk_task_activities_task FOREIGN KEY (task_id) REFERENCES tasks (id) -); diff --git a/backend/src/main/resources/db/migration/V1__first_version.sql b/backend/src/main/resources/db/migration/V1__first_version.sql new file mode 100644 index 0000000..40e4cba --- /dev/null +++ b/backend/src/main/resources/db/migration/V1__first_version.sql @@ -0,0 +1,82 @@ +CREATE TABLE users_entity ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, + password VARCHAR(255) NOT NULL, + photo VARCHAR(1000), + CONSTRAINT uk_users_entity_email UNIQUE (email) +); + +CREATE TABLE organizations ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL +); + +CREATE TABLE projects ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + name VARCHAR(255) NOT NULL, + organization_id BIGINT, + CONSTRAINT fk_projects_organization + FOREIGN KEY (organization_id) REFERENCES organizations (id) +); + +CREATE TABLE user_organizations ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + user_id BIGINT, + organization_id BIGINT, + role VARCHAR(32), + status VARCHAR(32), + CONSTRAINT fk_user_organizations_user + FOREIGN KEY (user_id) REFERENCES users_entity (id), + CONSTRAINT fk_user_organizations_organization + FOREIGN KEY (organization_id) REFERENCES organizations (id), + CONSTRAINT uk_user_organizations_user_org UNIQUE (user_id, organization_id), + CONSTRAINT chk_user_organizations_role + CHECK (role IN ('OWNER', 'ADMIN', 'MEMBER')), + CONSTRAINT chk_user_organizations_status + CHECK (status IN ('PENDING', 'ACTIVE', 'REJECTED')) +); + +CREATE TABLE project_users ( + project_id BIGINT NOT NULL, + user_id BIGINT NOT NULL, + CONSTRAINT pk_project_users PRIMARY KEY (project_id, user_id), + CONSTRAINT fk_project_users_project + FOREIGN KEY (project_id) REFERENCES projects (id), + CONSTRAINT fk_project_users_user + FOREIGN KEY (user_id) REFERENCES users_entity (id) +); + +CREATE TABLE tasks ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + title VARCHAR(255), + description VARCHAR(255), + status VARCHAR(32), + finished_at TIMESTAMP(6), + project_id BIGINT, + user_id BIGINT, + CONSTRAINT fk_tasks_project + FOREIGN KEY (project_id) REFERENCES projects (id), + CONSTRAINT fk_tasks_user + FOREIGN KEY (user_id) REFERENCES users_entity (id), + CONSTRAINT chk_tasks_status + CHECK (status IN ('NOT_STARTED', 'IN_PROGRESS', 'COMPLETED', 'CANCELED')) +); + +CREATE TABLE task_history ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + start_at TIMESTAMP(6), + end_at TIMESTAMP(6), + task_id BIGINT, + CONSTRAINT fk_task_history_task + FOREIGN KEY (task_id) REFERENCES tasks (id) +); + +CREATE INDEX idx_projects_organization_id ON projects (organization_id); +CREATE INDEX idx_user_organizations_user_id ON user_organizations (user_id); +CREATE INDEX idx_user_organizations_organization_id ON user_organizations (organization_id); +CREATE INDEX idx_project_users_user_id ON project_users (user_id); +CREATE INDEX idx_tasks_project_id ON tasks (project_id); +CREATE INDEX idx_tasks_user_id ON tasks (user_id); +CREATE INDEX idx_tasks_status ON tasks (status); +CREATE INDEX idx_task_history_task_id ON task_history (task_id); diff --git a/backend/src/main/resources/import.sql b/backend/src/main/resources/import.sql index 16aa523..e69de29 100644 --- a/backend/src/main/resources/import.sql +++ b/backend/src/main/resources/import.sql @@ -1,6 +0,0 @@ --- This file allow to write SQL commands that will be emitted in test and dev. --- The commands are commented as their support depends of the database --- insert into myentity (id, field) values(1, 'field-1'); --- insert into myentity (id, field) values(2, 'field-2'); --- insert into myentity (id, field) values(3, 'field-3'); --- alter sequence myentity_seq restart with 4; \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index aea32f1..41b8182 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,40 +1,21 @@ services: postgres: image: postgres:18.3 - container_name: timetrack-postgres + container_name: bee-task-postgres environment: - POSTGRES_USER: timetrack - POSTGRES_PASSWORD: timetrack - POSTGRES_DB: timetrack + POSTGRES_USER: beetask + POSTGRES_PASSWORD: beetask + POSTGRES_DB: beetask ports: - "5432:5432" volumes: - - postgres_data:/var/lib/postgresql + - postgres_data:/var/lib/postgresql/data - ./docker/postgres/init:/docker-entrypoint-initdb.d healthcheck: - test: ["CMD-SHELL", "pg_isready -U timetrack"] + test: ["CMD-SHELL", "pg_isready -U beetask"] interval: 10s timeout: 5s retries: 5 - keycloak: - image: quay.io/keycloak/keycloak:26.6.1 - container_name: timetrack-keycloak - command: start-dev - environment: - KEYCLOAK_ADMIN: admin - KEYCLOAK_ADMIN_PASSWORD: admin - KC_DB: postgres - KC_DB_URL_HOST: postgres - KC_DB_URL_PORT: 5432 - KC_DB_URL_DATABASE: keycloak - KC_DB_USERNAME: timetrack - KC_DB_PASSWORD: timetrack - ports: - - "8081:8080" - depends_on: - postgres: - condition: service_healthy - volumes: postgres_data: