diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c91f5a1..23e0dbc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -446,7 +446,12 @@ Database administrators use it to create the migration scripts. **Learn-dev MPD Diagram**: -> TODO: ![MPD](docs/database/merise/learn-dev_mpd.svg) +> ![MPD](docs/database/merise/mpd/schema.svg) + +The MPD is generated by [`tbls`](https://github.com/k1LoW/tbls) from the **live +PostgreSQL database** (not from the MCD), so it always reflects the real schema. +Run `make mpd` to regenerate it; per-table documentation is in +`docs/database/merise/mpd/` (`public..md` / `.svg`). #### ERD Diagram diff --git a/Makefile b/Makefile index 231d2d1..4172e12 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ # Display the syntax with available targets help: @echo "Available targets:" - @echo " make diagrams — generate MCD, MLD, and MPD" + @echo " make diagrams — generate Merise MCD, MLD, and MPD diagrams" @echo " make mcd — generate MCD" @echo " make mld — generate MLD" @echo " make mpd — generate MPD" @@ -41,12 +41,25 @@ mld: mocodo --input docs/database/merise/learn-dev_mld.mcd --output_dir docs/database/merise --colors ocean @echo "MLD generated: docs/database/merise/learn-dev_mld.svg" -# Generate MPD from the PostgreSQL database +# Generate MPD from the PostgreSQL database. +# Percent-encode the password because it may contain URL-reserved characters. mpd: @echo "Generating MPD from PostgreSQL Database..." - @test -n "$(TBLS_DSN)" || (echo "TBLS_DSN is required (e.g., postgres://user:pass@host:5432/dbname)" >&2; exit 1) - tbls doc "$(TBLS_DSN)" docs/database/merise --force - @echo "MPD generated in docs/database/merise/" + @if [ -e .env ]; then \ + while IFS= read -r line; do \ + case "$$line" in [A-Za-z_]*=*) export "$$line";; esac; \ + done < .env; \ + fi; \ + if [ -n "$$TBLS_DSN" ]; then \ + DSN="$$TBLS_DSN"; \ + elif [ -n "$$LEARNDEV_DB_USER" ]; then \ + ENC_LEARNDEV_DB_PASSWORD=$$(printf '%s' "$$LEARNDEV_DB_PASSWORD" | python3 -c 'import sys,urllib.parse; print(urllib.parse.quote(sys.stdin.read(), safe=""))'); \ + DSN="postgres://$$LEARNDEV_DB_USER:$$ENC_LEARNDEV_DB_PASSWORD@$$POSTGRES_HOST:$$POSTGRES_PORT/$$LEARNDEV_DB_NAME?sslmode=disable"; \ + else \ + echo "TBLS_DSN is required (or define LEARNDEV_DB_* / POSTGRES_* in .env)" >&2; exit 1; \ + fi; \ + tbls doc "$$DSN" docs/database/merise/mpd --force + @echo "MPD generated in docs/database/merise/mpd/" # Clean up generated diagram files clean: diff --git a/docs/database/merise/learn-dev.mcd b/docs/database/merise/learn-dev.mcd index 7f8a71b..e2f7bc8 100644 --- a/docs/database/merise/learn-dev.mcd +++ b/docs/database/merise/learn-dev.mcd @@ -9,7 +9,7 @@ : Email Token: token_id, token, expires_at, used_at -Audit Log: log_id, action_type, entity_type, entity_id, description, ip_address, user_agent, was_successful, error_message, metadata +Audit Log: log_id, action_type, entity_type, entity_id, description, ip_address, user_agent, was_successful, error_message, metadata, created_at : Reset Token: token_id, token, expires_at, used_at, ip_address diff --git a/docs/database/merise/learn-dev.svg b/docs/database/merise/learn-dev.svg index 448fe9a..7e3c097 100644 --- a/docs/database/merise/learn-dev.svg +++ b/docs/database/merise/learn-dev.svg @@ -1,99 +1,99 @@ - - + + - - + + - - - - - Receives + + + + + Receives - 1,1 - 0,N + 1,1 + 0,N - - + + - - - - - Performs + + + + + Performs - 0,1 - 0,N + 0,1 + 0,N - - + + - - - - - Requests + + + + + Requests - 1,1 - 0,N + 1,1 + 0,N - - + + - - - - - Holds - assigned_at - assigned_by + + + + + Holds + assigned_at + assigned_by - 0,N - 0,N + 0,N + 0,N - - - - + + + + - Email Token - token_id - - token - expires_at - used_at + Email Token + token_id + + token + expires_at + used_at - - + + Audit Log log_id action_type - entity_type + entity_type entity_id description ip_address @@ -101,62 +101,63 @@ was_successful error_message metadata + created_at - - - - + + + + - Reset Token - token_id - - token - expires_at - used_at - ip_address + Reset Token + token_id + + token + expires_at + used_at + ip_address - - - - + + + + - User - user_id - - username - email - password - first_name - last_name - is_active - is_verified - is_locked - failed_login_attempts - last_login_at - password_changed_at + User + user_id + + username + email + password + first_name + last_name + is_active + is_verified + is_locked + failed_login_attempts + last_login_at + password_changed_at - - - - + + + + - Role - role_id - - role_name - description - is_active + Role + role_id + + role_name + description + is_active \ No newline at end of file diff --git a/docs/database/merise/learn-dev_mld.svg b/docs/database/merise/learn-dev_mld.svg index b999402..7e20c93 100644 --- a/docs/database/merise/learn-dev_mld.svg +++ b/docs/database/merise/learn-dev_mld.svg @@ -1,31 +1,31 @@ - - + + - - - - + + + + - Email Token - token_id - - token - expires_at - used_at - #user_id + Email Token + token_id + + token + expires_at + used_at + #user_id - - + + Audit Log @@ -36,110 +36,111 @@ entity_id description ip_address - user_agent + user_agent was_successful error_message metadata - #user_id + created_at + #user_id - - - - + + + + - Reset Token - token_id - - token - expires_at - used_at - ip_address - #user_id + Reset Token + token_id + + token + expires_at + used_at + ip_address + #user_id - - - - + + + + - User - user_id - - username - email - password - first_name - last_name - is_active - is_verified - is_locked - failed_login_attempts - last_login_at - password_changed_at + User + user_id + + username + email + password + first_name + last_name + is_active + is_verified + is_locked + failed_login_attempts + last_login_at + password_changed_at - - - - + + + + - Holds - #user_id - - #role_id - - assigned_at - assigned_by + Holds + #user_id + + #role_id + + assigned_at + assigned_by - - - - + + + + - Role - role_id - - role_name - description - is_active + Role + role_id + + role_name + description + is_active - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + \ No newline at end of file diff --git a/docs/database/merise/mpd/README.md b/docs/database/merise/mpd/README.md new file mode 100644 index 0000000..6b7473e --- /dev/null +++ b/docs/database/merise/mpd/README.md @@ -0,0 +1,24 @@ +# learn-dev + +## Description + +Learn-dev MPD (Physical Data Model) + +## Tables + +| Name | Columns | Comment | Type | +| ---- | ------- | ------- | ---- | +| [public.users](public.users.md) | 12 | | BASE TABLE | +| [public.roles](public.roles.md) | 4 | | BASE TABLE | +| [public.user_roles](public.user_roles.md) | 4 | | BASE TABLE | +| [public.email_tokens](public.email_tokens.md) | 5 | | BASE TABLE | +| [public.reset_tokens](public.reset_tokens.md) | 6 | | BASE TABLE | +| [public.audit_logs](public.audit_logs.md) | 12 | | BASE TABLE | + +## Relations + +![er](schema.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/database/merise/mpd/public.audit_logs.md b/docs/database/merise/mpd/public.audit_logs.md new file mode 100644 index 0000000..e9049bd --- /dev/null +++ b/docs/database/merise/mpd/public.audit_logs.md @@ -0,0 +1,40 @@ +# public.audit_logs + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| log_id | bigint | | false | | | | +| action_type | varchar(100) | | false | | | | +| entity_type | varchar(100) | | true | | | | +| entity_id | varchar(64) | | true | | | | +| description | text | | true | | | | +| ip_address | inet | | true | | | | +| user_agent | text | | true | | | | +| was_successful | boolean | true | false | | | | +| error_message | text | | true | | | | +| metadata | jsonb | | true | | | | +| created_at | timestamp with time zone | now() | false | | | | +| user_id | uuid | | true | | [public.users](public.users.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| audit_logs_user_id_fkey | FOREIGN KEY | FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE SET NULL | +| audit_logs_pkey | PRIMARY KEY | PRIMARY KEY (log_id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| audit_logs_pkey | CREATE UNIQUE INDEX audit_logs_pkey ON public.audit_logs USING btree (log_id) | +| idx_audit_logs_user_id | CREATE INDEX idx_audit_logs_user_id ON public.audit_logs USING btree (user_id) | + +## Relations + +![er](public.audit_logs.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/database/merise/mpd/public.audit_logs.svg b/docs/database/merise/mpd/public.audit_logs.svg new file mode 100644 index 0000000..93ee9ab --- /dev/null +++ b/docs/database/merise/mpd/public.audit_logs.svg @@ -0,0 +1,110 @@ + + + + + + +public.audit_logs + + + +public.audit_logs + + +public.audit_logs +     +[BASE TABLE] + +log_id +[bigint] + +action_type +[varchar(100)] + +entity_type +[varchar(100)] + +entity_id +[varchar(64)] + +description +[text] + +ip_address +[inet] + +user_agent +[text] + +was_successful +[boolean] + +error_message +[text] + +metadata +[jsonb] + +created_at +[timestamp with time zone] + +user_id +[uuid] + + + + +public.users + + +public.users +     +[BASE TABLE] + +user_id +[uuid] + +username +[varchar(50)] + +email +[varchar(255)] + +password +[varchar(255)] + +first_name +[varchar(100)] + +last_name +[varchar(100)] + +is_active +[boolean] + +is_verified +[boolean] + +is_locked +[boolean] + +failed_login_attempts +[integer] + +last_login_at +[timestamp with time zone] + +password_changed_at +[timestamp with time zone] + + + +public.audit_logs:user_id->public.users:user_id + + + + + diff --git a/docs/database/merise/mpd/public.email_tokens.md b/docs/database/merise/mpd/public.email_tokens.md new file mode 100644 index 0000000..0258555 --- /dev/null +++ b/docs/database/merise/mpd/public.email_tokens.md @@ -0,0 +1,35 @@ +# public.email_tokens + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| token_id | bigint | | false | | | | +| token | varchar(255) | | false | | | | +| expires_at | timestamp with time zone | | false | | | | +| used_at | timestamp with time zone | | true | | | | +| user_id | uuid | | false | | [public.users](public.users.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| email_tokens_user_id_fkey | FOREIGN KEY | FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE | +| email_tokens_pkey | PRIMARY KEY | PRIMARY KEY (token_id) | +| email_tokens_token_key | UNIQUE | UNIQUE (token) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| email_tokens_pkey | CREATE UNIQUE INDEX email_tokens_pkey ON public.email_tokens USING btree (token_id) | +| email_tokens_token_key | CREATE UNIQUE INDEX email_tokens_token_key ON public.email_tokens USING btree (token) | +| idx_email_tokens_user_id | CREATE INDEX idx_email_tokens_user_id ON public.email_tokens USING btree (user_id) | + +## Relations + +![er](public.email_tokens.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/database/merise/mpd/public.email_tokens.svg b/docs/database/merise/mpd/public.email_tokens.svg new file mode 100644 index 0000000..af01e3b --- /dev/null +++ b/docs/database/merise/mpd/public.email_tokens.svg @@ -0,0 +1,89 @@ + + + + + + +public.email_tokens + + + +public.email_tokens + + +public.email_tokens +     +[BASE TABLE] + +token_id +[bigint] + +token +[varchar(255)] + +expires_at +[timestamp with time zone] + +used_at +[timestamp with time zone] + +user_id +[uuid] + + + + +public.users + + +public.users +     +[BASE TABLE] + +user_id +[uuid] + +username +[varchar(50)] + +email +[varchar(255)] + +password +[varchar(255)] + +first_name +[varchar(100)] + +last_name +[varchar(100)] + +is_active +[boolean] + +is_verified +[boolean] + +is_locked +[boolean] + +failed_login_attempts +[integer] + +last_login_at +[timestamp with time zone] + +password_changed_at +[timestamp with time zone] + + + +public.email_tokens:user_id->public.users:user_id + + + + + diff --git a/docs/database/merise/mpd/public.reset_tokens.md b/docs/database/merise/mpd/public.reset_tokens.md new file mode 100644 index 0000000..b3f5689 --- /dev/null +++ b/docs/database/merise/mpd/public.reset_tokens.md @@ -0,0 +1,36 @@ +# public.reset_tokens + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| token_id | bigint | | false | | | | +| token | varchar(255) | | false | | | | +| expires_at | timestamp with time zone | | false | | | | +| used_at | timestamp with time zone | | true | | | | +| ip_address | inet | | true | | | | +| user_id | uuid | | false | | [public.users](public.users.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| reset_tokens_user_id_fkey | FOREIGN KEY | FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE | +| reset_tokens_pkey | PRIMARY KEY | PRIMARY KEY (token_id) | +| reset_tokens_token_key | UNIQUE | UNIQUE (token) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| reset_tokens_pkey | CREATE UNIQUE INDEX reset_tokens_pkey ON public.reset_tokens USING btree (token_id) | +| reset_tokens_token_key | CREATE UNIQUE INDEX reset_tokens_token_key ON public.reset_tokens USING btree (token) | +| idx_reset_tokens_user_id | CREATE INDEX idx_reset_tokens_user_id ON public.reset_tokens USING btree (user_id) | + +## Relations + +![er](public.reset_tokens.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/database/merise/mpd/public.reset_tokens.svg b/docs/database/merise/mpd/public.reset_tokens.svg new file mode 100644 index 0000000..cb0a6b4 --- /dev/null +++ b/docs/database/merise/mpd/public.reset_tokens.svg @@ -0,0 +1,92 @@ + + + + + + +public.reset_tokens + + + +public.reset_tokens + + +public.reset_tokens +     +[BASE TABLE] + +token_id +[bigint] + +token +[varchar(255)] + +expires_at +[timestamp with time zone] + +used_at +[timestamp with time zone] + +ip_address +[inet] + +user_id +[uuid] + + + + +public.users + + +public.users +     +[BASE TABLE] + +user_id +[uuid] + +username +[varchar(50)] + +email +[varchar(255)] + +password +[varchar(255)] + +first_name +[varchar(100)] + +last_name +[varchar(100)] + +is_active +[boolean] + +is_verified +[boolean] + +is_locked +[boolean] + +failed_login_attempts +[integer] + +last_login_at +[timestamp with time zone] + +password_changed_at +[timestamp with time zone] + + + +public.reset_tokens:user_id->public.users:user_id + + + + + diff --git a/docs/database/merise/mpd/public.roles.md b/docs/database/merise/mpd/public.roles.md new file mode 100644 index 0000000..13c7cf2 --- /dev/null +++ b/docs/database/merise/mpd/public.roles.md @@ -0,0 +1,32 @@ +# public.roles + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| role_id | bigint | | false | [public.user_roles](public.user_roles.md) | | | +| role_name | varchar(50) | | false | | | | +| description | varchar(255) | | true | | | | +| is_active | boolean | true | false | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| roles_pkey | PRIMARY KEY | PRIMARY KEY (role_id) | +| roles_role_name_key | UNIQUE | UNIQUE (role_name) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| roles_pkey | CREATE UNIQUE INDEX roles_pkey ON public.roles USING btree (role_id) | +| roles_role_name_key | CREATE UNIQUE INDEX roles_role_name_key ON public.roles USING btree (role_name) | + +## Relations + +![er](public.roles.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/database/merise/mpd/public.roles.svg b/docs/database/merise/mpd/public.roles.svg new file mode 100644 index 0000000..148bcf7 --- /dev/null +++ b/docs/database/merise/mpd/public.roles.svg @@ -0,0 +1,62 @@ + + + + + + +public.roles + + + +public.roles + + +public.roles +     +[BASE TABLE] + +role_id +[bigint] + +role_name +[varchar(50)] + +description +[varchar(255)] + +is_active +[boolean] + + + + +public.user_roles + + +public.user_roles +     +[BASE TABLE] + +user_id +[uuid] + +role_id +[bigint] + +assigned_at +[timestamp with time zone] + +assigned_by +[uuid] + + + +public.user_roles:role_id->public.roles:role_id + + + + + diff --git a/docs/database/merise/mpd/public.user_roles.md b/docs/database/merise/mpd/public.user_roles.md new file mode 100644 index 0000000..60537b1 --- /dev/null +++ b/docs/database/merise/mpd/public.user_roles.md @@ -0,0 +1,34 @@ +# public.user_roles + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| user_id | uuid | | false | | [public.users](public.users.md) | | +| role_id | bigint | | false | | [public.roles](public.roles.md) | | +| assigned_at | timestamp with time zone | now() | false | | | | +| assigned_by | uuid | | true | | [public.users](public.users.md) | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| user_roles_assigned_by_fkey | FOREIGN KEY | FOREIGN KEY (assigned_by) REFERENCES users(user_id) ON DELETE SET NULL | +| user_roles_user_id_fkey | FOREIGN KEY | FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE | +| user_roles_role_id_fkey | FOREIGN KEY | FOREIGN KEY (role_id) REFERENCES roles(role_id) ON DELETE CASCADE | +| user_roles_pkey | PRIMARY KEY | PRIMARY KEY (user_id, role_id) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| user_roles_pkey | CREATE UNIQUE INDEX user_roles_pkey ON public.user_roles USING btree (user_id, role_id) | +| idx_user_roles_role_id | CREATE INDEX idx_user_roles_role_id ON public.user_roles USING btree (role_id) | + +## Relations + +![er](public.user_roles.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/database/merise/mpd/public.user_roles.svg b/docs/database/merise/mpd/public.user_roles.svg new file mode 100644 index 0000000..f373d99 --- /dev/null +++ b/docs/database/merise/mpd/public.user_roles.svg @@ -0,0 +1,125 @@ + + + + + + +public.user_roles + + + +public.user_roles + + +public.user_roles +     +[BASE TABLE] + +user_id +[uuid] + +role_id +[bigint] + +assigned_at +[timestamp with time zone] + +assigned_by +[uuid] + + + + +public.users + + +public.users +     +[BASE TABLE] + +user_id +[uuid] + +username +[varchar(50)] + +email +[varchar(255)] + +password +[varchar(255)] + +first_name +[varchar(100)] + +last_name +[varchar(100)] + +is_active +[boolean] + +is_verified +[boolean] + +is_locked +[boolean] + +failed_login_attempts +[integer] + +last_login_at +[timestamp with time zone] + +password_changed_at +[timestamp with time zone] + + + +public.user_roles:user_id->public.users:user_id + + + + + +public.user_roles:assigned_by->public.users:user_id + + + + + +public.user_roles:assigned_by->public.users:user_id + + + + + +public.roles + + +public.roles +     +[BASE TABLE] + +role_id +[bigint] + +role_name +[varchar(50)] + +description +[varchar(255)] + +is_active +[boolean] + + + +public.user_roles:role_id->public.roles:role_id + + + + + diff --git a/docs/database/merise/mpd/public.users.md b/docs/database/merise/mpd/public.users.md new file mode 100644 index 0000000..278ef47 --- /dev/null +++ b/docs/database/merise/mpd/public.users.md @@ -0,0 +1,42 @@ +# public.users + +## Columns + +| Name | Type | Default | Nullable | Children | Parents | Comment | +| ---- | ---- | ------- | -------- | -------- | ------- | ------- | +| user_id | uuid | gen_random_uuid() | false | [public.user_roles](public.user_roles.md) [public.email_tokens](public.email_tokens.md) [public.reset_tokens](public.reset_tokens.md) [public.audit_logs](public.audit_logs.md) | | | +| username | varchar(50) | | false | | | | +| email | varchar(255) | | false | | | | +| password | varchar(255) | | false | | | | +| first_name | varchar(100) | | true | | | | +| last_name | varchar(100) | | true | | | | +| is_active | boolean | true | false | | | | +| is_verified | boolean | false | false | | | | +| is_locked | boolean | false | false | | | | +| failed_login_attempts | integer | 0 | false | | | | +| last_login_at | timestamp with time zone | | true | | | | +| password_changed_at | timestamp with time zone | | true | | | | + +## Constraints + +| Name | Type | Definition | +| ---- | ---- | ---------- | +| users_pkey | PRIMARY KEY | PRIMARY KEY (user_id) | +| users_username_key | UNIQUE | UNIQUE (username) | +| users_email_key | UNIQUE | UNIQUE (email) | + +## Indexes + +| Name | Definition | +| ---- | ---------- | +| users_pkey | CREATE UNIQUE INDEX users_pkey ON public.users USING btree (user_id) | +| users_username_key | CREATE UNIQUE INDEX users_username_key ON public.users USING btree (username) | +| users_email_key | CREATE UNIQUE INDEX users_email_key ON public.users USING btree (email) | + +## Relations + +![er](public.users.svg) + +--- + +> Generated by [tbls](https://github.com/k1LoW/tbls) diff --git a/docs/database/merise/mpd/public.users.svg b/docs/database/merise/mpd/public.users.svg new file mode 100644 index 0000000..2459378 --- /dev/null +++ b/docs/database/merise/mpd/public.users.svg @@ -0,0 +1,212 @@ + + + + + + +public.users + + + +public.users + + +public.users +     +[BASE TABLE] + +user_id +[uuid] + +username +[varchar(50)] + +email +[varchar(255)] + +password +[varchar(255)] + +first_name +[varchar(100)] + +last_name +[varchar(100)] + +is_active +[boolean] + +is_verified +[boolean] + +is_locked +[boolean] + +failed_login_attempts +[integer] + +last_login_at +[timestamp with time zone] + +password_changed_at +[timestamp with time zone] + + + + +public.user_roles + + +public.user_roles +     +[BASE TABLE] + +user_id +[uuid] + +role_id +[bigint] + +assigned_at +[timestamp with time zone] + +assigned_by +[uuid] + + + +public.user_roles:assigned_by->public.users:user_id + + + + + +public.user_roles:user_id->public.users:user_id + + + + + +public.user_roles:assigned_by->public.users:user_id + + + + + +public.email_tokens + + +public.email_tokens +     +[BASE TABLE] + +token_id +[bigint] + +token +[varchar(255)] + +expires_at +[timestamp with time zone] + +used_at +[timestamp with time zone] + +user_id +[uuid] + + + +public.email_tokens:user_id->public.users:user_id + + + + + +public.reset_tokens + + +public.reset_tokens +     +[BASE TABLE] + +token_id +[bigint] + +token +[varchar(255)] + +expires_at +[timestamp with time zone] + +used_at +[timestamp with time zone] + +ip_address +[inet] + +user_id +[uuid] + + + +public.reset_tokens:user_id->public.users:user_id + + + + + +public.audit_logs + + +public.audit_logs +     +[BASE TABLE] + +log_id +[bigint] + +action_type +[varchar(100)] + +entity_type +[varchar(100)] + +entity_id +[varchar(64)] + +description +[text] + +ip_address +[inet] + +user_agent +[text] + +was_successful +[boolean] + +error_message +[text] + +metadata +[jsonb] + +created_at +[timestamp with time zone] + +user_id +[uuid] + + + +public.audit_logs:user_id->public.users:user_id + + + + + diff --git a/docs/database/merise/mpd/schema.svg b/docs/database/merise/mpd/schema.svg new file mode 100644 index 0000000..3a08b89 --- /dev/null +++ b/docs/database/merise/mpd/schema.svg @@ -0,0 +1,238 @@ + + + + + + +learn-dev + + + +public.users + + +public.users +     +[BASE TABLE] + +user_id +[uuid] + +username +[varchar(50)] + +email +[varchar(255)] + +password +[varchar(255)] + +first_name +[varchar(100)] + +last_name +[varchar(100)] + +is_active +[boolean] + +is_verified +[boolean] + +is_locked +[boolean] + +failed_login_attempts +[integer] + +last_login_at +[timestamp with time zone] + +password_changed_at +[timestamp with time zone] + + + +public.roles + + +public.roles +     +[BASE TABLE] + +role_id +[bigint] + +role_name +[varchar(50)] + +description +[varchar(255)] + +is_active +[boolean] + + + +public.user_roles + + +public.user_roles +     +[BASE TABLE] + +user_id +[uuid] + +role_id +[bigint] + +assigned_at +[timestamp with time zone] + +assigned_by +[uuid] + + + +public.user_roles:assigned_by->public.users:user_id + + + + + +public.user_roles:user_id->public.users:user_id + + + + + +public.user_roles:assigned_by->public.users:user_id + + + + + +public.user_roles:role_id->public.roles:role_id + + + + + +public.email_tokens + + +public.email_tokens +     +[BASE TABLE] + +token_id +[bigint] + +token +[varchar(255)] + +expires_at +[timestamp with time zone] + +used_at +[timestamp with time zone] + +user_id +[uuid] + + + +public.email_tokens:user_id->public.users:user_id + + + + + +public.reset_tokens + + +public.reset_tokens +     +[BASE TABLE] + +token_id +[bigint] + +token +[varchar(255)] + +expires_at +[timestamp with time zone] + +used_at +[timestamp with time zone] + +ip_address +[inet] + +user_id +[uuid] + + + +public.reset_tokens:user_id->public.users:user_id + + + + + +public.audit_logs + + +public.audit_logs +     +[BASE TABLE] + +log_id +[bigint] + +action_type +[varchar(100)] + +entity_type +[varchar(100)] + +entity_id +[varchar(64)] + +description +[text] + +ip_address +[inet] + +user_agent +[text] + +was_successful +[boolean] + +error_message +[text] + +metadata +[jsonb] + +created_at +[timestamp with time zone] + +user_id +[uuid] + + + +public.audit_logs:user_id->public.users:user_id + + + + + diff --git a/tbls.yaml b/tbls.yaml new file mode 100644 index 0000000..5650a2b --- /dev/null +++ b/tbls.yaml @@ -0,0 +1,42 @@ +# ~~~ Database name of the document +# +name: learn-dev + +# ~~~ Database description +# +desc: Learn-dev MPD (Physical Data Model) + +# ~~~ Do not generate JSON schema file +# +disableOutputSchema: true + +# ~~~ Hide Liquibase tables +# +exclude: [databasechangelog, databasechangeloglock] + +# ~~~ Relations +# Help tbls infer the self-reference on user_roles.assigned_by, +# which it cannot detect from foreign keys alone. +# +relations: + - table: user_roles + columns: + - assigned_by + parentTable: users + parentColumns: + - user_id + def: admin who assigned the role + +er: + # ER diagram image format (`png`, `jpg`, `svg`, `mermaid`) + # Default is `svg` + format: svg + # Add table/column comment to ER diagram + # Default is false + comment: true + # Hide relation definition from ER diagram + # Default is false + hideDef: true + # Distance between tables that display relations in the ER + # Default is 1 (only directly-related tables appear in each table's diagram) + distance: 1