diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ab01cc8..1340b6f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: release_semantic_dry: needs: prepare_jobs name: Release (semantic, dry) - uses: dargmuesli/github-actions/.github/workflows/release-semantic.yml@2.3.3 + uses: dargmuesli/github-actions/.github/workflows/release-semantic.yml@2.3.9 if: needs.prepare_jobs.outputs.pr_found == 'false' || github.event_name == 'pull_request' permissions: contents: write @@ -35,7 +35,7 @@ jobs: DRY_RUN: true build: name: Build - uses: dargmuesli/github-actions/.github/workflows/docker.yml@2.3.3 + uses: dargmuesli/github-actions/.github/workflows/docker.yml@2.3.9 needs: release_semantic_dry permissions: packages: write @@ -44,7 +44,7 @@ jobs: release_semantic: needs: build name: Release (semantic) - uses: dargmuesli/github-actions/.github/workflows/release-semantic.yml@2.3.3 + uses: dargmuesli/github-actions/.github/workflows/release-semantic.yml@2.3.9 permissions: contents: write secrets: diff --git a/.github/workflows/release-schedule.yml b/.github/workflows/release-schedule.yml index fcfc0c98..ba1bb14e 100644 --- a/.github/workflows/release-schedule.yml +++ b/.github/workflows/release-schedule.yml @@ -8,7 +8,7 @@ on: jobs: release-schedule: name: "Release: Scheduled" - uses: dargmuesli/github-actions/.github/workflows/release-schedule.yml@2.3.3 + uses: dargmuesli/github-actions/.github/workflows/release-schedule.yml@2.3.9 secrets: PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a5be2f8..71553f7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,140 @@ +## [4.10.1](https://github.com/maevsi/sqitch/compare/4.10.0...4.10.1) (2024-12-28) + +### Bug Fixes + +* schedule release ([7dbc9bb](https://github.com/maevsi/sqitch/commit/7dbc9bbe6c23449418012ed2eb439df4400749bf)) + +## [4.10.0](https://github.com/maevsi/sqitch/compare/4.9.1...4.10.0) (2024-12-19) + +### Features + +* **event:** mark events as favourite ([#109](https://github.com/maevsi/sqitch/issues/109)) ([7b75524](https://github.com/maevsi/sqitch/commit/7b75524def9ab2575db922567e9d6db87ef3a929)) + +## [4.9.1](https://github.com/maevsi/sqitch/compare/4.9.0...4.9.1) (2024-12-18) + +### Bug Fixes + +* **role:** drop before creation ([#106](https://github.com/maevsi/sqitch/issues/106)) ([fecd16e](https://github.com/maevsi/sqitch/commit/fecd16ea860a18f0cfdaa7f0118899acf4133cce)) + +## [4.9.0](https://github.com/maevsi/sqitch/compare/4.8.0...4.9.0) (2024-12-12) + +### Features + +* **event-category-mapping:** check if invited ([4ba7dac](https://github.com/maevsi/sqitch/commit/4ba7dac31bb06937cf01829db9e58d98e9a9c723)) +* **policy:** add policy to recommendation tables ([280f47b](https://github.com/maevsi/sqitch/commit/280f47b8fd93ee871f2bd25ba2daeaf5e496b84f)) +* **recommendation:** add enum and tables needed for event recommendation ([7fb5e21](https://github.com/maevsi/sqitch/commit/7fb5e21f28fc70ea7bcbb6e764cd54cb5f0a899b)) +* **recommendation:** several modifications to db schema ([8581ad0](https://github.com/maevsi/sqitch/commit/8581ad091bea58ff33fab8a31e1c9e8fd2f2c430)) +* **revert:** add revert for recommendation tables ([cff0b7f](https://github.com/maevsi/sqitch/commit/cff0b7fdef045ac3f388553f7c4bbffb3a019c78)) +* **schema:** fix small errors and build schema ([3183da0](https://github.com/maevsi/sqitch/commit/3183da01587f4b83e646a5158cb8fba42f44a7ff)) +* **verify:** add verification for event recommendation tables ([1d6bb59](https://github.com/maevsi/sqitch/commit/1d6bb59a8cd21b4b3bc1c8a48161b3d3ff6226a3)) + +### Bug Fixes + +* **build:** commit forgotten files ([d554d0f](https://github.com/maevsi/sqitch/commit/d554d0fe33d903da55a1b14ff9b35772ebad867b)) +* **policy:** fix user check in event category mapping policy ([3dfd96a](https://github.com/maevsi/sqitch/commit/3dfd96ab1949933b6326e1762ee6461ff39eda60)) +* **schema:** remove table prefix so schema can be build ([cc5be2d](https://github.com/maevsi/sqitch/commit/cc5be2d7f0db3a251337325ec0b3aa822d0f8482)) + +## [4.8.0](https://github.com/maevsi/sqitch/compare/4.7.0...4.8.0) (2024-12-12) + +### Features + +* **event_upload:** adjust policies. ([23eb8f4](https://github.com/maevsi/sqitch/commit/23eb8f4fbc169117e928c3b75a33635d7d970ff3)) +* **event:** assign images to events ([f4822f8](https://github.com/maevsi/sqitch/commit/f4822f8252089929dea47f3585737d49b19b7c30)) + +### Bug Fixes + +* **event-upload:** work in feedback ([678ddfc](https://github.com/maevsi/sqitch/commit/678ddfce330171ab340bd112f2734d1ab304559b)) + +## [4.7.0](https://github.com/maevsi/sqitch/compare/4.6.0...4.7.0) (2024-12-12) + +### Features + +* **invitation:** column names prefixed ([2e29431](https://github.com/maevsi/sqitch/commit/2e294319a7b651deb1b472953ebb3ee770c5a5c6)) +* **invitation:** provide flattened invitations ([119b0dd](https://github.com/maevsi/sqitch/commit/119b0dd3c7337db9688a78778eb8a9484e6d3785)) + +### Bug Fixes + +* **invitation-flat:** work in feedback ([6ac75ac](https://github.com/maevsi/sqitch/commit/6ac75ac03d73bdf6daed20e3bf47668fe9a45e22)) + +## [4.6.0](https://github.com/maevsi/sqitch/compare/4.5.1...4.6.0) (2024-12-12) + +### Features + +* **invitation:** add update metadata ([f493fe4](https://github.com/maevsi/sqitch/commit/f493fe4d6c5e5127a0cad253768c864fcdfe296b)) + +## [4.5.1](https://github.com/maevsi/sqitch/compare/4.5.0...4.5.1) (2024-12-12) + +### Bug Fixes + +* **legal-term-acceptance:** omit update and delete ([555e031](https://github.com/maevsi/sqitch/commit/555e031c96e3a83ae41e3b03dd5c2de72e51780f)) +* omit update for creation timestamps ([084ad1e](https://github.com/maevsi/sqitch/commit/084ad1e7f89dfcfd890fde76f3d5baa9dffe1cd8)) + +## [4.5.0](https://github.com/maevsi/sqitch/compare/4.4.0...4.5.0) (2024-12-12) + +### Features + +* **table:** add creation timestamps ([d8d142d](https://github.com/maevsi/sqitch/commit/d8d142d8d1b12ae4890b97f60fc2daf7eb20fe96)) + +## [4.4.0](https://github.com/maevsi/sqitch/compare/4.3.1...4.4.0) (2024-12-12) + +### Features + +* add language enumeration ([76a1465](https://github.com/maevsi/sqitch/commit/76a1465f219c4c0171aafcac1bbbac16580d9691)) +* **contact:** add language ([669570f](https://github.com/maevsi/sqitch/commit/669570f6322aa8ad971990b2de9fcf8afdf14007)) +* **contact:** add nickname ([8b7169a](https://github.com/maevsi/sqitch/commit/8b7169a856b5e81ebb0676ac7de6ce512a83d548)) +* **contact:** add timezone ([02da0f9](https://github.com/maevsi/sqitch/commit/02da0f9cdb644ef78c5c6a4b354d2bd968904337)) + +## [4.3.1](https://github.com/maevsi/sqitch/compare/4.3.0...4.3.1) (2024-12-06) + +### Bug Fixes + +* **account:** enable row level security for social networks ([5606344](https://github.com/maevsi/sqitch/commit/5606344016974dd223ece949fb11d0d4b02400de)) + +## [4.3.0](https://github.com/maevsi/sqitch/compare/4.2.0...4.3.0) (2024-12-06) + +### Features + +* **account:** Add ability to store an account's preferred event sizes ([5f47988](https://github.com/maevsi/sqitch/commit/5f47988bc0ebedf2caa3a38399adc4f4de6c5b38)) +* **event:** Add event sizes ([e3b389b](https://github.com/maevsi/sqitch/commit/e3b389bb302b16a208a1dddedc35f1b909175af6)) +* **event:** remove size function ([9338623](https://github.com/maevsi/sqitch/commit/93386233fd89a5c1fd7a2cfec4cce6c8a30be935)) + +## [4.2.0](https://github.com/maevsi/sqitch/compare/4.1.1...4.2.0) (2024-12-06) + +### Features + +* **account:** add social links ([b23fa1d](https://github.com/maevsi/sqitch/commit/b23fa1d6608275eadef48c33202bf33ae9b92411)) +* **social-network:** rework ([605cd77](https://github.com/maevsi/sqitch/commit/605cd773d156cfe4d24764d88b3ee294fce6bfbc)) + +## [4.1.1](https://github.com/maevsi/sqitch/compare/4.1.0...4.1.1) (2024-12-05) + +### Bug Fixes + +* **account:** allow empty birth date ([d308c21](https://github.com/maevsi/sqitch/commit/d308c21bda037f111c275df3c900b86e7a289d26)) + +## [4.1.0](https://github.com/maevsi/sqitch/compare/4.0.5...4.1.0) (2024-12-02) + +### Features + +* **account:** column day_of_birth added ([71cc5e4](https://github.com/maevsi/sqitch/commit/71cc5e46105e70205492d782207750805f1bc184)) + +## [4.0.5](https://github.com/maevsi/sqitch/compare/4.0.4...4.0.5) (2024-11-30) + +### Bug Fixes + +* schedule release ([432f826](https://github.com/maevsi/sqitch/commit/432f826cced7129907548418635f207ff1d06b24)) + +## [4.0.4](https://github.com/maevsi/sqitch/compare/4.0.3...4.0.4) (2024-11-16) + +### Bug Fixes + +* schedule release ([1f54ae2](https://github.com/maevsi/sqitch/commit/1f54ae20aa31fa3f322eca46db74194482582649)) + +## [4.0.3](https://github.com/maevsi/sqitch/compare/4.0.2...4.0.3) (2024-11-09) + +### Bug Fixes + +* schedule release ([2f3dc5e](https://github.com/maevsi/sqitch/commit/2f3dc5ecd5b11657fb99dc94f364b7d11950904d)) + ## [4.0.2](https://github.com/maevsi/sqitch/compare/4.0.1...4.0.2) (2024-10-26) ### Bug Fixes diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..c506ef3b --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +contact+code-of-conduct@maev.si. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..c74751df --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,97 @@ +# Contributing to Our Project + +First off, thank you for considering contributing to our project! 🎉 We’re excited to have you on board and appreciate the effort you're putting into making our project better. Whether you’re a seasoned developer or a newbie, we believe every contribution counts, and this guide will help you get started. + +## Getting Started + +We putting continuous effort into making the contribution process as simple as possible. Please follow the steps below, and if you ever get stuck, don’t hesitate to ask questions—we're here to help! + +### 1. Fork and Clone the Repository + +Start by forking the repository to your GitHub account, and then clone it to your local machine using [Git](https://git-scm.com/): + +``` +git clone https://github.com/maevsi/sqitch.git +cd maevsi/sqitch +``` + +### 2. Install Dependencies + +After cloning the repository, make sure you install all the required dependencies using [pnpm](https://pnpm.io/): + +``` +pnpm install +``` + +### 3. Start the Schema Explorer + + + +Head over to [maevsi/maevsi](https://github.com/maevsi/maevsi) to see how to start the full project. Then, you should be able to access the GraphiQL interface at [https://postgraphile.localhost/graphiql](https://postgraphile.localhost/graphiql). This is where you can check that all intended queries and mutations are working as expected. + +Please make sure that the queries and mutations listed on the page align with the expected functionality of the project. + +### 4. Update Schema Artifacts + +Before submitting a pull request, it's important to update the schema artifacts to ensure consistency. We have a script to make this process easier. Run the following command: + +``` +test/schema/schema-update.sh +``` + +This script will regenerate the necessary schema files and update other artifacts as needed. Make sure to include these changes in your pull request. + +### 5. Follow Semantic Versioning + +We follow [Semantic Versioning](https://semver.org/) in this project. This means: + +- **Patch versions** (x.x.1) are for small fixes that don’t affect the API. +- **Minor versions** (x.1.x) are for backward-compatible functionality additions. +- **Major versions** (1.x.x) are for changes that break backward compatibility. + +When submitting changes, please ensure your updates and commit messages are aligned with this versioning strategy. + +## Contribution Workflow + +### 1. Branching + +Create a new branch for your work. This keeps your work isolated and makes it easier for others to review. + +``` +git checkout -b feature/new-feature +``` + +### 2. Commit Messages + +Write clear and concise commit messages that explain the reasoning behind your changes. For example: + +- `feat(event)!: remove start time` +- `feat(event): add ticketing` +- `fix(account): correct username length constraint` +- `docs: add contribution guide` + + +### 3. Pull Requests + +When you’re ready to submit your changes, push your branch and open a pull request. In your PR description: + +- **Explain the purpose of your changes**: What problem does this solve? Why is this needed? +- **Reference relevant issues**: Link to any GitHub issues this PR addresses. + +### 4. Code Reviews + +Once your pull request is submitted, someone from the team will review your changes. Be open to feedback! Code reviews are meant to ensure high-quality code and are part of the collaborative development process. + +## New to Open Source? + +No worries! We’re happy to guide you through the process. Check out [GitHub's Guide to Contributing](https://docs.github.com/en/get-started/quickstart/contributing-to-projects) to get started with open-source contributions. + +Feel free to open a draft pull request if you're unsure about anything or if you'd like some early feedback! + +## Code of Conduct + +We expect all contributors to adhere to our [Code of Conduct](CODE_OF_CONDUCT.md). Please read it before starting any contribution. We aim to foster a welcoming and inclusive community, and we appreciate your respect for fellow contributors. + +--- + +Thank you again for your interest in contributing! Let’s build something amazing together 🚀 diff --git a/Dockerfile b/Dockerfile index 1e482806..31f298f3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,29 @@ +# syntax=docker/dockerfile:1 +# check=skip=SecretsUsedInArgOrEnv + ############################## -FROM sqitch/sqitch:v1.4.1.2 AS development +FROM sqitch/sqitch:v1.4.1.3 AS prepare WORKDIR /srv/app + +############################## +FROM prepare AS development + VOLUME /srv/app -ENTRYPOINT ["/srv/app/docker-entrypoint.sh"] +ENTRYPOINT ["docker-entrypoint.sh"] CMD ["sqitch", "--chdir", "src", "deploy", "&&", "sleep", "infinity"] ########################### -FROM postgres:17.0 AS build +FROM prepare AS build + +COPY ./src ./ + + +########################### +FROM postgres:17.2 AS test-build ENV POSTGRES_DB=maevsi ENV POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password @@ -38,26 +51,30 @@ RUN export SQITCH_TARGET="$(cat SQITCH_TARGET.env)" \ && pg_dump -s -h localhost -U postgres -p 5432 maevsi | sed -e '/^-- Dumped/d' > schema.sql \ && sqitch revert -t db:pg://postgres:postgres@/maevsi -############################## -FROM alpine:3.20.3 AS validate -WORKDIR /srv/app +############################## +FROM test-build AS test -COPY ./schema ./ -COPY --from=build /srv/app ./ +COPY ./test/schema/schema.definition.sql ./ RUN diff schema.definition.sql schema.sql ############################## -FROM sqitch/sqitch:v1.4.1.2 AS production +FROM prepare AS collect -ENV ENV=production +COPY --from=test /srv/app/schema.sql /dev/null +COPY --from=build /srv/app ./ -WORKDIR /srv/app + +############################## +FROM collect AS production + +# used in docker entrypoint +ENV ENV=production COPY ./docker-entrypoint.sh /usr/local/bin/ -COPY --from=validate /srv/app ./ +COPY --from=collect /srv/app ./ ENTRYPOINT ["docker-entrypoint.sh"] CMD ["sqitch", "deploy", "&&", "sleep", "infinity"] diff --git a/README.md b/README.md index 8862a933..0f23f9aa 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ For example, run `./sqitch deploy` to fill the database with structure like tabl In case you want to be able to simple call `sqitch deploy` without `./` instead, add an `alias sqitch="./sqitch"` to your shell configuration (`~/.bashrc`, `~/.zshrc`, ...). +The `test` directory contains the `data.patch` file that can be applied by running `git apply --3way data.patch` to add basic test data to your working directory. + ## Database Diagram This diagram shows the structure of maevsi's database. diff --git a/package.json b/package.json index 2e6d2a7f..d3ac50bd 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,19 @@ { "name": "@maevsi/sqitch", - "version": "4.0.2", + "version": "4.10.1", "private": true, "engines": { "node": "22" }, - "packageManager": "pnpm@9.12.3", + "packageManager": "pnpm@9.15.1", "scripts": { "prepare": "husky" }, "devDependencies": { - "@commitlint/cli": "19.5.0", - "@commitlint/config-conventional": "19.5.0", + "@commitlint/cli": "19.6.1", + "@commitlint/config-conventional": "19.6.0", "conventional-changelog-conventionalcommits": "8.0.0", - "husky": "9.1.6" + "husky": "9.1.7" }, "type": "module" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 438c95b0..bd148290 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,35 +9,35 @@ importers: .: devDependencies: '@commitlint/cli': - specifier: 19.5.0 - version: 19.5.0(@types/node@22.8.1)(typescript@5.6.3) + specifier: 19.6.1 + version: 19.6.1(@types/node@22.10.2)(typescript@5.7.2) '@commitlint/config-conventional': - specifier: 19.5.0 - version: 19.5.0 + specifier: 19.6.0 + version: 19.6.0 conventional-changelog-conventionalcommits: specifier: 8.0.0 version: 8.0.0 husky: - specifier: 9.1.6 - version: 9.1.6 + specifier: 9.1.7 + version: 9.1.7 packages: - '@babel/code-frame@7.26.0': - resolution: {integrity: sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==} + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} '@babel/helper-validator-identifier@7.25.9': resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@commitlint/cli@19.5.0': - resolution: {integrity: sha512-gaGqSliGwB86MDmAAKAtV9SV1SHdmN8pnGq4EJU4+hLisQ7IFfx4jvU4s+pk6tl0+9bv6yT+CaZkufOinkSJIQ==} + '@commitlint/cli@19.6.1': + resolution: {integrity: sha512-8hcyA6ZoHwWXC76BoC8qVOSr8xHy00LZhZpauiD0iO0VYbVhMnED0da85lTfIULxl7Lj4c6vZgF0Wu/ed1+jlQ==} engines: {node: '>=v18'} hasBin: true - '@commitlint/config-conventional@19.5.0': - resolution: {integrity: sha512-OBhdtJyHNPryZKg0fFpZNOBM1ZDbntMvqMuSmpfyP86XSfwzGw4CaoYRG4RutUPg0BTK07VMRIkNJT6wi2zthg==} + '@commitlint/config-conventional@19.6.0': + resolution: {integrity: sha512-DJT40iMnTYtBtUfw9ApbsLZFke1zKh6llITVJ+x9mtpHD08gsNXaIRqHTmwTZL3dNX5+WoyK7pCN/5zswvkBCQ==} engines: {node: '>=v18'} '@commitlint/config-validator@19.5.0': @@ -56,16 +56,16 @@ packages: resolution: {integrity: sha512-yNy088miE52stCI3dhG/vvxFo9e4jFkU1Mj3xECfzp/bIS/JUay4491huAlVcffOoMK1cd296q0W92NlER6r3A==} engines: {node: '>=v18'} - '@commitlint/is-ignored@19.5.0': - resolution: {integrity: sha512-0XQ7Llsf9iL/ANtwyZ6G0NGp5Y3EQ8eDQSxv/SRcfJ0awlBY4tHFAvwWbw66FVUaWICH7iE5en+FD9TQsokZ5w==} + '@commitlint/is-ignored@19.6.0': + resolution: {integrity: sha512-Ov6iBgxJQFR9koOupDPHvcHU9keFupDgtB3lObdEZDroiG4jj1rzky60fbQozFKVYRTUdrBGICHG0YVmRuAJmw==} engines: {node: '>=v18'} - '@commitlint/lint@19.5.0': - resolution: {integrity: sha512-cAAQwJcRtiBxQWO0eprrAbOurtJz8U6MgYqLz+p9kLElirzSCc0vGMcyCaA1O7AqBuxo11l1XsY3FhOFowLAAg==} + '@commitlint/lint@19.6.0': + resolution: {integrity: sha512-LRo7zDkXtcIrpco9RnfhOKeg8PAnE3oDDoalnrVU/EVaKHYBWYL1DlRR7+3AWn0JiBqD8yKOfetVxJGdEtZ0tg==} engines: {node: '>=v18'} - '@commitlint/load@19.5.0': - resolution: {integrity: sha512-INOUhkL/qaKqwcTUvCE8iIUf5XHsEPCLY9looJ/ipzi7jtGhgmtH7OOFiNvwYgH7mA8osUWOUDV8t4E2HAi4xA==} + '@commitlint/load@19.6.1': + resolution: {integrity: sha512-kE4mRKWWNju2QpsCWt428XBvUH55OET2N4QKQ0bF85qS/XbsRGG1MiTByDNlEVpEPceMkDr46LNH95DtRwcsfA==} engines: {node: '>=v18'} '@commitlint/message@19.5.0': @@ -84,8 +84,8 @@ packages: resolution: {integrity: sha512-CU/GscZhCUsJwcKTJS9Ndh3AKGZTNFIOoQB2n8CmFnizE0VnEuJoum+COW+C1lNABEeqk6ssfc1Kkalm4bDklA==} engines: {node: '>=v18'} - '@commitlint/rules@19.5.0': - resolution: {integrity: sha512-hDW5TPyf/h1/EufSHEKSp6Hs+YVsDMHazfJ2azIk9tHPXS6UqSz1dIRs1gpqS3eMXgtkT7JH6TW4IShdqOwhAw==} + '@commitlint/rules@19.6.0': + resolution: {integrity: sha512-1f2reW7lbrI0X0ozZMesS/WZxgPa4/wi56vFuJENBmed6mWq5KsheN/nxqnl/C23ioxpPO/PL6tXpiiFy5Bhjw==} engines: {node: '>=v18'} '@commitlint/to-lines@19.5.0': @@ -100,11 +100,11 @@ packages: resolution: {integrity: sha512-DSHae2obMSMkAtTBSOulg5X7/z+rGLxcXQIkg3OmWvY6wifojge5uVMydfhUvs7yQj+V7jNmRZ2Xzl8GJyqRgg==} engines: {node: '>=v18'} - '@types/conventional-commits-parser@5.0.0': - resolution: {integrity: sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==} + '@types/conventional-commits-parser@5.0.1': + resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==} - '@types/node@22.8.1': - resolution: {integrity: sha512-k6Gi8Yyo8EtrNtkHXutUu2corfDf9su95VYVP10aGYMMROM6SAItZi0w1XszA6RtWTHSVp5OeFof37w0IEqCQg==} + '@types/node@22.10.2': + resolution: {integrity: sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==} JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} @@ -131,8 +131,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} cliui@8.0.1: @@ -166,13 +166,13 @@ packages: engines: {node: '>=16'} hasBin: true - cosmiconfig-typescript-loader@5.1.0: - resolution: {integrity: sha512-7PtBB+6FdsOvZyJtlF3hEPpACq7RQX6BVGsgC7/lfVXnKMvNCu/XY3ykreqG5w/rBNdu2z8LCIKoF3kpHHdHlA==} - engines: {node: '>=v16'} + cosmiconfig-typescript-loader@6.1.0: + resolution: {integrity: sha512-tJ1w35ZRUiM5FeTzT7DtYWAFFv37ZLqSRkGi2oeCK1gPhvaWjkAtfXvLmvE1pRfxxp9aQo6ba/Pvg1dKj05D4g==} + engines: {node: '>=v18'} peerDependencies: '@types/node': '*' - cosmiconfig: '>=8.2' - typescript: '>=4' + cosmiconfig: '>=9' + typescript: '>=5' cosmiconfig@9.0.0: resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} @@ -228,8 +228,8 @@ packages: resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} engines: {node: '>=18'} - husky@9.1.6: - resolution: {integrity: sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==} + husky@9.1.7: + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} engines: {node: '>=18'} hasBin: true @@ -259,8 +259,8 @@ packages: resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} engines: {node: '>=8'} - jiti@1.21.6: - resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + jiti@2.4.2: + resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true js-tokens@4.0.0: @@ -387,13 +387,13 @@ packages: tinyexec@0.3.1: resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} - typescript@5.6.3: - resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} + typescript@5.7.2: + resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} engines: {node: '>=14.17'} hasBin: true - undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} unicorn-magic@0.1.0: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} @@ -421,7 +421,7 @@ packages: snapshots: - '@babel/code-frame@7.26.0': + '@babel/code-frame@7.26.2': dependencies: '@babel/helper-validator-identifier': 7.25.9 js-tokens: 4.0.0 @@ -429,11 +429,11 @@ snapshots: '@babel/helper-validator-identifier@7.25.9': {} - '@commitlint/cli@19.5.0(@types/node@22.8.1)(typescript@5.6.3)': + '@commitlint/cli@19.6.1(@types/node@22.10.2)(typescript@5.7.2)': dependencies: '@commitlint/format': 19.5.0 - '@commitlint/lint': 19.5.0 - '@commitlint/load': 19.5.0(@types/node@22.8.1)(typescript@5.6.3) + '@commitlint/lint': 19.6.0 + '@commitlint/load': 19.6.1(@types/node@22.10.2)(typescript@5.7.2) '@commitlint/read': 19.5.0 '@commitlint/types': 19.5.0 tinyexec: 0.3.1 @@ -442,7 +442,7 @@ snapshots: - '@types/node' - typescript - '@commitlint/config-conventional@19.5.0': + '@commitlint/config-conventional@19.6.0': dependencies: '@commitlint/types': 19.5.0 conventional-changelog-conventionalcommits: 7.0.2 @@ -466,29 +466,29 @@ snapshots: '@commitlint/format@19.5.0': dependencies: '@commitlint/types': 19.5.0 - chalk: 5.3.0 + chalk: 5.4.1 - '@commitlint/is-ignored@19.5.0': + '@commitlint/is-ignored@19.6.0': dependencies: '@commitlint/types': 19.5.0 semver: 7.6.3 - '@commitlint/lint@19.5.0': + '@commitlint/lint@19.6.0': dependencies: - '@commitlint/is-ignored': 19.5.0 + '@commitlint/is-ignored': 19.6.0 '@commitlint/parse': 19.5.0 - '@commitlint/rules': 19.5.0 + '@commitlint/rules': 19.6.0 '@commitlint/types': 19.5.0 - '@commitlint/load@19.5.0(@types/node@22.8.1)(typescript@5.6.3)': + '@commitlint/load@19.6.1(@types/node@22.10.2)(typescript@5.7.2)': dependencies: '@commitlint/config-validator': 19.5.0 '@commitlint/execute-rule': 19.5.0 '@commitlint/resolve-extends': 19.5.0 '@commitlint/types': 19.5.0 - chalk: 5.3.0 - cosmiconfig: 9.0.0(typescript@5.6.3) - cosmiconfig-typescript-loader: 5.1.0(@types/node@22.8.1)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3) + chalk: 5.4.1 + cosmiconfig: 9.0.0(typescript@5.7.2) + cosmiconfig-typescript-loader: 6.1.0(@types/node@22.10.2)(cosmiconfig@9.0.0(typescript@5.7.2))(typescript@5.7.2) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -521,7 +521,7 @@ snapshots: lodash.mergewith: 4.6.2 resolve-from: 5.0.0 - '@commitlint/rules@19.5.0': + '@commitlint/rules@19.6.0': dependencies: '@commitlint/ensure': 19.5.0 '@commitlint/message': 19.5.0 @@ -536,16 +536,16 @@ snapshots: '@commitlint/types@19.5.0': dependencies: - '@types/conventional-commits-parser': 5.0.0 - chalk: 5.3.0 + '@types/conventional-commits-parser': 5.0.1 + chalk: 5.4.1 - '@types/conventional-commits-parser@5.0.0': + '@types/conventional-commits-parser@5.0.1': dependencies: - '@types/node': 22.8.1 + '@types/node': 22.10.2 - '@types/node@22.8.1': + '@types/node@22.10.2': dependencies: - undici-types: 6.19.8 + undici-types: 6.20.0 JSONStream@1.3.5: dependencies: @@ -571,7 +571,7 @@ snapshots: callsites@3.1.0: {} - chalk@5.3.0: {} + chalk@5.4.1: {} cliui@8.0.1: dependencies: @@ -609,21 +609,21 @@ snapshots: meow: 12.1.1 split2: 4.2.0 - cosmiconfig-typescript-loader@5.1.0(@types/node@22.8.1)(cosmiconfig@9.0.0(typescript@5.6.3))(typescript@5.6.3): + cosmiconfig-typescript-loader@6.1.0(@types/node@22.10.2)(cosmiconfig@9.0.0(typescript@5.7.2))(typescript@5.7.2): dependencies: - '@types/node': 22.8.1 - cosmiconfig: 9.0.0(typescript@5.6.3) - jiti: 1.21.6 - typescript: 5.6.3 + '@types/node': 22.10.2 + cosmiconfig: 9.0.0(typescript@5.7.2) + jiti: 2.4.2 + typescript: 5.7.2 - cosmiconfig@9.0.0(typescript@5.6.3): + cosmiconfig@9.0.0(typescript@5.7.2): dependencies: env-paths: 2.2.1 import-fresh: 3.3.0 js-yaml: 4.1.0 parse-json: 5.2.0 optionalDependencies: - typescript: 5.6.3 + typescript: 5.7.2 dargs@8.1.0: {} @@ -663,7 +663,7 @@ snapshots: dependencies: ini: 4.1.1 - husky@9.1.6: {} + husky@9.1.7: {} import-fresh@3.3.0: dependencies: @@ -684,7 +684,7 @@ snapshots: dependencies: text-extensions: 2.4.0 - jiti@1.21.6: {} + jiti@2.4.2: {} js-tokens@4.0.0: {} @@ -740,7 +740,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.26.0 + '@babel/code-frame': 7.26.2 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -777,9 +777,9 @@ snapshots: tinyexec@0.3.1: {} - typescript@5.6.3: {} + typescript@5.7.2: {} - undici-types@6.19.8: {} + undici-types@6.20.0: {} unicorn-magic@0.1.0: {} diff --git a/src/deploy/database_grafana.sql b/src/deploy/database_grafana.sql index 2f10f7ab..73955152 100644 --- a/src/deploy/database_grafana.sql +++ b/src/deploy/database_grafana.sql @@ -1,5 +1,3 @@ --- Deploy maevsi:database_grafana to pg - CREATE DATABASE grafana; COMMENT ON DATABASE grafana IS 'The observation dashboard''s database.'; diff --git a/src/deploy/enum_achievement_type.sql b/src/deploy/enum_achievement_type.sql index 87b98cd2..2b9fc8d4 100644 --- a/src/deploy/enum_achievement_type.sql +++ b/src/deploy/enum_achievement_type.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:enum_achievement_type to pg --- requires: schema_public - BEGIN; CREATE TYPE maevsi.achievement_type AS ENUM ( diff --git a/src/deploy/enum_event_size.sql b/src/deploy/enum_event_size.sql new file mode 100644 index 00000000..b3af027c --- /dev/null +++ b/src/deploy/enum_event_size.sql @@ -0,0 +1,12 @@ +BEGIN; + +CREATE TYPE maevsi.event_size AS ENUM ( + 'small', + 'medium', + 'large', + 'huge' +); + +COMMENT ON TYPE maevsi.event_size IS 'Possible event sizes: small, medium, large, huge.'; + +COMMIT; diff --git a/src/deploy/enum_event_visibility.sql b/src/deploy/enum_event_visibility.sql index 13688d52..46fdf623 100644 --- a/src/deploy/enum_event_visibility.sql +++ b/src/deploy/enum_event_visibility.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:enum_event_visibility to pg --- requires: schema_public - BEGIN; CREATE TYPE maevsi.event_visibility AS ENUM ( diff --git a/src/deploy/enum_invitation_feedback.sql b/src/deploy/enum_invitation_feedback.sql index 5263db59..dfdf76d7 100644 --- a/src/deploy/enum_invitation_feedback.sql +++ b/src/deploy/enum_invitation_feedback.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:enum_invitation_feedback to pg --- requires: schema_public - BEGIN; CREATE TYPE maevsi.invitation_feedback AS ENUM ( diff --git a/src/deploy/enum_invitation_feedback_paper.sql b/src/deploy/enum_invitation_feedback_paper.sql index c87f0ce9..64ec9c85 100644 --- a/src/deploy/enum_invitation_feedback_paper.sql +++ b/src/deploy/enum_invitation_feedback_paper.sql @@ -1,5 +1,3 @@ --- Deploy maevsi:enum_paper_invitation_feedback to pg - BEGIN; CREATE TYPE maevsi.invitation_feedback_paper AS ENUM ( diff --git a/src/deploy/enum_language.sql b/src/deploy/enum_language.sql new file mode 100644 index 00000000..56e7c109 --- /dev/null +++ b/src/deploy/enum_language.sql @@ -0,0 +1,10 @@ +BEGIN; + +CREATE TYPE maevsi.language AS ENUM ( + 'de', + 'en' +); + +COMMENT ON TYPE maevsi.language IS 'Supported ISO 639 language codes.'; + +COMMIT; diff --git a/src/deploy/enum_social_network.sql b/src/deploy/enum_social_network.sql new file mode 100644 index 00000000..5ea9d01e --- /dev/null +++ b/src/deploy/enum_social_network.sql @@ -0,0 +1,12 @@ +BEGIN; + +CREATE TYPE maevsi.social_network AS ENUM ( + 'facebook', + 'instagram', + 'tiktok', + 'x' +); + +COMMENT ON TYPE maevsi.social_network IS 'Social networks.'; + +COMMIT; diff --git a/src/deploy/extension_pgcrypto.sql b/src/deploy/extension_pgcrypto.sql index 39614f21..a2797be3 100644 --- a/src/deploy/extension_pgcrypto.sql +++ b/src/deploy/extension_pgcrypto.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:extension_pgcrypto to pg --- requires: schema_public - BEGIN; CREATE EXTENSION pgcrypto WITH SCHEMA maevsi; diff --git a/src/deploy/function_account_delete.sql b/src/deploy/function_account_delete.sql index f89f4d1f..b1ce1ba7 100644 --- a/src/deploy/function_account_delete.sql +++ b/src/deploy/function_account_delete.sql @@ -1,11 +1,3 @@ --- Deploy maevsi:function_account_delete to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: role_account --- requires: table_account_private --- requires: table_event --- requires: extension_pgcrypto - BEGIN; CREATE FUNCTION maevsi.account_delete( diff --git a/src/deploy/function_account_email_address_verification.sql b/src/deploy/function_account_email_address_verification.sql index addb9a39..a211fc2b 100644 --- a/src/deploy/function_account_email_address_verification.sql +++ b/src/deploy/function_account_email_address_verification.sql @@ -1,11 +1,3 @@ --- Deploy maevsi:function_account_email_address_verification to pg --- requires: privilege_execute_revoke --- requires: schema_private --- requires: schema_public --- requires: role_account --- requires: role_anonymous --- requires: table_account_private - BEGIN; CREATE FUNCTION maevsi.account_email_address_verification( @@ -23,7 +15,7 @@ BEGIN RAISE 'Unknown verification code!' USING ERRCODE = 'no_data_found'; END IF; - IF (_account.email_address_verification_valid_until < NOW()) THEN + IF (_account.email_address_verification_valid_until < CURRENT_TIMESTAMP) THEN RAISE 'Verification code expired!' USING ERRCODE = 'object_not_in_prerequisite_state'; END IF; diff --git a/src/deploy/function_account_password_change.sql b/src/deploy/function_account_password_change.sql index 0c7e0a4b..69a75e52 100644 --- a/src/deploy/function_account_password_change.sql +++ b/src/deploy/function_account_password_change.sql @@ -1,11 +1,3 @@ --- Deploy maevsi:function_account_password_change to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: schema_private --- requires: role_account --- requires: table_account_private --- requires: extension_pgcrypto - BEGIN; CREATE FUNCTION maevsi.account_password_change( diff --git a/src/deploy/function_account_password_reset.sql b/src/deploy/function_account_password_reset.sql index be6277cb..44b2e706 100644 --- a/src/deploy/function_account_password_reset.sql +++ b/src/deploy/function_account_password_reset.sql @@ -1,12 +1,3 @@ --- Deploy maevsi:function_account_password_reset to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: schema_private --- requires: table_account_private --- requires: extension_pgcrypto --- requires: role_anonymous --- requires: role_account - BEGIN; CREATE FUNCTION maevsi.account_password_reset( @@ -29,7 +20,7 @@ BEGIN RAISE 'Unknown reset code!' USING ERRCODE = 'no_data_found'; END IF; - IF (_account.password_reset_verification_valid_until < NOW()) THEN + IF (_account.password_reset_verification_valid_until < CURRENT_TIMESTAMP) THEN RAISE 'Reset code expired!' USING ERRCODE = 'object_not_in_prerequisite_state'; END IF; diff --git a/src/deploy/function_account_password_reset_request.sql b/src/deploy/function_account_password_reset_request.sql index 51de79ff..ce2a62b0 100644 --- a/src/deploy/function_account_password_reset_request.sql +++ b/src/deploy/function_account_password_reset_request.sql @@ -1,12 +1,3 @@ --- Deploy maevsi:function_account_password_reset_request to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: schema_private --- requires: table_account_private --- requires: table_notification --- requires: role_anonymous --- requires: role_account - BEGIN; CREATE FUNCTION maevsi.account_password_reset_request( diff --git a/src/deploy/function_account_registration.sql b/src/deploy/function_account_registration.sql index 25bc93dd..e1c19019 100644 --- a/src/deploy/function_account_registration.sql +++ b/src/deploy/function_account_registration.sql @@ -1,15 +1,3 @@ --- Deploy maevsi:function_account_registration to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: schema_private --- requires: table_account_private --- requires: table_account_public --- requires: table_contact --- requires: extension_pgcrypto --- requires: table_notification --- requires: role_anonymous --- requires: role_account - BEGIN; CREATE FUNCTION maevsi.account_registration( @@ -23,24 +11,24 @@ DECLARE _new_account_public maevsi.account; _new_account_notify RECORD; BEGIN - IF (char_length($3) < 8) THEN + IF (char_length(account_registration.password) < 8) THEN RAISE 'Password too short!' USING ERRCODE = 'invalid_parameter_value'; END IF; - IF (EXISTS (SELECT 1 FROM maevsi.account WHERE account.username = $1)) THEN + IF (EXISTS (SELECT 1 FROM maevsi.account WHERE account.username = account_registration.username)) THEN RAISE 'An account with this username already exists!' USING ERRCODE = 'unique_violation'; END IF; - IF (EXISTS (SELECT 1 FROM maevsi_private.account WHERE account.email_address = $2)) THEN + IF (EXISTS (SELECT 1 FROM maevsi_private.account WHERE account.email_address = account_registration.email_address)) THEN RAISE 'An account with this email address already exists!' USING ERRCODE = 'unique_violation'; END IF; INSERT INTO maevsi_private.account(email_address, password_hash, last_activity) VALUES - ($2, maevsi.crypt($3, maevsi.gen_salt('bf')), NOW()) + (account_registration.email_address, maevsi.crypt(account_registration.password, maevsi.gen_salt('bf')), CURRENT_TIMESTAMP) RETURNING * INTO _new_account_private; INSERT INTO maevsi.account(id, username) VALUES - (_new_account_private.id, $1) + (_new_account_private.id, account_registration.username) RETURNING * INTO _new_account_public; SELECT @@ -56,7 +44,7 @@ BEGIN 'account_registration', jsonb_pretty(jsonb_build_object( 'account', row_to_json(_new_account_notify), - 'template', jsonb_build_object('language', $4) + 'template', jsonb_build_object('language', account_registration.language) )) ); diff --git a/src/deploy/function_account_registration_refresh.sql b/src/deploy/function_account_registration_refresh.sql index abd20e97..fe37ea80 100644 --- a/src/deploy/function_account_registration_refresh.sql +++ b/src/deploy/function_account_registration_refresh.sql @@ -1,11 +1,3 @@ --- Deploy maevsi:function_account_registration_refresh to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: schema_private --- requires: table_account_private --- requires: table_notification --- requires: role_anonymous - BEGIN; CREATE FUNCTION maevsi.account_registration_refresh( diff --git a/src/deploy/function_account_upload_quota_bytes.sql b/src/deploy/function_account_upload_quota_bytes.sql index b817a5af..a001ff9c 100644 --- a/src/deploy/function_account_upload_quota_bytes.sql +++ b/src/deploy/function_account_upload_quota_bytes.sql @@ -1,10 +1,3 @@ --- Deploy maevsi:function_account_upload_quota_bytes to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: schema_private --- requires: table_account_private --- requires: role_account - BEGIN; CREATE FUNCTION maevsi.account_upload_quota_bytes() RETURNS BIGINT AS $$ diff --git a/src/deploy/function_achievement_unlock.sql b/src/deploy/function_achievement_unlock.sql index 959dd25f..773d87ba 100644 --- a/src/deploy/function_achievement_unlock.sql +++ b/src/deploy/function_achievement_unlock.sql @@ -1,12 +1,3 @@ --- Deploy maevsi:function_achievement_unlock to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: enum_achievement_type --- requires: schema_private --- requires: table_achievement_code --- requires: table_achievement --- requires: role_account - BEGIN; CREATE FUNCTION maevsi.achievement_unlock( @@ -18,7 +9,7 @@ DECLARE _achievement maevsi.achievement_type; _achievement_id UUID; BEGIN - _account_id := NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID; + _account_id := maevsi.invoker_account_id(); SELECT achievement FROM maevsi_private.achievement_code diff --git a/src/deploy/function_authenticate.sql b/src/deploy/function_authenticate.sql index 1916b76c..9d9e15df 100644 --- a/src/deploy/function_authenticate.sql +++ b/src/deploy/function_authenticate.sql @@ -1,12 +1,3 @@ --- Deploy maevsi:function_authenticate to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: role_account --- requires: role_anonymous --- requires: type_jwt --- requires: table_account_private --- requires: table_jwt - BEGIN; CREATE FUNCTION maevsi.authenticate( @@ -16,7 +7,7 @@ CREATE FUNCTION maevsi.authenticate( DECLARE _account_id UUID; _jwt_id UUID := gen_random_uuid(); - _jwt_exp BIGINT := EXTRACT(EPOCH FROM ((SELECT date_trunc('second', NOW()::TIMESTAMP)) + COALESCE(current_setting('maevsi.jwt_expiry_duration', true), '1 day')::INTERVAL)); + _jwt_exp BIGINT := EXTRACT(EPOCH FROM ((SELECT date_trunc('second', CURRENT_TIMESTAMP::TIMESTAMP)) + COALESCE(current_setting('maevsi.jwt_expiry_duration', true), '1 day')::INTERVAL)); _jwt maevsi.jwt; BEGIN IF ($1 = '' AND $2 = '') THEN diff --git a/src/deploy/function_event_delete.sql b/src/deploy/function_event_delete.sql index 3fd46dd9..cc3a9afd 100644 --- a/src/deploy/function_event_delete.sql +++ b/src/deploy/function_event_delete.sql @@ -1,11 +1,3 @@ --- Deploy maevsi:function_event_delete to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: role_account --- requires: table_account_private --- requires: table_event --- requires: extension_pgcrypto - BEGIN; CREATE FUNCTION maevsi.event_delete( diff --git a/src/deploy/function_event_invitee_count_maximum.sql b/src/deploy/function_event_invitee_count_maximum.sql index 0ffdc386..387fbb48 100644 --- a/src/deploy/function_event_invitee_count_maximum.sql +++ b/src/deploy/function_event_invitee_count_maximum.sql @@ -1,13 +1,3 @@ --- Deploy maevsi:function_event_invitee_count_maximum to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: table_event --- requires: function_invitee_count --- requires: schema_private --- requires: function_events_invited --- requires: role_account --- requires: role_anonymous - BEGIN; CREATE FUNCTION maevsi.event_invitee_count_maximum( @@ -30,9 +20,9 @@ BEGIN ) ) OR ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - "event".author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + "event".author_account_id = maevsi.invoker_account_id() ) OR "event".id IN (SELECT maevsi_private.events_invited()) ) diff --git a/src/deploy/function_event_is_existing.sql b/src/deploy/function_event_is_existing.sql index 7d02302b..bfcc7748 100644 --- a/src/deploy/function_event_is_existing.sql +++ b/src/deploy/function_event_is_existing.sql @@ -1,10 +1,3 @@ --- Deploy maevsi:function_event_is_existing to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: table_event --- requires: role_account --- requires: role_anonymous - BEGIN; CREATE FUNCTION maevsi.event_is_existing( diff --git a/src/deploy/function_event_unlock.sql b/src/deploy/function_event_unlock.sql index 1e66df17..8d4fe6a2 100644 --- a/src/deploy/function_event_unlock.sql +++ b/src/deploy/function_event_unlock.sql @@ -1,13 +1,3 @@ --- Deploy maevsi:function_event_unlock to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: table_invitation --- requires: table_event --- requires: type_event_unlock_response --- requires: function_invitation_claims_to_array --- requires: type_jwt --- requires: table_jwt - BEGIN; CREATE FUNCTION maevsi.event_unlock( @@ -23,7 +13,7 @@ BEGIN _jwt_id := current_setting('jwt.claims.id', true)::UUID; _jwt := ( _jwt_id, - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID, -- prevent empty string cast to UUID + maevsi.invoker_account_id(), -- prevent empty string cast to UUID current_setting('jwt.claims.account_username', true)::TEXT, current_setting('jwt.claims.exp', true)::BIGINT, (SELECT ARRAY(SELECT DISTINCT UNNEST(maevsi.invitation_claim_array() || $1) ORDER BY 1)), diff --git a/src/deploy/function_events_invited.sql b/src/deploy/function_events_invited.sql index d84396ee..f23a9c83 100644 --- a/src/deploy/function_events_invited.sql +++ b/src/deploy/function_events_invited.sql @@ -1,13 +1,3 @@ --- Deploy maevsi:function_events_invited to pg --- requires: privilege_execute_revoke --- requires: schema_private --- requires: schema_public --- requires: table_invitation --- requires: table_contact --- requires: table_account_block --- requires: role_account --- requires: role_anonymous - BEGIN; CREATE FUNCTION maevsi_private.events_invited() @@ -16,7 +6,7 @@ AS $$ DECLARE jwt_account_id UUID; BEGIN - jwt_account_id := NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID; + jwt_account_id := maevsi.invoker_account_id(); RETURN QUERY SELECT i.event_id FROM maevsi.invitation i diff --git a/src/deploy/function_events_organized.sql b/src/deploy/function_events_organized.sql index 39860764..00dd883c 100644 --- a/src/deploy/function_events_organized.sql +++ b/src/deploy/function_events_organized.sql @@ -1,10 +1,3 @@ --- Deploy maevsi:function_events_organized to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: table_event --- requires: role_account --- requires: role_anonymous - BEGIN; CREATE FUNCTION maevsi.events_organized() @@ -12,7 +5,7 @@ RETURNS TABLE (event_id UUID) AS $$ DECLARE account_id UUID; BEGIN - account_id := NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID; + account_id := maevsi.invoker_account_id(); RETURN QUERY SELECT id FROM maevsi.event diff --git a/src/deploy/function_invitation_claim_array.sql b/src/deploy/function_invitation_claim_array.sql index 7d67781d..577074ab 100644 --- a/src/deploy/function_invitation_claim_array.sql +++ b/src/deploy/function_invitation_claim_array.sql @@ -1,12 +1,3 @@ --- Deploy maevsi:function_invitation_claim_array to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: table_invitation --- requires: table_contact --- requires: table_account_block --- requires: role_account --- requires: role_anonymous - BEGIN; CREATE FUNCTION maevsi.invitation_claim_array() diff --git a/src/deploy/function_invitation_contact_ids.sql b/src/deploy/function_invitation_contact_ids.sql index a24c8d47..f36667cb 100644 --- a/src/deploy/function_invitation_contact_ids.sql +++ b/src/deploy/function_invitation_contact_ids.sql @@ -1,14 +1,3 @@ --- Deploy maevsi:function_invitation_contact_ids to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: table_invitation --- requires: table_contact --- requires: table_account_block --- requires: function_invitation_claim_array --- requires: function_events_organized --- requires: role_account --- requires: role_anonymous - BEGIN; CREATE FUNCTION maevsi.invitation_contact_ids() diff --git a/src/deploy/function_invite.sql b/src/deploy/function_invite.sql index c65c3f42..c29ceb0b 100644 --- a/src/deploy/function_invite.sql +++ b/src/deploy/function_invite.sql @@ -1,16 +1,3 @@ --- Deploy maevsi:function_account_delete to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: table_invitation --- requires: function_events_organized --- requires: table_event --- requires: table_contact --- requires: schema_private --- requires: table_account_private --- requires: table_profile_picture --- requires: table_notification --- requires: role_account - BEGIN; CREATE FUNCTION maevsi.invite( diff --git a/src/deploy/function_invitee_count.sql b/src/deploy/function_invitee_count.sql index 655b838a..e6f67195 100644 --- a/src/deploy/function_invitee_count.sql +++ b/src/deploy/function_invitee_count.sql @@ -1,10 +1,3 @@ --- Deploy maevsi:function_invitee_count to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: table_invitation --- requires: role_account --- requires: role_anonymous - BEGIN; CREATE FUNCTION maevsi.invitee_count(event_id UUID) diff --git a/src/deploy/function_invoker_account_id.sql b/src/deploy/function_invoker_account_id.sql new file mode 100644 index 00000000..c2ef0658 --- /dev/null +++ b/src/deploy/function_invoker_account_id.sql @@ -0,0 +1,13 @@ +BEGIN; + +CREATE FUNCTION maevsi.invoker_account_id() RETURNS UUID AS $$ +BEGIN + RETURN NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID; +END; +$$ LANGUAGE PLPGSQL STRICT SECURITY DEFINER STABLE; + +COMMENT ON FUNCTION maevsi.invoker_account_id() IS 'Returns the session''s account id.'; + +GRANT EXECUTE ON FUNCTION maevsi.invoker_account_id() TO maevsi_account, maevsi_anonymous; + +COMMIT; diff --git a/src/deploy/function_jwt_refresh.sql b/src/deploy/function_jwt_refresh.sql index c0f9fad5..824f642d 100644 --- a/src/deploy/function_jwt_refresh.sql +++ b/src/deploy/function_jwt_refresh.sql @@ -1,16 +1,10 @@ --- Deploy maevsi:function_jwt_refresh to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: type_jwt --- requires: table_jwt - BEGIN; CREATE FUNCTION maevsi.jwt_refresh( jwt_id UUID ) RETURNS maevsi.jwt AS $$ DECLARE - _epoch_now BIGINT := EXTRACT(EPOCH FROM (SELECT date_trunc('second', NOW()::TIMESTAMP))); + _epoch_now BIGINT := EXTRACT(EPOCH FROM (SELECT date_trunc('second', CURRENT_TIMESTAMP::TIMESTAMP))); _jwt maevsi.jwt; BEGIN SELECT (token).id, (token).account_id, (token).account_username, (token)."exp", (token).invitations, (token).role INTO _jwt @@ -22,7 +16,7 @@ BEGIN RETURN NULL; ELSE UPDATE maevsi_private.jwt - SET token.exp = EXTRACT(EPOCH FROM ((SELECT date_trunc('second', NOW()::TIMESTAMP)) + COALESCE(current_setting('maevsi.jwt_expiry_duration', true), '1 day')::INTERVAL)) + SET token.exp = EXTRACT(EPOCH FROM ((SELECT date_trunc('second', CURRENT_TIMESTAMP::TIMESTAMP)) + COALESCE(current_setting('maevsi.jwt_expiry_duration', true), '1 day')::INTERVAL)) WHERE id = $1; UPDATE maevsi_private.account diff --git a/src/deploy/function_notification_acknowledge.sql b/src/deploy/function_notification_acknowledge.sql index 6b4e1305..388f3421 100644 --- a/src/deploy/function_notification_acknowledge.sql +++ b/src/deploy/function_notification_acknowledge.sql @@ -1,10 +1,3 @@ --- Deploy maevsi:function_notification_acknowledge to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: schema_private --- requires: table_notification --- requires: role_anonymous - BEGIN; CREATE FUNCTION maevsi.notification_acknowledge( diff --git a/src/deploy/function_profile_picture_set.sql b/src/deploy/function_profile_picture_set.sql index d79b3d46..69366bb7 100644 --- a/src/deploy/function_profile_picture_set.sql +++ b/src/deploy/function_profile_picture_set.sql @@ -1,9 +1,3 @@ --- Deploy maevsi:function_profile_picture_set to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: role_account --- requires: table_profile_picture - BEGIN; CREATE FUNCTION maevsi.profile_picture_set( diff --git a/src/deploy/function_upload_create.sql b/src/deploy/function_upload_create.sql index 1321d2d7..17f0ca92 100644 --- a/src/deploy/function_upload_create.sql +++ b/src/deploy/function_upload_create.sql @@ -1,11 +1,3 @@ --- Deploy maevsi:function_upload_create to pg --- requires: privilege_execute_revoke --- requires: schema_public --- requires: schema_private --- requires: role_account --- requires: table_upload --- requires: table_account_private - BEGIN; CREATE FUNCTION maevsi.upload_create( diff --git a/src/deploy/index_event_author_username.sql b/src/deploy/index_event_author_username.sql index 37771c57..388ca32a 100644 --- a/src/deploy/index_event_author_username.sql +++ b/src/deploy/index_event_author_username.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:index_event_author_account_id to pg --- requires: table_event - BEGIN; CREATE INDEX idx_event_author_account_id ON maevsi.event (author_account_id); diff --git a/src/deploy/index_event_group_author_username.sql b/src/deploy/index_event_group_author_username.sql index b8379765..eaf1dfbf 100644 --- a/src/deploy/index_event_group_author_username.sql +++ b/src/deploy/index_event_group_author_username.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:index_event_group_author_account_id to pg --- requires: table_event_group - BEGIN; CREATE INDEX idx_event_group_author_account_id ON maevsi.event_group (author_account_id); diff --git a/src/deploy/index_event_grouping_event_group_id.sql b/src/deploy/index_event_grouping_event_group_id.sql index a19a9c7e..4cd5b927 100644 --- a/src/deploy/index_event_grouping_event_group_id.sql +++ b/src/deploy/index_event_grouping_event_group_id.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:index_event_grouping_event_group_id to pg --- requires: table_event_grouping - BEGIN; CREATE INDEX idx_event_grouping_event_group_id ON maevsi.event_grouping (event_group_id); diff --git a/src/deploy/index_event_grouping_event_id.sql b/src/deploy/index_event_grouping_event_id.sql index 562e814c..253b12e5 100644 --- a/src/deploy/index_event_grouping_event_id.sql +++ b/src/deploy/index_event_grouping_event_id.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:index_event_grouping_event_id to pg --- requires: table_event_grouping - BEGIN; CREATE INDEX idx_event_grouping_event_id ON maevsi.event_grouping (event_id); diff --git a/src/deploy/index_invitation_contact_id.sql b/src/deploy/index_invitation_contact_id.sql index 16be1d2e..8b035f99 100644 --- a/src/deploy/index_invitation_contact_id.sql +++ b/src/deploy/index_invitation_contact_id.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:index_invitation_contact_id to pg --- requires: table_invitation - BEGIN; CREATE INDEX idx_invitation_contact_id ON maevsi.invitation (contact_id); diff --git a/src/deploy/index_invitation_event_id.sql b/src/deploy/index_invitation_event_id.sql index e1bb090d..85faa012 100644 --- a/src/deploy/index_invitation_event_id.sql +++ b/src/deploy/index_invitation_event_id.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:index_invitation_event_id to pg --- requires: table_invitation - BEGIN; CREATE INDEX idx_invitation_event_id ON maevsi.invitation (event_id); diff --git a/src/deploy/privilege_execute_revoke.sql b/src/deploy/privilege_execute_revoke.sql index 86f6040a..21ba09b5 100644 --- a/src/deploy/privilege_execute_revoke.sql +++ b/src/deploy/privilege_execute_revoke.sql @@ -1,5 +1,3 @@ --- Deploy maevsi:privilege_execute_revoke to pg - BEGIN; ALTER DEFAULT PRIVILEGES REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC; diff --git a/src/deploy/role_account.sql b/src/deploy/role_account.sql index 0765e03b..49adaa71 100644 --- a/src/deploy/role_account.sql +++ b/src/deploy/role_account.sql @@ -1,8 +1,6 @@ --- Deploy maevsi:role_account to pg --- requires: role_postgraphile - BEGIN; +DROP ROLE IF EXISTS maevsi_account; CREATE ROLE maevsi_account; GRANT maevsi_account to maevsi_postgraphile; diff --git a/src/deploy/role_anonymous.sql b/src/deploy/role_anonymous.sql index 9ab9c9e9..f7daa6c6 100644 --- a/src/deploy/role_anonymous.sql +++ b/src/deploy/role_anonymous.sql @@ -1,8 +1,6 @@ --- Deploy maevsi:role_anonymous to pg --- requires: role_postgraphile - BEGIN; +DROP ROLE IF EXISTS maevsi_anonymous; CREATE ROLE maevsi_anonymous; GRANT maevsi_anonymous to maevsi_postgraphile; diff --git a/src/deploy/role_grafana.sql b/src/deploy/role_grafana.sql index b61e525c..fd773cf0 100644 --- a/src/deploy/role_grafana.sql +++ b/src/deploy/role_grafana.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:role_grafana to pg --- requires: database_grafana - \connect grafana BEGIN; @@ -8,6 +5,7 @@ BEGIN; \set role_grafana_password `cat /run/secrets/postgres_role_grafana_password` \set role_grafana_username `cat /run/secrets/postgres_role_grafana_username` +DROP ROLE IF EXISTS :role_grafana_username; CREATE ROLE :role_grafana_username LOGIN PASSWORD :'role_grafana_password'; GRANT ALL PRIVILEGES ON DATABASE grafana TO :role_grafana_username; diff --git a/src/deploy/role_postgraphile.sql b/src/deploy/role_postgraphile.sql index 10a83e9d..6b4223b3 100644 --- a/src/deploy/role_postgraphile.sql +++ b/src/deploy/role_postgraphile.sql @@ -1,8 +1,8 @@ --- Deploy maevsi:role_postgraphile to pg - BEGIN; \set role_maevsi_postgraphile_password `cat /run/secrets/postgres_role_maevsi-postgraphile_password` + +DROP ROLE IF EXISTS maevsi_postgraphile; CREATE ROLE maevsi_postgraphile LOGIN PASSWORD :'role_maevsi_postgraphile_password'; COMMIT; diff --git a/src/deploy/role_tusd.sql b/src/deploy/role_tusd.sql index 033a084f..a3f57012 100644 --- a/src/deploy/role_tusd.sql +++ b/src/deploy/role_tusd.sql @@ -1,9 +1,8 @@ --- Deploy maevsi:role_tusd to pg --- requires: role_postgraphile - BEGIN; \set role_maevsi_tusd_password `cat /run/secrets/postgres_role_maevsi-tusd_password` + +DROP ROLE IF EXISTS maevsi_tusd; CREATE ROLE maevsi_tusd LOGIN PASSWORD :'role_maevsi_tusd_password'; GRANT maevsi_tusd to maevsi_postgraphile; diff --git a/src/deploy/schema_private.sql b/src/deploy/schema_private.sql index c80dbbb1..96960f64 100644 --- a/src/deploy/schema_private.sql +++ b/src/deploy/schema_private.sql @@ -1,5 +1,3 @@ --- Deploy maevsi:schema_private to pg - BEGIN; CREATE SCHEMA maevsi_private; diff --git a/src/deploy/schema_public.sql b/src/deploy/schema_public.sql index 66a56965..abc2f95b 100644 --- a/src/deploy/schema_public.sql +++ b/src/deploy/schema_public.sql @@ -1,8 +1,3 @@ --- Deploy maevsi:schema_public to pg --- requires: role_anonymous --- requires: role_account --- requires: role_tusd - BEGIN; CREATE SCHEMA maevsi; diff --git a/src/deploy/table_account_block.sql b/src/deploy/table_account_block.sql index 2bba97f2..4d932bea 100644 --- a/src/deploy/table_account_block.sql +++ b/src/deploy/table_account_block.sql @@ -1,7 +1,3 @@ --- Deploy maevsi:table_account_block to pg --- requires: schema_public --- requires: table_account_public - BEGIN; CREATE TABLE maevsi.account_block ( diff --git a/src/deploy/table_account_block_policy.sql b/src/deploy/table_account_block_policy.sql index 19f7212a..49df96a9 100644 --- a/src/deploy/table_account_block_policy.sql +++ b/src/deploy/table_account_block_policy.sql @@ -1,8 +1,3 @@ --- Deploy maevsi:table_account_block_policy to pg --- requires: schema_public --- requires: table_account_block --- requires: role_account - BEGIN; GRANT INSERT, SELECT ON TABLE maevsi.account_block TO maevsi_account; diff --git a/src/deploy/table_account_interest.sql b/src/deploy/table_account_interest.sql new file mode 100644 index 00000000..2eec0a52 --- /dev/null +++ b/src/deploy/table_account_interest.sql @@ -0,0 +1,14 @@ +BEGIN; + +CREATE TABLE maevsi.account_interest ( + account_id UUID NOT NULL REFERENCES maevsi.account(id) ON DELETE CASCADE, + category TEXT NOT NULL REFERENCES maevsi.event_category(category) ON DELETE CASCADE, + + PRIMARY KEY (account_id, category) +); + +COMMENT ON TABLE maevsi.account_interest IS 'Event categories a user account is interested in (M:N relationship).'; +COMMENT ON COLUMN maevsi.account_interest.account_id IS 'A user account id.'; +COMMENT ON COLUMN maevsi.account_interest.category IS 'An event category.'; + +COMMIT; diff --git a/src/deploy/table_account_interest_policy.sql b/src/deploy/table_account_interest_policy.sql new file mode 100644 index 00000000..3f94072a --- /dev/null +++ b/src/deploy/table_account_interest_policy.sql @@ -0,0 +1,22 @@ +BEGIN; + +GRANT SELECT, INSERT, DELETE ON TABLE maevsi.account_interest TO maevsi_account; + +ALTER TABLE maevsi.account_interest ENABLE ROW LEVEL SECURITY; + +-- Only allow selects by the current account. +CREATE POLICY account_interest_select ON maevsi.account_interest FOR SELECT USING ( + account_id = maevsi.invoker_account_id() +); + +-- Only allow inserts by the current account. +CREATE POLICY account_interest_insert ON maevsi.account_interest FOR INSERT WITH CHECK ( + account_id = maevsi.invoker_account_id() +); + +-- Only allow deletes by the current account. +CREATE POLICY account_interest_delete ON maevsi.account_interest FOR DELETE USING ( + account_id = maevsi.invoker_account_id() +); + +COMMIT; diff --git a/src/deploy/table_account_preference_event_size.sql b/src/deploy/table_account_preference_event_size.sql new file mode 100644 index 00000000..a1ff33a3 --- /dev/null +++ b/src/deploy/table_account_preference_event_size.sql @@ -0,0 +1,17 @@ +BEGIN; + +CREATE TABLE maevsi.account_preference_event_size ( + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + + account_id UUID REFERENCES maevsi.account(id), + event_size maevsi.event_size, + + PRIMARY KEY (account_id, event_size) +); + +COMMENT ON TABLE maevsi.account_preference_event_size IS 'Table for the user accounts'' preferred event sizes (M:N relationship).'; +COMMENT ON COLUMN maevsi.account_preference_event_size.created_at IS E'@omit create,update\nTimestamp of when the event size preference was created, defaults to the current timestamp.'; +COMMENT ON COLUMN maevsi.account_preference_event_size.account_id IS 'The account''s internal id.'; +COMMENT ON COLUMN maevsi.account_preference_event_size.event_size IS 'A preferred event sized'; + +END; diff --git a/src/deploy/table_account_preference_event_size_policy.sql b/src/deploy/table_account_preference_event_size_policy.sql new file mode 100644 index 00000000..004d967d --- /dev/null +++ b/src/deploy/table_account_preference_event_size_policy.sql @@ -0,0 +1,22 @@ +BEGIN; + +GRANT SELECT, INSERT, DELETE ON TABLE maevsi.account_preference_event_size TO maevsi_account; + +ALTER TABLE maevsi.account_preference_event_size ENABLE ROW LEVEL SECURITY; + +-- Only allow selects by the current account. +CREATE POLICY account_preference_event_size_select ON maevsi.account_preference_event_size FOR SELECT USING ( + account_id = maevsi.invoker_account_id() +); + +-- Only allow inserts by the current account. +CREATE POLICY account_preference_event_size_insert ON maevsi.account_preference_event_size FOR INSERT WITH CHECK ( + account_id = maevsi.invoker_account_id() +); + +-- Only allow deletes by the current account. +CREATE POLICY account_preference_event_size_delete ON maevsi.account_preference_event_size FOR DELETE USING ( + account_id = maevsi.invoker_account_id() +); + +COMMIT; diff --git a/src/deploy/table_account_private.sql b/src/deploy/table_account_private.sql index 78c53872..b79c2f61 100644 --- a/src/deploy/table_account_private.sql +++ b/src/deploy/table_account_private.sql @@ -1,16 +1,14 @@ --- Deploy maevsi:table_account_private to pg --- requires: schema_private --- requires: schema_public - BEGIN; CREATE TABLE maevsi_private.account ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - created TIMESTAMP NOT NULL DEFAULT NOW(), + + birth_date DATE, -- TODO: evaluate if this should be `NOT NULL` for all new accounts + created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, email_address TEXT NOT NULL CHECK (char_length(email_address) < 255) UNIQUE, -- no regex check as "a valid email address is one that you can send emails to" (http://www.dominicsayers.com/isemail/) email_address_verification UUID DEFAULT gen_random_uuid(), email_address_verification_valid_until TIMESTAMP, - last_activity TIMESTAMP NOT NULL DEFAULT NOW(), + last_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, password_hash TEXT NOT NULL, password_reset_verification UUID, password_reset_verification_valid_until TIMESTAMP, @@ -19,6 +17,7 @@ CREATE TABLE maevsi_private.account ( COMMENT ON TABLE maevsi_private.account IS 'Private account data.'; COMMENT ON COLUMN maevsi_private.account.id IS 'The account''s internal id.'; +COMMENT ON COLUMN maevsi_private.account.birth_date IS 'The account owner''s date of birth.'; COMMENT ON COLUMN maevsi_private.account.created IS 'Timestamp at which the account was last active.'; COMMENT ON COLUMN maevsi_private.account.email_address IS 'The account''s email address for account related information.'; COMMENT ON COLUMN maevsi_private.account.email_address_verification IS 'The UUID used to verify an email address, or null if already verified.'; @@ -35,7 +34,7 @@ CREATE FUNCTION maevsi_private.account_email_address_verification_valid_until() NEW.email_address_verification_valid_until = NULL; ELSE IF ((OLD IS NULL) OR (OLD.email_address_verification IS DISTINCT FROM NEW.email_address_verification)) THEN - NEW.email_address_verification_valid_until = (SELECT (NOW() + INTERVAL '1 day')::TIMESTAMP); + NEW.email_address_verification_valid_until = (SELECT (CURRENT_TIMESTAMP + INTERVAL '1 day')::TIMESTAMP); END IF; END IF; @@ -53,7 +52,7 @@ CREATE FUNCTION maevsi_private.account_password_reset_verification_valid_until() NEW.password_reset_verification_valid_until = NULL; ELSE IF ((OLD IS NULL) OR (OLD.password_reset_verification IS DISTINCT FROM NEW.password_reset_verification)) THEN - NEW.password_reset_verification_valid_until = (SELECT (NOW() + INTERVAL '2 hours')::TIMESTAMP); + NEW.password_reset_verification_valid_until = (SELECT (CURRENT_TIMESTAMP + INTERVAL '2 hours')::TIMESTAMP); END IF; END IF; diff --git a/src/deploy/table_account_public.sql b/src/deploy/table_account_public.sql index 1749c94c..502ff010 100644 --- a/src/deploy/table_account_public.sql +++ b/src/deploy/table_account_public.sql @@ -1,8 +1,3 @@ --- Deploy maevsi:table_account_public to pg --- requires: schema_public --- requires: schema_private --- requires: table_account_private - BEGIN; CREATE TABLE maevsi.account ( diff --git a/src/deploy/table_account_social_network.sql b/src/deploy/table_account_social_network.sql new file mode 100644 index 00000000..b83cc143 --- /dev/null +++ b/src/deploy/table_account_social_network.sql @@ -0,0 +1,17 @@ +BEGIN; + +CREATE TABLE maevsi.account_social_network ( + account_id UUID NOT NULL REFERENCES maevsi.account(id) ON DELETE CASCADE, + social_network maevsi.social_network NOT NULL, + social_network_username TEXT NOT NULL, + + PRIMARY KEY (account_id, social_network) +); + +COMMENT ON TABLE maevsi.account_social_network IS 'Links accounts to their social media profiles. Each entry represents a specific social network and associated username for an account.'; +COMMENT ON COLUMN maevsi.account_social_network.account_id IS 'The unique identifier of the account.'; +COMMENT ON COLUMN maevsi.account_social_network.social_network IS 'The social network to which the account is linked.'; +COMMENT ON COLUMN maevsi.account_social_network.social_network_username IS 'The username of the account on the specified social network.'; +COMMENT ON CONSTRAINT account_social_network_pkey ON maevsi.account_social_network IS 'Ensures uniqueness by combining the account ID and social network, allowing each account to have a single entry per social network.'; + +COMMIT; diff --git a/src/deploy/table_account_social_network_policy.sql b/src/deploy/table_account_social_network_policy.sql new file mode 100644 index 00000000..99c9eff9 --- /dev/null +++ b/src/deploy/table_account_social_network_policy.sql @@ -0,0 +1,23 @@ +BEGIN; + +GRANT SELECT ON TABLE maevsi.account_social_network TO maevsi_anonymous; +GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE maevsi.account_social_network TO maevsi_account; + +ALTER TABLE maevsi.account_social_network ENABLE ROW LEVEL SECURITY; + +-- Only allow inserting social links of the current account. +CREATE POLICY account_social_network_insert ON maevsi.account_social_network FOR INSERT WITH CHECK ( + account_id = maevsi.invoker_account_id() +); + +-- Only allow updating social links of the current account. +CREATE POLICY account_social_network_update ON maevsi.account_social_network FOR UPDATE USING ( + account_id = maevsi.invoker_account_id() +); + +-- Only allow deleting social links of the current account.. +CREATE POLICY account_social_network_delete ON maevsi.account_social_network FOR DELETE USING ( + account_id = maevsi.invoker_account_id() +); + +COMMIT; diff --git a/src/deploy/table_achievement.sql b/src/deploy/table_achievement.sql index b1544172..b5377ec2 100644 --- a/src/deploy/table_achievement.sql +++ b/src/deploy/table_achievement.sql @@ -1,10 +1,3 @@ --- Deploy maevsi:table_achievement to pg --- requires: schema_public --- requires: table_account_public --- requires: enum_achievement_type --- requires: role_account --- requires: role_anonymous - BEGIN; CREATE TABLE maevsi.achievement ( diff --git a/src/deploy/table_achievement_code.sql b/src/deploy/table_achievement_code.sql index 40adf944..554a94e1 100644 --- a/src/deploy/table_achievement_code.sql +++ b/src/deploy/table_achievement_code.sql @@ -1,9 +1,3 @@ --- Deploy maevsi:table_achievement_code to pg --- requires: schema_private --- requires: schema_public --- requires: enum_achievement_type --- requires: role_tusd - BEGIN; CREATE TABLE maevsi_private.achievement_code ( diff --git a/src/deploy/table_contact.sql b/src/deploy/table_contact.sql index 52e71adc..7971d4c0 100644 --- a/src/deploy/table_contact.sql +++ b/src/deploy/table_contact.sql @@ -1,35 +1,39 @@ --- Deploy maevsi:table_contact to pg --- requires: schema_public --- requires: role_account --- requires: role_anonymous --- requires: table_account_public - BEGIN; CREATE TABLE maevsi.contact ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + account_id UUID REFERENCES maevsi.account(id), - "address" TEXT CHECK (char_length("address") > 0 AND char_length("address") < 300), + address TEXT CHECK (char_length("address") > 0 AND char_length("address") < 300), author_account_id UUID NOT NULL REFERENCES maevsi.account(id) ON DELETE CASCADE, email_address TEXT CHECK (char_length(email_address) < 255), -- no regex check as "a valid email address is one that you can send emails to" (http://www.dominicsayers.com/isemail/) email_address_hash TEXT GENERATED ALWAYS AS (md5(lower(substring(email_address, '\S(?:.*\S)*')))) STORED, -- for gravatar profile pictures first_name TEXT CHECK (char_length(first_name) > 0 AND char_length(first_name) < 100), + language maevsi.language, last_name TEXT CHECK (char_length(last_name) > 0 AND char_length(last_name) < 100), + nickname TEXT CHECK (char_length(nickname) > 0 AND char_length(nickname) < 100), phone_number TEXT CHECK (phone_number ~ '^\+(?:[0-9] ?){6,14}[0-9]$'), -- E.164 format (https://wikipedia.org/wiki/E.164) - "url" TEXT CHECK (char_length("url") < 300 AND "url" ~ '^https:\/\/'), + timezone TEXT CHECK (timezone ~ '^([+-](0[0-9]|1[0-4]):[0-5][0-9]|Z)$'), + url TEXT CHECK (char_length("url") < 300 AND "url" ~ '^https:\/\/'), + UNIQUE (author_account_id, account_id) ); COMMENT ON TABLE maevsi.contact IS 'Contact data.'; COMMENT ON COLUMN maevsi.contact.id IS E'@omit create,update\nThe contact''s internal id.'; +COMMENT ON COLUMN maevsi.contact.created_at IS E'@omit create,update\nTimestamp of when the contact was created, defaults to the current timestamp.'; COMMENT ON COLUMN maevsi.contact.account_id IS 'The contact account''s id.'; COMMENT ON COLUMN maevsi.contact.address IS 'The contact''s physical address.'; COMMENT ON COLUMN maevsi.contact.author_account_id IS 'The contact author''s id.'; COMMENT ON COLUMN maevsi.contact.email_address IS 'The contact''s email address.'; COMMENT ON COLUMN maevsi.contact.email_address_hash IS E'@omit create,update\nThe contact''s email address''s md5 hash.'; COMMENT ON COLUMN maevsi.contact.first_name IS 'The contact''s first name.'; +COMMENT ON COLUMN maevsi.contact.language IS 'The contact''s language.'; COMMENT ON COLUMN maevsi.contact.last_name IS 'The contact''s last name.'; -COMMENT ON COLUMN maevsi.contact.phone_number IS 'The contact''s international phone number.'; +COMMENT ON COLUMN maevsi.contact.nickname IS 'The contact''s nickname.'; +COMMENT ON COLUMN maevsi.contact.phone_number IS 'The contact''s international phone number in E.164 format (https://wikipedia.org/wiki/E.164).'; +COMMENT ON COLUMN maevsi.contact.timezone IS 'The contact''s ISO 8601 timezone, e.g. `+02:00`, `-05:30` or `Z`.'; COMMENT ON COLUMN maevsi.contact.url IS 'The contact''s website url.'; -- GRANTs, RLS and POLICYs are specified in 'table_contact_policy`. @@ -38,15 +42,15 @@ CREATE FUNCTION maevsi.trigger_contact_update_account_id() RETURNS TRIGGER AS $$ BEGIN IF ( -- invoked without account it - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NULL + maevsi.invoker_account_id() IS NULL OR -- invoked with account it -- and ( -- updating own account's contact - OLD.account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + OLD.account_id = maevsi.invoker_account_id() AND - OLD.author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + OLD.author_account_id = maevsi.invoker_account_id() AND ( -- trying to detach from account diff --git a/src/deploy/table_contact_policy.sql b/src/deploy/table_contact_policy.sql index e5fba06d..e06e46e6 100644 --- a/src/deploy/table_contact_policy.sql +++ b/src/deploy/table_contact_policy.sql @@ -1,11 +1,3 @@ --- Deploy maevsi:table_contact_policy to pg --- requires: schema_public --- requires: table_account_block --- requires: table_contact --- requires: role_account --- requires: role_anonymous --- requires: function_invitation_contact_ids - BEGIN; GRANT SELECT ON TABLE maevsi.contact TO maevsi_account, maevsi_anonymous; @@ -18,16 +10,16 @@ ALTER TABLE maevsi.contact ENABLE ROW LEVEL SECURITY; -- Only display contacts for which an accessible invitation exists. CREATE POLICY contact_select ON maevsi.contact FOR SELECT USING ( ( - account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + account_id = maevsi.invoker_account_id() AND author_account_id NOT IN ( SELECT blocked_account_id FROM maevsi.account_block - WHERE author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE author_account_id = maevsi.invoker_account_id() UNION ALL SELECT author_account_id FROM maevsi.account_block - WHERE blocked_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE blocked_account_id = maevsi.invoker_account_id() ) ) OR @@ -54,32 +46,32 @@ CREATE POLICY contact_select ON maevsi.contact FOR SELECT USING ( -- Only allow inserts for contacts authored by the invoker's account. -- Disallow inserts for contacts that refer to a blocked account. CREATE POLICY contact_insert ON maevsi.contact FOR INSERT WITH CHECK ( - author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + author_account_id = maevsi.invoker_account_id() AND account_id NOT IN ( SELECT blocked_account_id FROM maevsi.account_block - WHERE author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE author_account_id = maevsi.invoker_account_id() ) ); -- Only allow updates for contacts authored by the invoker's account. -- No contact referring to a blocked account can be updated. CREATE POLICY contact_update ON maevsi.contact FOR UPDATE USING ( - author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + author_account_id = maevsi.invoker_account_id() AND account_id NOT IN ( SELECT blocked_account_id FROM maevsi.account_block - WHERE author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE author_account_id = maevsi.invoker_account_id() ) ); -- Only allow deletes for contacts authored by the invoker's account except for the own account's contact. CREATE POLICY contact_delete ON maevsi.contact FOR DELETE USING ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + author_account_id = maevsi.invoker_account_id() AND - account_id IS DISTINCT FROM NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + account_id IS DISTINCT FROM maevsi.invoker_account_id() ); COMMIT; diff --git a/src/deploy/table_event.sql b/src/deploy/table_event.sql index bab8646b..8c219528 100644 --- a/src/deploy/table_event.sql +++ b/src/deploy/table_event.sql @@ -1,32 +1,29 @@ --- Deploy maevsi:table_event to pg --- requires: schema_public --- requires: role_account --- requires: role_anonymous --- requires: table_account_public --- requires: enum_event_visibility - BEGIN; CREATE TABLE maevsi.event ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + author_account_id UUID NOT NULL REFERENCES maevsi.account(id), - "description" TEXT CHECK (char_length("description") > 0 AND char_length("description") < 1000000), - "end" TIMESTAMP WITH TIME ZONE, + description TEXT CHECK (char_length("description") > 0 AND char_length("description") < 1000000), + "end" TIMESTAMP WITH TIME ZONE, invitee_count_maximum INTEGER CHECK (invitee_count_maximum > 0), is_archived BOOLEAN NOT NULL DEFAULT FALSE, is_in_person BOOLEAN, is_remote BOOLEAN, - "location" TEXT CHECK (char_length("location") > 0 AND char_length("location") < 300), - "name" TEXT NOT NULL CHECK (char_length("name") > 0 AND char_length("name") < 100), + location TEXT CHECK (char_length("location") > 0 AND char_length("location") < 300), + name TEXT NOT NULL CHECK (char_length("name") > 0 AND char_length("name") < 100), slug TEXT NOT NULL CHECK (char_length(slug) < 100 AND slug ~ '^[-A-Za-z0-9]+$'), - "start" TIMESTAMP WITH TIME ZONE NOT NULL, - "url" TEXT CHECK (char_length("url") < 300 AND "url" ~ '^https:\/\/'), + start TIMESTAMP WITH TIME ZONE NOT NULL, + url TEXT CHECK (char_length("url") < 300 AND "url" ~ '^https:\/\/'), visibility maevsi.event_visibility NOT NULL, + UNIQUE (author_account_id, slug) ); COMMENT ON TABLE maevsi.event IS 'An event.'; COMMENT ON COLUMN maevsi.event.id IS E'@omit create,update\nThe event''s internal id.'; +COMMENT ON COLUMN maevsi.event.created_at IS E'@omit create,update\nTimestamp of when the event was created, defaults to the current timestamp.'; COMMENT ON COLUMN maevsi.event.author_account_id IS 'The event author''s id.'; COMMENT ON COLUMN maevsi.event.description IS 'The event''s description.'; COMMENT ON COLUMN maevsi.event.end IS 'The event''s end date and time, with timezone.'; diff --git a/src/deploy/table_event_category.sql b/src/deploy/table_event_category.sql new file mode 100644 index 00000000..c01cd9bf --- /dev/null +++ b/src/deploy/table_event_category.sql @@ -0,0 +1,10 @@ +BEGIN; + +CREATE TABLE maevsi.event_category( + category TEXT PRIMARY KEY +); + +COMMENT ON TABLE maevsi.event_category IS 'Event categories.'; +COMMENT ON COLUMN maevsi.event_category.category IS 'A category name.'; + +END; diff --git a/src/deploy/table_event_category_mapping.sql b/src/deploy/table_event_category_mapping.sql new file mode 100644 index 00000000..9e1db6d7 --- /dev/null +++ b/src/deploy/table_event_category_mapping.sql @@ -0,0 +1,13 @@ +BEGIN; + +CREATE TABLE maevsi.event_category_mapping ( + event_id uuid NOT NULL REFERENCES maevsi.event(id) ON DELETE CASCADE, + category TEXT NOT NULL REFERENCES maevsi.event_category(category) ON DELETE CASCADE, + PRIMARY KEY (event_id, category) +); + +COMMENT ON TABLE maevsi.event_category_mapping IS 'Mapping events to categories (M:N relationship).'; +COMMENT ON COLUMN maevsi.event_category_mapping.event_id IS 'An event id.'; +COMMENT ON COLUMN maevsi.event_category_mapping.category IS 'A category name.'; + +COMMIT; diff --git a/src/deploy/table_event_category_mapping_policy.sql b/src/deploy/table_event_category_mapping_policy.sql new file mode 100644 index 00000000..cfac16ea --- /dev/null +++ b/src/deploy/table_event_category_mapping_policy.sql @@ -0,0 +1,45 @@ +BEGIN; + +GRANT SELECT ON TABLE maevsi.event_category_mapping TO maevsi_anonymous; +GRANT SELECT, INSERT, DELETE ON TABLE maevsi.event_category_mapping TO maevsi_account; + +ALTER TABLE maevsi.event_category_mapping ENABLE ROW LEVEL SECURITY; + +-- Only allow selects for events authored by user, events that are public or that the user is invited to. +-- Exclude events created by a blocked user and invitated events where the invation comes form a blocked user. +CREATE POLICY event_category_mapping_select ON maevsi.event_category_mapping FOR SELECT USING ( + ( + maevsi.invoker_account_id() IS NOT NULL + AND ( + (SELECT author_account_id FROM maevsi.event WHERE id = event_id) = maevsi.invoker_account_id() + ) + ) + OR + event_id IN (SELECT maevsi_private.events_invited()) + -- TODO: condition using table maevsi.account_block to be added later +/* + AND + (SELECT visibility FROM maevsi.event WHERE id = event_id) = 'public' + AND event_id NOT IN ( + SELECT e.event_id + FROM maevsi.event e JOIN maevsi.account_block b ON e.account_id = b.blocked_account_id + WHERE b.account_id = maevsi.invoker_account_id() + ) +*/ +); + +-- Only allow inserts for events authored by user. +CREATE POLICY event_category_mapping_insert ON maevsi.event_category_mapping FOR INSERT WITH CHECK ( + maevsi.invoker_account_id() IS NOT NULL + AND + (SELECT author_account_id FROM maevsi.event WHERE id = event_id) = maevsi.invoker_account_id() +); + +-- Only allow deletes for events authored by user. +CREATE POLICY event_category_mapping_delete ON maevsi.event_category_mapping FOR DELETE USING ( + maevsi.invoker_account_id() IS NOT NULL + AND + (SELECT author_account_id FROM maevsi.event WHERE id = event_id) = maevsi.invoker_account_id() +); + +COMMIT; diff --git a/src/deploy/table_event_category_policy.sql b/src/deploy/table_event_category_policy.sql new file mode 100644 index 00000000..12e81b89 --- /dev/null +++ b/src/deploy/table_event_category_policy.sql @@ -0,0 +1,7 @@ +BEGIN; + +GRANT SELECT ON TABLE maevsi.event_category TO maevsi_anonymous, maevsi_account; + +-- no row level security necessary for this table as it does not contain user data + +COMMIT; diff --git a/src/deploy/table_event_favourite.sql b/src/deploy/table_event_favourite.sql new file mode 100644 index 00000000..cd8e1c70 --- /dev/null +++ b/src/deploy/table_event_favourite.sql @@ -0,0 +1,14 @@ +BEGIN; + +CREATE TABLE maevsi.event_favourite ( + account_id uuid NOT NULL REFERENCES maevsi.account(id) ON DELETE CASCADE, + event_id uuid NOT NULL REFERENCES maevsi.event(id) ON DELETE CASCADE, + + PRIMARY KEY (account_id, event_id) +); + +COMMENT ON TABLE maevsi.event_favourite IS 'The user accounts'' favourite events.'; +COMMENT ON COLUMN maevsi.event_favourite.account_id IS 'A user account id.'; +COMMENT ON COLUMN maevsi.event_favourite.event_id IS 'The ID of an event which the user marked as a favourite.'; + +COMMIT; diff --git a/src/deploy/table_event_favourite_policy.sql b/src/deploy/table_event_favourite_policy.sql new file mode 100644 index 00000000..825cbafc --- /dev/null +++ b/src/deploy/table_event_favourite_policy.sql @@ -0,0 +1,14 @@ +BEGIN; + +GRANT SELECT, INSERT, DELETE ON TABLE maevsi.event_favourite TO maevsi_account; + +ALTER TABLE maevsi.event_favourite ENABLE ROW LEVEL SECURITY; + +-- Only allow selects by the current user. +CREATE POLICY event_favourite_select ON maevsi.event_favourite FOR SELECT USING ( + maevsi.invoker_account_id() IS NOT NULL + AND + account_id = maevsi.invoker_account_id() +); + +COMMIT; diff --git a/src/deploy/table_event_group.sql b/src/deploy/table_event_group.sql index 75e9f228..d730c314 100644 --- a/src/deploy/table_event_group.sql +++ b/src/deploy/table_event_group.sql @@ -1,13 +1,9 @@ --- Deploy maevsi:table_event_group to pg --- requires: schema_public --- requires: role_account --- requires: role_anonymous --- requires: table_account_public - BEGIN; CREATE TABLE maevsi.event_group ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + author_account_id UUID NOT NULL REFERENCES maevsi.account(id), "description" TEXT CHECK (char_length("description") < 1000000), is_archived BOOLEAN NOT NULL DEFAULT FALSE, @@ -18,6 +14,7 @@ CREATE TABLE maevsi.event_group ( COMMENT ON TABLE maevsi.event_group IS 'A group of events.'; COMMENT ON COLUMN maevsi.event_group.id IS E'@omit create,update\nThe event group''s internal id.'; +COMMENT ON COLUMN maevsi.event_group.created_at IS E'@omit create,update\nTimestamp of when the event group was created, defaults to the current timestamp.'; COMMENT ON COLUMN maevsi.event_group.author_account_id IS 'The event group author''s id.'; COMMENT ON COLUMN maevsi.event_group.description IS 'The event group''s description.'; COMMENT ON COLUMN maevsi.event_group.is_archived IS 'Indicates whether the event group is archived.'; diff --git a/src/deploy/table_event_grouping.sql b/src/deploy/table_event_grouping.sql index 71a37295..39579564 100644 --- a/src/deploy/table_event_grouping.sql +++ b/src/deploy/table_event_grouping.sql @@ -1,10 +1,3 @@ --- Deploy maevsi:table_event_grouping to pg --- requires: schema_public --- requires: role_account --- requires: role_anonymous --- requires: table_event --- requires: table_event_group - BEGIN; CREATE TABLE maevsi.event_grouping ( diff --git a/src/deploy/table_event_policy.sql b/src/deploy/table_event_policy.sql index 7a1493f1..46d4b5e0 100644 --- a/src/deploy/table_event_policy.sql +++ b/src/deploy/table_event_policy.sql @@ -1,12 +1,3 @@ --- Deploy maevsi:table_event_policy to pg --- requires: schema_public --- requires: table_event --- requires: table_account_block --- requires: role_account --- requires: role_anonymous --- requires: schema_private --- requires: function_events_invited - BEGIN; GRANT SELECT ON TABLE maevsi.event TO maevsi_account, maevsi_anonymous; @@ -30,15 +21,15 @@ CREATE POLICY event_select ON maevsi.event FOR SELECT USING ( AND author_account_id NOT IN ( SELECT blocked_account_id FROM maevsi.account_block - WHERE author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE author_account_id = maevsi.invoker_account_id() UNION ALL SELECT author_account_id FROM maevsi.account_block - WHERE blocked_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE blocked_account_id = maevsi.invoker_account_id() ) ) OR ( - author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + author_account_id = maevsi.invoker_account_id() ) OR ( id IN (SELECT maevsi_private.events_invited()) @@ -47,16 +38,16 @@ CREATE POLICY event_select ON maevsi.event FOR SELECT USING ( -- Only allow inserts for events authored by the current user. CREATE POLICY event_insert ON maevsi.event FOR INSERT WITH CHECK ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + author_account_id = maevsi.invoker_account_id() ); -- Only allow updates for events authored by the current user. CREATE POLICY event_update ON maevsi.event FOR UPDATE USING ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + author_account_id = maevsi.invoker_account_id() ); COMMIT; diff --git a/src/deploy/table_event_recommendation.sql b/src/deploy/table_event_recommendation.sql new file mode 100644 index 00000000..5921c689 --- /dev/null +++ b/src/deploy/table_event_recommendation.sql @@ -0,0 +1,19 @@ +BEGIN; + +CREATE TABLE maevsi.event_recommendation ( + account_id uuid NOT NULL REFERENCES maevsi.account(id) ON DELETE CASCADE, + event_id uuid NOT NULL REFERENCES maevsi.event(id) ON DELETE CASCADE, + score float(8), + predicted_score float(8), + + PRIMARY KEY (account_id, event_id) +); + +COMMENT ON TABLE maevsi.event_recommendation IS 'Events recommended to a user account (M:N relationship).'; +COMMENT ON COLUMN maevsi.event_recommendation.account_id IS 'A user account id.'; +COMMENT ON COLUMN maevsi.event_recommendation.event_id IS 'An event id.'; +COMMENT ON COLUMN maevsi.event_recommendation.score IS 'An event id.'; +COMMENT ON COLUMN maevsi.event_recommendation.predicted_score IS 'The score of the recommendation.'; +COMMENT ON COLUMN maevsi.event_recommendation.event_id IS 'The predicted score of the recommendation.'; + +COMMIT; diff --git a/src/deploy/table_event_recommendation_policy.sql b/src/deploy/table_event_recommendation_policy.sql new file mode 100644 index 00000000..569f54bb --- /dev/null +++ b/src/deploy/table_event_recommendation_policy.sql @@ -0,0 +1,14 @@ +BEGIN; + +GRANT SELECT, INSERT, DELETE ON TABLE maevsi.event_recommendation TO maevsi_account; + +ALTER TABLE maevsi.event_recommendation ENABLE ROW LEVEL SECURITY; + +-- Only allow selects by the current user. +CREATE POLICY event_recommendation_select ON maevsi.event_recommendation FOR SELECT USING ( + maevsi.invoker_account_id() IS NOT NULL + AND + account_id = maevsi.invoker_account_id() +); + +COMMIT; diff --git a/src/deploy/table_event_upload.sql b/src/deploy/table_event_upload.sql new file mode 100644 index 00000000..cda1380d --- /dev/null +++ b/src/deploy/table_event_upload.sql @@ -0,0 +1,17 @@ +BEGIN; + +CREATE TABLE maevsi.event_upload ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + + event_id UUID NOT NULL REFERENCES maevsi.event(id), + upload_id UUID NOT NULL REFERENCES maevsi.upload(id), + + UNIQUE (event_id, upload_id) +); + +COMMENT ON TABLE maevsi.event_upload IS 'An assignment of an uploaded content (e.g. an image) to an event.'; +COMMENT ON COLUMN maevsi.event_upload.id IS E'@omit create,update\nThe event''s internal id for which the invitation is valid.'; +COMMENT ON COLUMN maevsi.event_upload.event_id IS E'@omit update\nThe event''s internal id for which the invitation is valid.'; +COMMENT ON COLUMN maevsi.event_upload.upload_id IS E'@omit update\nThe internal id of the uploaded content.'; + +END; diff --git a/src/deploy/table_event_upload_policy.sql b/src/deploy/table_event_upload_policy.sql new file mode 100644 index 00000000..fd4f790c --- /dev/null +++ b/src/deploy/table_event_upload_policy.sql @@ -0,0 +1,37 @@ +BEGIN; + +GRANT SELECT ON TABLE maevsi.event_upload TO maevsi_account, maevsi_anonymous; +GRANT INSERT, DELETE ON TABLE maevsi.event_upload TO maevsi_account; + +ALTER TABLE maevsi.event_upload ENABLE ROW LEVEL SECURITY; + +-- Only select rows for accessable events where accessability is specified +-- by the event_select policy for table event. +CREATE POLICY event_upload_select ON maevsi.event_upload FOR SELECT USING ( + event_id IN ( + SELECT id FROM maevsi.event + ) +); + +-- Only allow inserts for events authored by the current user and for uploads of the current_user. +CREATE POLICY event_upload_insert ON maevsi.event_upload FOR INSERT WITH CHECK ( + event_id IN ( + SELECT id FROM maevsi.event + WHERE author_account_id = maevsi.invoker_account_id() + ) + AND + upload_id IN ( + SELECT id FROM maevsi.upload + WHERE account_id = maevsi.invoker_account_id() + ) +); + +-- Only allow deletes if event is authored by the current user. +CREATE POLICY event_upload_delete ON maevsi.event_upload FOR DELETE USING ( + event_id IN ( + SELECT id FROM maevsi.event + WHERE author_account_id = maevsi.invoker_account_id() + ) +); + +COMMIT; diff --git a/src/deploy/table_invitation.sql b/src/deploy/table_invitation.sql index fc5bb79d..2645d11a 100644 --- a/src/deploy/table_invitation.sql +++ b/src/deploy/table_invitation.sql @@ -1,23 +1,24 @@ --- Deploy maevsi:table_invitation to pg --- requires: schema_public --- requires: table_event --- requires: table_contact --- requires: enum_invitation_feedback --- requires: enum_invitation_feedback_paper - BEGIN; CREATE TABLE maevsi.invitation ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP WITH TIME ZONE, + updated_by UUID REFERENCES maevsi.account(id), + contact_id UUID NOT NULL REFERENCES maevsi.contact(id), event_id UUID NOT NULL REFERENCES maevsi.event(id), feedback maevsi.invitation_feedback, feedback_paper maevsi.invitation_feedback_paper, + UNIQUE (event_id, contact_id) ); COMMENT ON TABLE maevsi.invitation IS 'An invitation for a contact. A bidirectional mapping between an event and a contact.'; COMMENT ON COLUMN maevsi.invitation.id IS E'@omit create,update\nThe invitations''s internal id.'; +COMMENT ON COLUMN maevsi.invitation.created_at IS E'@omit create,update\nTimestamp of when the invitation was created, defaults to the current timestamp.'; +COMMENT ON COLUMN maevsi.invitation.updated_at IS E'@omit create,update\nTimestamp of when the invitation was last updated.'; +COMMENT ON COLUMN maevsi.invitation.updated_by IS E'@omit create,update\nThe id of the account which last updated the invitation. `NULL` if the invitation was updated by an anonymous user.'; COMMENT ON COLUMN maevsi.invitation.contact_id IS 'The contact''s internal id for which the invitation is valid.'; COMMENT ON COLUMN maevsi.invitation.event_id IS 'The event''s internal id for which the invitation is valid.'; COMMENT ON COLUMN maevsi.invitation.feedback IS 'The invitation''s general feedback status.'; diff --git a/src/deploy/table_invitation_policy.sql b/src/deploy/table_invitation_policy.sql index d957f1d1..56e7696d 100644 --- a/src/deploy/table_invitation_policy.sql +++ b/src/deploy/table_invitation_policy.sql @@ -1,14 +1,3 @@ --- Deploy maevsi:table_invitation_policy to pg --- requires: schema_public --- requires: table_invitation --- requires: table_contact --- requires: table_account_block --- requires: role_account --- requires: role_anonymous --- requires: function_invitation_claim_array --- requires: function_events_organized --- requires: function_event_invitee_count_maximum - BEGIN; GRANT SELECT, UPDATE ON TABLE maevsi.invitation TO maevsi_account, maevsi_anonymous; @@ -26,7 +15,7 @@ CREATE POLICY invitation_select ON maevsi.invitation FOR SELECT USING ( contact_id IN ( SELECT id FROM maevsi.contact - WHERE account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE account_id = maevsi.invoker_account_id() EXCEPT @@ -34,7 +23,7 @@ CREATE POLICY invitation_select ON maevsi.invitation FOR SELECT USING ( SELECT c.id FROM maevsi.contact c JOIN maevsi.account_block b ON c.account_id = b.author_account_id AND c.author_account_id = b.blocked_account_id - WHERE c.account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE c.account_id = maevsi.invoker_account_id() ) ) OR ( @@ -47,11 +36,11 @@ CREATE POLICY invitation_select ON maevsi.invitation FOR SELECT USING ( OR c.account_id NOT IN ( SELECT blocked_account_id FROM maevsi.account_block - WHERE author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE author_account_id = maevsi.invoker_account_id() UNION ALL SELECT author_account_id FROM maevsi.account_block - WHERE blocked_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE blocked_account_id = maevsi.invoker_account_id() ) ) ) @@ -72,14 +61,14 @@ CREATE POLICY invitation_insert ON maevsi.invitation FOR INSERT WITH CHECK ( contact_id IN ( SELECT id FROM maevsi.contact - WHERE author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE author_account_id = maevsi.invoker_account_id() EXCEPT SELECT c.id FROM maevsi.contact c JOIN maevsi.account_block b ON c.account_id = b.blocked_account_id and c.author_account_id = b.author_account_id - WHERE c.author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE c.author_account_id = maevsi.invoker_account_id() ) ); @@ -93,14 +82,14 @@ CREATE POLICY invitation_update ON maevsi.invitation FOR UPDATE USING ( contact_id IN ( SELECT id FROM maevsi.contact - WHERE account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE account_id = maevsi.invoker_account_id() EXCEPT SELECT c.id FROM maevsi.contact c JOIN maevsi.account_block b ON c.account_id = b.author_account_id and c.author_account_id = b.blocked_account_id - WHERE c.account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE c.account_id = maevsi.invoker_account_id() ) ) OR @@ -115,11 +104,11 @@ CREATE POLICY invitation_update ON maevsi.invitation FOR UPDATE USING ( OR c.account_id NOT IN ( SELECT blocked_account_id FROM maevsi.account_block - WHERE author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE author_account_id = maevsi.invoker_account_id() UNION ALL SELECT author_account_id FROM maevsi.account_block - WHERE blocked_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE blocked_account_id = maevsi.invoker_account_id() ) ) ) @@ -140,12 +129,12 @@ BEGIN OLD.id = ANY (maevsi.invitation_claim_array()) OR ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND OLD.contact_id IN ( SELECT id FROM maevsi.contact - WHERE contact.account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE contact.account_id = maevsi.invoker_account_id() ) ) ) @@ -159,6 +148,8 @@ BEGIN THEN RAISE 'You''re only allowed to alter these rows: %!', whitelisted_cols USING ERRCODE = 'insufficient_privilege'; ELSE + NEW.updated_at = CURRENT_TIMESTAMP; + NEW.updated_by = maevsi.invoker_account_id(); RETURN NEW; END IF; END $$ LANGUAGE PLPGSQL STRICT VOLATILE SECURITY INVOKER; diff --git a/src/deploy/table_jwt.sql b/src/deploy/table_jwt.sql index 9387acbd..b69c6393 100644 --- a/src/deploy/table_jwt.sql +++ b/src/deploy/table_jwt.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:table_jwt to pg --- requires: schema_private - BEGIN; CREATE TABLE maevsi_private.jwt ( diff --git a/src/deploy/table_legal_term.sql b/src/deploy/table_legal_term.sql index db980db7..cc8802a4 100644 --- a/src/deploy/table_legal_term.sql +++ b/src/deploy/table_legal_term.sql @@ -1,8 +1,3 @@ --- Deploy maevsi:table_legal_term to pg --- requires: schema_public --- requires: role_account --- requires: role_anonymous - BEGIN; CREATE TABLE maevsi.legal_term ( diff --git a/src/deploy/table_legal_term_acceptance.sql b/src/deploy/table_legal_term_acceptance.sql index 09239094..7a79d8e8 100644 --- a/src/deploy/table_legal_term_acceptance.sql +++ b/src/deploy/table_legal_term_acceptance.sql @@ -1,9 +1,3 @@ --- Deploy maevsi:table_legal_term_acceptance to pg --- requires: schema_public --- requires: table_account_public --- requires: table_legal_term --- requires: role_account - BEGIN; CREATE TABLE maevsi.legal_term_acceptance ( @@ -14,7 +8,7 @@ CREATE TABLE maevsi.legal_term_acceptance ( legal_term_id UUID NOT NULL REFERENCES maevsi.legal_term(id) ON DELETE RESTRICT -- deletion of the parent row should not be possible ); -COMMENT ON TABLE maevsi.legal_term_acceptance IS 'Tracks each user account''s acceptance of legal terms and conditions.'; +COMMENT ON TABLE maevsi.legal_term_acceptance IS '@omit update,delete\nTracks each user account''s acceptance of legal terms and conditions.'; COMMENT ON COLUMN maevsi.legal_term_acceptance.id IS E'@omit create\nUnique identifier for this legal term acceptance record. Automatically generated for each new acceptance.'; COMMENT ON COLUMN maevsi.legal_term_acceptance.created_at IS E'@omit create\nTimestamp showing when the legal terms were accepted, set automatically at the time of acceptance.'; COMMENT ON COLUMN maevsi.legal_term_acceptance.account_id IS 'The user account ID that accepted the legal terms. If the account is deleted, this acceptance record will also be deleted.'; @@ -26,15 +20,15 @@ ALTER TABLE maevsi.legal_term_acceptance ENABLE ROW LEVEL SECURITY; -- Allow to select legal term acceptances for the own account. CREATE POLICY legal_term_acceptance_select ON maevsi.legal_term_acceptance FOR SELECT USING ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + account_id = maevsi.invoker_account_id() ); CREATE POLICY legal_term_acceptance_insert ON maevsi.legal_term_acceptance FOR INSERT WITH CHECK ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + account_id = maevsi.invoker_account_id() ); COMMIT; diff --git a/src/deploy/table_notification.sql b/src/deploy/table_notification.sql index b6050e4c..ba24446b 100644 --- a/src/deploy/table_notification.sql +++ b/src/deploy/table_notification.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:table_event to pg --- requires: schema_private - BEGIN; CREATE TABLE maevsi_private.notification ( @@ -8,7 +5,7 @@ CREATE TABLE maevsi_private.notification ( channel TEXT NOT NULL, is_acknowledged BOOLEAN, payload TEXT NOT NULL CHECK (octet_length(payload) <= 8000), - "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() + "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP ); COMMENT ON TABLE maevsi_private.notification IS 'A notification.'; diff --git a/src/deploy/table_profile_picture.sql b/src/deploy/table_profile_picture.sql index 8757f655..65b1b07d 100644 --- a/src/deploy/table_profile_picture.sql +++ b/src/deploy/table_profile_picture.sql @@ -1,11 +1,3 @@ --- Deploy maevsi:table_profile_picture to pg --- requires: schema_public --- requires: table_account_public --- requires: table_upload --- requires: role_account --- requires: role_anonymous --- requires: role_tusd - BEGIN; CREATE TABLE maevsi.profile_picture ( @@ -32,16 +24,16 @@ CREATE POLICY profile_picture_select ON maevsi.profile_picture FOR SELECT USING -- Only allow inserts with a account id that matches the invoker's account id. CREATE POLICY profile_picture_insert ON maevsi.profile_picture FOR INSERT WITH CHECK ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + account_id = maevsi.invoker_account_id() ); -- Only allow updates to the item with the account id that matches the invoker's account id. CREATE POLICY profile_picture_update ON maevsi.profile_picture FOR UPDATE USING ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + account_id = maevsi.invoker_account_id() ); -- Only allow deletes for the item with the account id that matches the invoker's account id. @@ -49,9 +41,9 @@ CREATE POLICY profile_picture_delete ON maevsi.profile_picture FOR DELETE USING (SELECT current_user) = 'maevsi_tusd' OR ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + account_id = maevsi.invoker_account_id() ) ); diff --git a/src/deploy/table_report.sql b/src/deploy/table_report.sql index 1fd3b343..820af755 100644 --- a/src/deploy/table_report.sql +++ b/src/deploy/table_report.sql @@ -1,19 +1,14 @@ --- Deploy maevsi:table_report to pg --- requires: schema_public --- requires: table_account_public --- requires: table_event --- requires: table_upload - BEGIN; CREATE TABLE maevsi.report ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + author_account_id UUID NOT NULL REFERENCES maevsi.account(id), reason TEXT NOT NULL CHECK (char_length("reason") > 0 AND char_length("reason") < 2000), target_account_id UUID REFERENCES maevsi.account(id), target_event_id UUID REFERENCES maevsi.event(id), target_upload_id UUID REFERENCES maevsi.upload(id), - created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, CHECK (num_nonnulls(target_account_id, target_event_id, target_upload_id) = 1), UNIQUE (author_account_id, target_account_id, target_event_id, target_upload_id) @@ -21,12 +16,12 @@ CREATE TABLE maevsi.report ( COMMENT ON TABLE maevsi.report IS E'@omit update,delete\nStores reports made by users on other users, events, or uploads for moderation purposes.'; COMMENT ON COLUMN maevsi.report.id IS E'@omit create\nUnique identifier for the report, generated randomly using UUIDs.'; +COMMENT ON COLUMN maevsi.report.created_at IS E'@omit create\nTimestamp of when the report was created, defaults to the current timestamp.'; COMMENT ON COLUMN maevsi.report.author_account_id IS 'The ID of the user who created the report.'; COMMENT ON COLUMN maevsi.report.reason IS 'The reason for the report, provided by the reporting user. Must be non-empty and less than 2000 characters.'; COMMENT ON COLUMN maevsi.report.target_account_id IS 'The ID of the account being reported, if applicable.'; COMMENT ON COLUMN maevsi.report.target_event_id IS 'The ID of the event being reported, if applicable.'; COMMENT ON COLUMN maevsi.report.target_upload_id IS 'The ID of the upload being reported, if applicable.'; -COMMENT ON COLUMN maevsi.report.created_at IS E'@omit create\nTimestamp of when the report was created, defaults to the current timestamp.'; COMMENT ON CONSTRAINT report_reason_check ON maevsi.report IS 'Ensures the reason field contains between 1 and 2000 characters.'; COMMENT ON CONSTRAINT report_check ON maevsi.report IS 'Ensures that the report targets exactly one element (account, event, or upload).'; COMMENT ON CONSTRAINT report_author_account_id_target_account_id_target_event_id__key ON maevsi.report IS 'Ensures that the same user cannot submit multiple reports on the same element (account, event, or upload).'; diff --git a/src/deploy/table_report_policy.sql b/src/deploy/table_report_policy.sql index c330a8b9..a1cad560 100644 --- a/src/deploy/table_report_policy.sql +++ b/src/deploy/table_report_policy.sql @@ -1,8 +1,3 @@ --- Deploy maevsi:table_report_policy to pg --- requires: schema_public --- requires: table_report --- requires: role_account - BEGIN; GRANT INSERT, SELECT ON TABLE maevsi.report TO maevsi_account; @@ -11,16 +6,16 @@ ALTER TABLE maevsi.report ENABLE ROW LEVEL SECURITY; -- Only allow inserts for reports authored by the current user. CREATE POLICY report_insert ON maevsi.report FOR INSERT WITH CHECK ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + author_account_id = maevsi.invoker_account_id() ); -- Only allow selects for reports authored by the current user. CREATE POLICY report_select ON maevsi.report FOR SELECT USING ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + author_account_id = maevsi.invoker_account_id() ); COMMIT; diff --git a/src/deploy/table_upload.sql b/src/deploy/table_upload.sql index 7949dbc6..cf7e52c4 100644 --- a/src/deploy/table_upload.sql +++ b/src/deploy/table_upload.sql @@ -1,20 +1,23 @@ --- Deploy maevsi:table_event to pg --- requires: schema_public --- requires: table_account_public - BEGIN; CREATE TABLE maevsi.upload ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + account_id UUID NOT NULL REFERENCES maevsi.account(id), + name TEXT CHECK (char_length("name") > 0 AND char_length("name") < 300), size_byte BIGINT NOT NULL CHECK (size_byte > 0), - storage_key TEXT UNIQUE + storage_key TEXT UNIQUE, + type TEXT NOT NULL DEFAULT 'image' ); COMMENT ON TABLE maevsi.upload IS 'An upload.'; COMMENT ON COLUMN maevsi.upload.id IS E'@omit create,update\nThe upload''s internal id.'; +COMMENT ON COLUMN maevsi.upload.created_at IS E'@omit create,update\nTimestamp of when the upload was created, defaults to the current timestamp.'; COMMENT ON COLUMN maevsi.upload.account_id IS 'The uploader''s account id.'; +COMMENT ON COLUMN maevsi.upload.name IS 'The name of the uploaded file.'; COMMENT ON COLUMN maevsi.upload.size_byte IS 'The upload''s size in bytes.'; COMMENT ON COLUMN maevsi.upload.storage_key IS 'The upload''s storage key.'; +COMMENT ON COLUMN maevsi.upload.type IS 'The type of the uploaded file, default is ''image''.'; COMMIT; diff --git a/src/deploy/table_upload_policy.sql b/src/deploy/table_upload_policy.sql index f3c3691b..d573d8b9 100644 --- a/src/deploy/table_upload_policy.sql +++ b/src/deploy/table_upload_policy.sql @@ -1,10 +1,3 @@ --- Deploy maevsi:table_event to pg --- requires: schema_public --- requires: table_upload --- requires: role_account --- requires: role_anonymous --- requires: role_tusd - BEGIN; GRANT SELECT ON TABLE maevsi.upload TO maevsi_account, maevsi_anonymous, maevsi_tusd; @@ -21,9 +14,9 @@ CREATE POLICY upload_select_using ON maevsi.upload FOR SELECT USING ( (SELECT current_user) = 'maevsi_tusd' OR ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + account_id = maevsi.invoker_account_id() ) OR id IN (SELECT upload_id FROM maevsi.profile_picture) diff --git a/src/deploy/type_event_unlock_response.sql b/src/deploy/type_event_unlock_response.sql index be57ef04..c3ab338a 100644 --- a/src/deploy/type_event_unlock_response.sql +++ b/src/deploy/type_event_unlock_response.sql @@ -1,7 +1,3 @@ --- Deploy maevsi:type_event_unlock_response to pg --- requires: schema_public --- requires: type_jwt - BEGIN; -- TODO: remove type diff --git a/src/deploy/type_jwt.sql b/src/deploy/type_jwt.sql index 391118ae..6721fb21 100644 --- a/src/deploy/type_jwt.sql +++ b/src/deploy/type_jwt.sql @@ -1,6 +1,3 @@ --- Deploy maevsi:type_jwt to pg --- requires: schema_public - BEGIN; CREATE TYPE maevsi.jwt AS ( diff --git a/src/deploy/view_invitation_flat.sql b/src/deploy/view_invitation_flat.sql new file mode 100644 index 00000000..a9be71af --- /dev/null +++ b/src/deploy/view_invitation_flat.sql @@ -0,0 +1,43 @@ +BEGIN; +CREATE VIEW maevsi.invitation_flat WITH (security_invoker) AS + SELECT + invitation.id AS invitation_id, + invitation.contact_id AS invitation_contact_id, + invitation.event_id AS invitation_event_id, + invitation.feedback AS invitation_feedback, + invitation.feedback_paper AS invitation_feedback_paper, + + contact.id AS contact_id, + contact.account_id AS contact_account_id, + contact.address AS contact_address, + contact.author_account_id AS contact_author_account_id, + contact.email_address AS contact_email_address, + contact.email_address_hash AS contact_email_address_hash, + contact.first_name AS contact_first_name , + contact.last_name AS contact_last_name, + contact.phone_number AS contact_phone_number, + contact.url AS contact_url, + + event.id AS event_id, + event.author_account_id AS event_author_account_id, + event.description AS event_description, + event.start AS event_start, + event.end AS event_end, + event.invitee_count_maximum AS event_invitee_count_maximum, + event.is_archived AS event_is_archived, + event.is_in_person AS event_is_in_person, + event.is_remote AS event_is_remote, + event.location AS event_location, + event.name AS event_name, + event.slug AS event_slug, + event.url AS event_url, + event.visibility AS event_visibility + FROM maevsi.invitation + JOIN maevsi.contact ON invitation.contact_id = contact.id + JOIN maevsi.event ON invitation.event_id = event.id; + +COMMENT ON VIEW maevsi.invitation_flat IS 'View returning flattened invitations.'; + +GRANT SELECT ON maevsi.invitation_flat TO maevsi_account, maevsi_anonymous; + +END; diff --git a/src/revert/database_grafana.sql b/src/revert/database_grafana.sql index bf0c67c0..b4229d9e 100644 --- a/src/revert/database_grafana.sql +++ b/src/revert/database_grafana.sql @@ -1,3 +1 @@ --- Revert maevsi:database_grafana from pg - DROP DATABASE grafana WITH (FORCE); diff --git a/src/revert/enum_achievement_type.sql b/src/revert/enum_achievement_type.sql index 7a4c17d5..2b6351e3 100644 --- a/src/revert/enum_achievement_type.sql +++ b/src/revert/enum_achievement_type.sql @@ -1,5 +1,3 @@ --- Revert maevsi:enum_achievement_type from pg - BEGIN; DROP TYPE maevsi.achievement_type; diff --git a/src/revert/enum_event_size.sql b/src/revert/enum_event_size.sql new file mode 100644 index 00000000..21b19e74 --- /dev/null +++ b/src/revert/enum_event_size.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TYPE maevsi.event_size; + +COMMIT; diff --git a/src/revert/enum_event_visibility.sql b/src/revert/enum_event_visibility.sql index 53bbb300..c68614b7 100644 --- a/src/revert/enum_event_visibility.sql +++ b/src/revert/enum_event_visibility.sql @@ -1,5 +1,3 @@ --- Revert maevsi:enum_event_visibility from pg - BEGIN; DROP TYPE maevsi.event_visibility; diff --git a/src/revert/enum_invitation_feedback.sql b/src/revert/enum_invitation_feedback.sql index f4e3e4e1..4963783e 100644 --- a/src/revert/enum_invitation_feedback.sql +++ b/src/revert/enum_invitation_feedback.sql @@ -1,5 +1,3 @@ --- Revert maevsi:enum_invitation_feedback from pg - BEGIN; DROP TYPE maevsi.invitation_feedback; diff --git a/src/revert/enum_invitation_feedback_paper.sql b/src/revert/enum_invitation_feedback_paper.sql index db49f019..b75f81c0 100644 --- a/src/revert/enum_invitation_feedback_paper.sql +++ b/src/revert/enum_invitation_feedback_paper.sql @@ -1,5 +1,3 @@ --- Revert maevsi:enum_paper_invitation_feedback from pg - BEGIN; DROP TYPE maevsi.invitation_feedback_paper; diff --git a/src/revert/enum_language.sql b/src/revert/enum_language.sql new file mode 100644 index 00000000..328d537b --- /dev/null +++ b/src/revert/enum_language.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TYPE maevsi.language; + +COMMIT; diff --git a/src/revert/enum_social_network.sql b/src/revert/enum_social_network.sql new file mode 100644 index 00000000..418c38a0 --- /dev/null +++ b/src/revert/enum_social_network.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TYPE maevsi.social_network; + +COMMIT; diff --git a/src/revert/extension_pgcrypto.sql b/src/revert/extension_pgcrypto.sql index 7c5a26a7..52fd7c5c 100644 --- a/src/revert/extension_pgcrypto.sql +++ b/src/revert/extension_pgcrypto.sql @@ -1,5 +1,3 @@ --- Revert maevsi:extension_pgcrypto from pg - BEGIN; DROP EXTENSION pgcrypto; diff --git a/src/revert/function_account_delete.sql b/src/revert/function_account_delete.sql index 834cb211..428cc715 100644 --- a/src/revert/function_account_delete.sql +++ b/src/revert/function_account_delete.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_account_delete from pg - BEGIN; DROP FUNCTION maevsi.account_delete; diff --git a/src/revert/function_account_email_address_verification.sql b/src/revert/function_account_email_address_verification.sql index c06da189..752433bf 100644 --- a/src/revert/function_account_email_address_verification.sql +++ b/src/revert/function_account_email_address_verification.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_account_email_address_verification from pg - BEGIN; DROP FUNCTION maevsi.account_email_address_verification; diff --git a/src/revert/function_account_password_change.sql b/src/revert/function_account_password_change.sql index ddb2d608..44d12043 100644 --- a/src/revert/function_account_password_change.sql +++ b/src/revert/function_account_password_change.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_account_password_change from pg - BEGIN; DROP FUNCTION maevsi.account_password_change; diff --git a/src/revert/function_account_password_reset.sql b/src/revert/function_account_password_reset.sql index 76d2c6a4..ea6a50bc 100644 --- a/src/revert/function_account_password_reset.sql +++ b/src/revert/function_account_password_reset.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_account_password_reset from pg - BEGIN; DROP FUNCTION maevsi.account_password_reset; diff --git a/src/revert/function_account_password_reset_request.sql b/src/revert/function_account_password_reset_request.sql index bbe7aca5..2fa920f8 100644 --- a/src/revert/function_account_password_reset_request.sql +++ b/src/revert/function_account_password_reset_request.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_account_password_reset_request from pg - BEGIN; DROP FUNCTION maevsi.account_password_reset_request; diff --git a/src/revert/function_account_registration.sql b/src/revert/function_account_registration.sql index b5d5045c..789d9b7f 100644 --- a/src/revert/function_account_registration.sql +++ b/src/revert/function_account_registration.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_account_registration from pg - BEGIN; DROP FUNCTION maevsi.account_registration; diff --git a/src/revert/function_account_registration_refresh.sql b/src/revert/function_account_registration_refresh.sql index 27f20cb1..a402c1aa 100644 --- a/src/revert/function_account_registration_refresh.sql +++ b/src/revert/function_account_registration_refresh.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_account_registration_refresh from pg - BEGIN; DROP FUNCTION maevsi.account_registration_refresh; diff --git a/src/revert/function_account_upload_quota_bytes.sql b/src/revert/function_account_upload_quota_bytes.sql index c8c5ebc9..205466a7 100644 --- a/src/revert/function_account_upload_quota_bytes.sql +++ b/src/revert/function_account_upload_quota_bytes.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_account_upload_quota_bytes from pg - BEGIN; DROP FUNCTION maevsi.account_upload_quota_bytes; diff --git a/src/revert/function_achievement_unlock.sql b/src/revert/function_achievement_unlock.sql index 38a4f0ae..d2372760 100644 --- a/src/revert/function_achievement_unlock.sql +++ b/src/revert/function_achievement_unlock.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_achievement_unlock from pg - BEGIN; DROP FUNCTION maevsi.achievement_unlock; diff --git a/src/revert/function_authenticate.sql b/src/revert/function_authenticate.sql index 2151da6f..94dea8f7 100644 --- a/src/revert/function_authenticate.sql +++ b/src/revert/function_authenticate.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_authenticate from pg - BEGIN; DROP FUNCTION maevsi.authenticate; diff --git a/src/revert/function_event_delete.sql b/src/revert/function_event_delete.sql index 2c8c7f75..b8172a1c 100644 --- a/src/revert/function_event_delete.sql +++ b/src/revert/function_event_delete.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_event_delete from pg - BEGIN; DROP FUNCTION maevsi.event_delete; diff --git a/src/revert/function_event_invitee_count_maximum.sql b/src/revert/function_event_invitee_count_maximum.sql index df59199d..1cd8a47a 100644 --- a/src/revert/function_event_invitee_count_maximum.sql +++ b/src/revert/function_event_invitee_count_maximum.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_event_invitee_count_maximum from pg - BEGIN; DROP FUNCTION maevsi.event_invitee_count_maximum; diff --git a/src/revert/function_event_is_existing.sql b/src/revert/function_event_is_existing.sql index 8d54daa3..72be1ce0 100644 --- a/src/revert/function_event_is_existing.sql +++ b/src/revert/function_event_is_existing.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_event_is_existing from pg - BEGIN; DROP FUNCTION maevsi.event_is_existing; diff --git a/src/revert/function_event_unlock.sql b/src/revert/function_event_unlock.sql index dc443148..5b1a6302 100644 --- a/src/revert/function_event_unlock.sql +++ b/src/revert/function_event_unlock.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_event_unlock from pg - BEGIN; DROP FUNCTION maevsi.event_unlock; diff --git a/src/revert/function_events_invited.sql b/src/revert/function_events_invited.sql index 719d21f2..2ae2dbc0 100644 --- a/src/revert/function_events_invited.sql +++ b/src/revert/function_events_invited.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_events_invited from pg - BEGIN; DROP FUNCTION maevsi_private.events_invited; diff --git a/src/revert/function_events_organized.sql b/src/revert/function_events_organized.sql index 8817f7f7..f588f241 100644 --- a/src/revert/function_events_organized.sql +++ b/src/revert/function_events_organized.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_events_organized from pg - BEGIN; DROP FUNCTION maevsi.events_organized; diff --git a/src/revert/function_invitation_claim_array.sql b/src/revert/function_invitation_claim_array.sql index 35671f45..ec234c7f 100644 --- a/src/revert/function_invitation_claim_array.sql +++ b/src/revert/function_invitation_claim_array.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_invitation_claim_array from pg - BEGIN; DROP FUNCTION maevsi.invitation_claim_array(); diff --git a/src/revert/function_invitation_contact_ids.sql b/src/revert/function_invitation_contact_ids.sql index e69b332c..28a25aa8 100644 --- a/src/revert/function_invitation_contact_ids.sql +++ b/src/revert/function_invitation_contact_ids.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_invitation_contact_ids from pg - BEGIN; DROP FUNCTION maevsi.invitation_contact_ids; diff --git a/src/revert/function_invite.sql b/src/revert/function_invite.sql index 9aeaa3d5..747ed328 100644 --- a/src/revert/function_invite.sql +++ b/src/revert/function_invite.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_invite from pg - BEGIN; DROP FUNCTION maevsi.invite; diff --git a/src/revert/function_invitee_count.sql b/src/revert/function_invitee_count.sql index 6cc780a2..4cd17e31 100644 --- a/src/revert/function_invitee_count.sql +++ b/src/revert/function_invitee_count.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_invitee_count from pg - BEGIN; DROP FUNCTION maevsi.invitee_count; diff --git a/src/revert/function_invoker_account_id.sql b/src/revert/function_invoker_account_id.sql new file mode 100644 index 00000000..d20fbd7c --- /dev/null +++ b/src/revert/function_invoker_account_id.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP FUNCTION maevsi.invoker_account_id; + +COMMIT; diff --git a/src/revert/function_jwt_refresh.sql b/src/revert/function_jwt_refresh.sql index f6767d37..11a70ca6 100644 --- a/src/revert/function_jwt_refresh.sql +++ b/src/revert/function_jwt_refresh.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_jwt_refresh from pg - BEGIN; DROP FUNCTION maevsi.jwt_refresh; diff --git a/src/revert/function_notification_acknowledge.sql b/src/revert/function_notification_acknowledge.sql index b47d2487..0bd570fd 100644 --- a/src/revert/function_notification_acknowledge.sql +++ b/src/revert/function_notification_acknowledge.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_notification_acknowledge from pg - BEGIN; DROP FUNCTION maevsi.notification_acknowledge; diff --git a/src/revert/function_profile_picture_set.sql b/src/revert/function_profile_picture_set.sql index 0cd41c58..be7e68a9 100644 --- a/src/revert/function_profile_picture_set.sql +++ b/src/revert/function_profile_picture_set.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_profile_picture_set from pg - BEGIN; DROP FUNCTION maevsi.profile_picture_set; diff --git a/src/revert/function_upload_create.sql b/src/revert/function_upload_create.sql index 0497894a..47722b1e 100644 --- a/src/revert/function_upload_create.sql +++ b/src/revert/function_upload_create.sql @@ -1,5 +1,3 @@ --- Revert maevsi:function_upload_create from pg - BEGIN; DROP FUNCTION maevsi.upload_create; diff --git a/src/revert/index_event_author_username.sql b/src/revert/index_event_author_username.sql index 9e06d129..aedea681 100644 --- a/src/revert/index_event_author_username.sql +++ b/src/revert/index_event_author_username.sql @@ -1,5 +1,3 @@ --- Revert maevsi:index_event_author_account_id from pg - BEGIN; DROP INDEX maevsi.idx_event_author_account_id; diff --git a/src/revert/index_event_group_author_username.sql b/src/revert/index_event_group_author_username.sql index 3e9d032d..b1917682 100644 --- a/src/revert/index_event_group_author_username.sql +++ b/src/revert/index_event_group_author_username.sql @@ -1,5 +1,3 @@ --- Revert maevsi:index_event_group_author_account_id from pg - BEGIN; DROP INDEX maevsi.idx_event_group_author_account_id; diff --git a/src/revert/index_event_grouping_event_group_id.sql b/src/revert/index_event_grouping_event_group_id.sql index 7b664369..12fa6c00 100644 --- a/src/revert/index_event_grouping_event_group_id.sql +++ b/src/revert/index_event_grouping_event_group_id.sql @@ -1,5 +1,3 @@ --- Revert maevsi:index_event_grouping_event_group_id from pg - BEGIN; DROP INDEX maevsi.idx_event_grouping_event_group_id; diff --git a/src/revert/index_event_grouping_event_id.sql b/src/revert/index_event_grouping_event_id.sql index 82117a0b..ce5d392e 100644 --- a/src/revert/index_event_grouping_event_id.sql +++ b/src/revert/index_event_grouping_event_id.sql @@ -1,5 +1,3 @@ --- Revert maevsi:index_event_grouping_event_id from pg - BEGIN; DROP INDEX maevsi.idx_event_grouping_event_id; diff --git a/src/revert/index_invitation_contact_id.sql b/src/revert/index_invitation_contact_id.sql index 4beab183..5f77296f 100644 --- a/src/revert/index_invitation_contact_id.sql +++ b/src/revert/index_invitation_contact_id.sql @@ -1,5 +1,3 @@ --- Revert maevsi:index_invitation_contact_id from pg - BEGIN; DROP INDEX maevsi.idx_invitation_contact_id; diff --git a/src/revert/index_invitation_event_id.sql b/src/revert/index_invitation_event_id.sql index 77bca5f0..1d1a29d6 100644 --- a/src/revert/index_invitation_event_id.sql +++ b/src/revert/index_invitation_event_id.sql @@ -1,5 +1,3 @@ --- Revert maevsi:index_invitation_event_id from pg - BEGIN; DROP INDEX maevsi.idx_invitation_event_id; diff --git a/src/revert/privilege_execute_revoke.sql b/src/revert/privilege_execute_revoke.sql index f400687e..90cb7960 100644 --- a/src/revert/privilege_execute_revoke.sql +++ b/src/revert/privilege_execute_revoke.sql @@ -1,5 +1,3 @@ --- Revert maevsi:privilege_execute_revoke from pg - BEGIN; ALTER DEFAULT PRIVILEGES GRANT EXECUTE ON FUNCTIONS TO PUBLIC; diff --git a/src/revert/role_account.sql b/src/revert/role_account.sql index 94525d14..127d8b68 100644 --- a/src/revert/role_account.sql +++ b/src/revert/role_account.sql @@ -1,5 +1,3 @@ --- Revert maevsi:role_account from pg - BEGIN; DROP ROLE maevsi_account; diff --git a/src/revert/role_anonymous.sql b/src/revert/role_anonymous.sql index 38f534db..f903c5d2 100644 --- a/src/revert/role_anonymous.sql +++ b/src/revert/role_anonymous.sql @@ -1,5 +1,3 @@ --- Revert maevsi:role_anonymous from pg - BEGIN; DROP ROLE maevsi_anonymous; diff --git a/src/revert/role_grafana.sql b/src/revert/role_grafana.sql index 0ea7b5b0..c52617ed 100644 --- a/src/revert/role_grafana.sql +++ b/src/revert/role_grafana.sql @@ -1,5 +1,3 @@ --- Revert maevsi:role_grafana from pg - \connect grafana BEGIN; diff --git a/src/revert/role_postgraphile.sql b/src/revert/role_postgraphile.sql index 856d191f..cf46f8e2 100644 --- a/src/revert/role_postgraphile.sql +++ b/src/revert/role_postgraphile.sql @@ -1,5 +1,3 @@ --- Revert maevsi:role_postgraphile from pg - BEGIN; DROP OWNED BY maevsi_postgraphile; diff --git a/src/revert/role_tusd.sql b/src/revert/role_tusd.sql index 16f6f706..334783d5 100644 --- a/src/revert/role_tusd.sql +++ b/src/revert/role_tusd.sql @@ -1,5 +1,3 @@ --- Revert maevsi:role_tusd from pg - BEGIN; DROP OWNED BY maevsi_tusd; diff --git a/src/revert/schema_private.sql b/src/revert/schema_private.sql index 54b0fd75..baf6816f 100644 --- a/src/revert/schema_private.sql +++ b/src/revert/schema_private.sql @@ -1,5 +1,3 @@ --- Revert maevsi:schema_private from pg - BEGIN; DROP SCHEMA maevsi_private; diff --git a/src/revert/schema_public.sql b/src/revert/schema_public.sql index 34724032..542da575 100644 --- a/src/revert/schema_public.sql +++ b/src/revert/schema_public.sql @@ -1,5 +1,3 @@ --- Revert maevsi:schema_public from pg - BEGIN; DROP SCHEMA maevsi; diff --git a/src/revert/table_account_block.sql b/src/revert/table_account_block.sql index 77d764a7..57b147d3 100644 --- a/src/revert/table_account_block.sql +++ b/src/revert/table_account_block.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_account_block from pg - BEGIN; DROP TABLE maevsi.account_block; diff --git a/src/revert/table_account_block_policy.sql b/src/revert/table_account_block_policy.sql index a2efadb3..c2a68ed8 100644 --- a/src/revert/table_account_block_policy.sql +++ b/src/revert/table_account_block_policy.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_account_block_policy from pg - BEGIN; DROP POLICY account_block_insert ON maevsi.account_block; diff --git a/src/revert/table_account_interest.sql b/src/revert/table_account_interest.sql new file mode 100644 index 00000000..1359236b --- /dev/null +++ b/src/revert/table_account_interest.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TABLE maevsi.account_interest; + +COMMIT; diff --git a/src/revert/table_account_interest_policy.sql b/src/revert/table_account_interest_policy.sql new file mode 100644 index 00000000..b2604c7e --- /dev/null +++ b/src/revert/table_account_interest_policy.sql @@ -0,0 +1,7 @@ +BEGIN; + +DROP POLICY account_interest_select ON maevsi.account_interest; +DROP POLICY account_interest_insert ON maevsi.account_interest; +DROP POLICY account_interest_delete ON maevsi.account_interest; + +COMMIT; diff --git a/src/revert/table_account_preference_event_size.sql b/src/revert/table_account_preference_event_size.sql new file mode 100644 index 00000000..2789e92f --- /dev/null +++ b/src/revert/table_account_preference_event_size.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TABLE maevsi.account_preference_event_size; + +COMMIT; diff --git a/src/revert/table_account_preference_event_size_policy.sql b/src/revert/table_account_preference_event_size_policy.sql new file mode 100644 index 00000000..36b32c3b --- /dev/null +++ b/src/revert/table_account_preference_event_size_policy.sql @@ -0,0 +1,7 @@ +BEGIN; + +DROP POLICY account_preference_event_size_select ON maevsi.account_preference_event_size; +DROP POLICY account_preference_event_size_insert ON maevsi.account_preference_event_size; +DROP POLICY account_preference_event_size_delete ON maevsi.account_preference_event_size; + +COMMIT; diff --git a/src/revert/table_account_private.sql b/src/revert/table_account_private.sql index d2dd4b12..dd74a4d0 100644 --- a/src/revert/table_account_private.sql +++ b/src/revert/table_account_private.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_account_private from pg - BEGIN; DROP TRIGGER maevsi_private_account_password_reset_verification_valid_until ON maevsi_private.account; diff --git a/src/revert/table_account_public.sql b/src/revert/table_account_public.sql index 877a5669..cc12edbf 100644 --- a/src/revert/table_account_public.sql +++ b/src/revert/table_account_public.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_account_public from pg - BEGIN; DROP TABLE maevsi.account; diff --git a/src/revert/table_account_social_network.sql b/src/revert/table_account_social_network.sql new file mode 100644 index 00000000..fd426820 --- /dev/null +++ b/src/revert/table_account_social_network.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TABLE maevsi.account_social_network ; + +COMMIT; diff --git a/src/revert/table_account_social_network_policy.sql b/src/revert/table_account_social_network_policy.sql new file mode 100644 index 00000000..740760f0 --- /dev/null +++ b/src/revert/table_account_social_network_policy.sql @@ -0,0 +1,7 @@ +BEGIN; + +DROP POLICY account_social_network_insert ON maevsi.account_social_network; +DROP POLICY account_social_network_update ON maevsi.account_social_network; +DROP POLICY account_social_network_delete ON maevsi.account_social_network; + +COMMIT; diff --git a/src/revert/table_achievement.sql b/src/revert/table_achievement.sql index e1a5ac02..9e715529 100644 --- a/src/revert/table_achievement.sql +++ b/src/revert/table_achievement.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_achievement from pg - BEGIN; DROP POLICY achievement_select ON maevsi.achievement; diff --git a/src/revert/table_achievement_code.sql b/src/revert/table_achievement_code.sql index fc98a23e..5583eec2 100644 --- a/src/revert/table_achievement_code.sql +++ b/src/revert/table_achievement_code.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_achievement_code from pg - BEGIN; DROP TABLE maevsi_private.achievement_code; diff --git a/src/revert/table_contact.sql b/src/revert/table_contact.sql index 695466eb..2e74c355 100644 --- a/src/revert/table_contact.sql +++ b/src/revert/table_contact.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_contact from pg - BEGIN; DROP TRIGGER maevsi_trigger_contact_update_account_id ON maevsi.contact; diff --git a/src/revert/table_contact_policy.sql b/src/revert/table_contact_policy.sql index 43b6f062..a1da8c27 100644 --- a/src/revert/table_contact_policy.sql +++ b/src/revert/table_contact_policy.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_contact_policy from pg - BEGIN; DROP POLICY contact_delete ON maevsi.contact; diff --git a/src/revert/table_event.sql b/src/revert/table_event.sql index e15d40c5..abefa8d0 100644 --- a/src/revert/table_event.sql +++ b/src/revert/table_event.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_event from pg - BEGIN; DROP TABLE maevsi.event; diff --git a/src/revert/table_event_category.sql b/src/revert/table_event_category.sql new file mode 100644 index 00000000..11c54528 --- /dev/null +++ b/src/revert/table_event_category.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TABLE maevsi.event_category; + +COMMIT; diff --git a/src/revert/table_event_category_mapping.sql b/src/revert/table_event_category_mapping.sql new file mode 100644 index 00000000..c0104d8f --- /dev/null +++ b/src/revert/table_event_category_mapping.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TABLE maevsi.event_category_mapping; + +COMMIT; diff --git a/src/revert/table_event_category_mapping_policy.sql b/src/revert/table_event_category_mapping_policy.sql new file mode 100644 index 00000000..07325561 --- /dev/null +++ b/src/revert/table_event_category_mapping_policy.sql @@ -0,0 +1,7 @@ +BEGIN; + +DROP POLICY event_category_mapping_select ON maevsi.event_category_mapping; +DROP POLICY event_category_mapping_insert ON maevsi.event_category_mapping; +DROP POLICY event_category_mapping_delete ON maevsi.event_category_mapping; + +COMMIT; diff --git a/src/revert/table_event_category_policy.sql b/src/revert/table_event_category_policy.sql new file mode 100644 index 00000000..c4c4836d --- /dev/null +++ b/src/revert/table_event_category_policy.sql @@ -0,0 +1,3 @@ +BEGIN; + +COMMIT; diff --git a/src/revert/table_event_favourite.sql b/src/revert/table_event_favourite.sql new file mode 100644 index 00000000..b6948718 --- /dev/null +++ b/src/revert/table_event_favourite.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TABLE maevsi.event_favourite; + +COMMIT; diff --git a/src/revert/table_event_favourite_policy.sql b/src/revert/table_event_favourite_policy.sql new file mode 100644 index 00000000..57626801 --- /dev/null +++ b/src/revert/table_event_favourite_policy.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP POLICY event_favourite_select ON maevsi.event_favourite; + +COMMIT; diff --git a/src/revert/table_event_group.sql b/src/revert/table_event_group.sql index 93892a95..01bf43c0 100644 --- a/src/revert/table_event_group.sql +++ b/src/revert/table_event_group.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_event_group from pg - BEGIN; DROP TABLE maevsi.event_group; diff --git a/src/revert/table_event_grouping.sql b/src/revert/table_event_grouping.sql index 93563327..fa5d1aaa 100644 --- a/src/revert/table_event_grouping.sql +++ b/src/revert/table_event_grouping.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_event_grouping from pg - BEGIN; DROP TABLE maevsi.event_grouping; diff --git a/src/revert/table_event_policy.sql b/src/revert/table_event_policy.sql index e6dca1c2..bb9918bb 100644 --- a/src/revert/table_event_policy.sql +++ b/src/revert/table_event_policy.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_event_policy from pg - BEGIN; DROP POLICY event_update ON maevsi.event; diff --git a/src/revert/table_event_recommendation.sql b/src/revert/table_event_recommendation.sql new file mode 100644 index 00000000..58928388 --- /dev/null +++ b/src/revert/table_event_recommendation.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TABLE maevsi.event_recommendation; + +COMMIT; diff --git a/src/revert/table_event_recommendation_policy.sql b/src/revert/table_event_recommendation_policy.sql new file mode 100644 index 00000000..2d38bd4b --- /dev/null +++ b/src/revert/table_event_recommendation_policy.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP POLICY event_recommendation_select ON maevsi.event_recommendation; + +COMMIT; diff --git a/src/revert/table_event_upload.sql b/src/revert/table_event_upload.sql new file mode 100644 index 00000000..b8e71493 --- /dev/null +++ b/src/revert/table_event_upload.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TABLE maevsi.event_upload; + +COMMIT; diff --git a/src/revert/table_event_upload_policy.sql b/src/revert/table_event_upload_policy.sql new file mode 100644 index 00000000..b88850a2 --- /dev/null +++ b/src/revert/table_event_upload_policy.sql @@ -0,0 +1,7 @@ +BEGIN; + +DROP POLICY event_upload_select ON maevsi.event_upload; +DROP POLICY event_upload_insert ON maevsi.event_upload; +DROP POLICY event_upload_delete ON maevsi.event_upload; + +COMMIT; diff --git a/src/revert/table_invitation.sql b/src/revert/table_invitation.sql index f0517aaf..82cd0bee 100644 --- a/src/revert/table_invitation.sql +++ b/src/revert/table_invitation.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_invitation from pg - BEGIN; DROP TABLE maevsi.invitation; diff --git a/src/revert/table_invitation_policy.sql b/src/revert/table_invitation_policy.sql index 36c59dc3..e0d151b4 100644 --- a/src/revert/table_invitation_policy.sql +++ b/src/revert/table_invitation_policy.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_invitation_policy from pg - BEGIN; DROP TRIGGER maevsi_invitation_update ON maevsi.invitation; diff --git a/src/revert/table_jwt.sql b/src/revert/table_jwt.sql index da05ca19..7f67a80f 100644 --- a/src/revert/table_jwt.sql +++ b/src/revert/table_jwt.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_jwt from pg - BEGIN; DROP TABLE maevsi_private.jwt; diff --git a/src/revert/table_legal_term.sql b/src/revert/table_legal_term.sql index 24467527..4a8db85a 100644 --- a/src/revert/table_legal_term.sql +++ b/src/revert/table_legal_term.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_legal_term from pg - BEGIN; DROP POLICY legal_term_select ON maevsi.legal_term; diff --git a/src/revert/table_legal_term_acceptance.sql b/src/revert/table_legal_term_acceptance.sql index 6fd5a939..6808d751 100644 --- a/src/revert/table_legal_term_acceptance.sql +++ b/src/revert/table_legal_term_acceptance.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_legal_term_acceptance from pg - BEGIN; DROP POLICY legal_term_acceptance_select ON maevsi.legal_term_acceptance; diff --git a/src/revert/table_notification.sql b/src/revert/table_notification.sql index ef9ee886..840e2a1c 100644 --- a/src/revert/table_notification.sql +++ b/src/revert/table_notification.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_notification from pg - BEGIN; DROP TABLE maevsi_private.notification; diff --git a/src/revert/table_profile_picture.sql b/src/revert/table_profile_picture.sql index fb96c89e..0ee2f5c1 100644 --- a/src/revert/table_profile_picture.sql +++ b/src/revert/table_profile_picture.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_profile_picture from pg - BEGIN; DROP TABLE maevsi.profile_picture; diff --git a/src/revert/table_report.sql b/src/revert/table_report.sql index e0d0e890..df03a553 100644 --- a/src/revert/table_report.sql +++ b/src/revert/table_report.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_report from pg - BEGIN; DROP TABLE maevsi.report; diff --git a/src/revert/table_report_policy.sql b/src/revert/table_report_policy.sql index 219fe50f..b90b8742 100644 --- a/src/revert/table_report_policy.sql +++ b/src/revert/table_report_policy.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_report_policy from pg - BEGIN; DROP POLICY report_select ON maevsi.report; diff --git a/src/revert/table_upload.sql b/src/revert/table_upload.sql index 0028f82b..a6066f5b 100644 --- a/src/revert/table_upload.sql +++ b/src/revert/table_upload.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_upload from pg - BEGIN; DROP TABLE maevsi.upload; diff --git a/src/revert/table_upload_policy.sql b/src/revert/table_upload_policy.sql index 861f14df..099ad350 100644 --- a/src/revert/table_upload_policy.sql +++ b/src/revert/table_upload_policy.sql @@ -1,5 +1,3 @@ --- Revert maevsi:table_upload from pg - BEGIN; DROP POLICY upload_delete_using ON maevsi.upload; diff --git a/src/revert/type_event_unlock_response.sql b/src/revert/type_event_unlock_response.sql index 469cecda..603be2d2 100644 --- a/src/revert/type_event_unlock_response.sql +++ b/src/revert/type_event_unlock_response.sql @@ -1,5 +1,3 @@ --- Revert maevsi:type_event_unlock_response from pg - BEGIN; DROP TYPE maevsi.event_unlock_response; diff --git a/src/revert/type_jwt.sql b/src/revert/type_jwt.sql index b2712cb4..5625524d 100644 --- a/src/revert/type_jwt.sql +++ b/src/revert/type_jwt.sql @@ -1,5 +1,3 @@ --- Revert maevsi:type_jwt from pg - BEGIN; DROP TYPE maevsi.jwt; diff --git a/src/revert/view_invitation_flat.sql b/src/revert/view_invitation_flat.sql new file mode 100644 index 00000000..3906ba4b --- /dev/null +++ b/src/revert/view_invitation_flat.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP VIEW maevsi.invitation_flat; + +COMMIT; diff --git a/src/sqitch.plan b/src/sqitch.plan index 22061476..293458bd 100644 --- a/src/sqitch.plan +++ b/src/sqitch.plan @@ -11,6 +11,7 @@ schema_public [role_anonymous role_account role_tusd] 1970-01-01T00:00:00Z Jonas schema_private 1970-01-01T00:00:00Z Jonas Thelemann # Add private schema. schema_test 1970-01-01T00:00:00Z Sven Thelemann # Add test schema. extension_pgcrypto [schema_public] 1970-01-01T00:00:00Z Jonas Thelemann # Add extension pgcrypto. +function_invoker_account_id [privilege_execute_revoke schema_public role_account role_anonymous] 1970-01-01T00:00:00Z Jonas Thelemann # Returns the session's account id. enum_invitation_feedback [schema_public] 1970-01-01T00:00:00Z Jonas Thelemann # Possible answers to an invitation: accepted, canceled. enum_event_visibility [schema_public] 1970-01-01T00:00:00Z Jonas Thelemann # Possible visibilities of events and event groups: public, private. table_notification [schema_private] 1970-01-01T00:00:00Z Jonas Thelemann # Notifications that are sent via pg_notify. @@ -21,21 +22,22 @@ table_account_block_policy [schema_public table_account_block role_account] 1970 table_event_group [schema_public role_account role_anonymous table_account_public enum_event_visibility] 1970-01-01T00:00:00Z Jonas Thelemann # Add table event_group. index_event_group_author_username [table_event_group] 1970-01-01T00:00:00Z Jonas Thelemann # Add an index to the event group table's author_username field. table_event [schema_public role_account role_anonymous table_account_public] 1970-01-01T00:00:00Z Jonas Thelemann # Add table event. -function_events_organized [privilege_execute_revoke schema_public table_event role_account role_anonymous] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that returns all event ids for which the invoker is the author. +function_events_organized [privilege_execute_revoke schema_public function_invoker_account_id table_event role_account role_anonymous] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that returns all event ids for which the invoker is the author. index_event_author_username [table_event] 1970-01-01T00:00:00Z Jonas Thelemann # Add an index to the event table's username field. enum_invitation_feedback_paper 1970-01-01T00:00:00Z Jonas Thelemann # Possible choices on how to receive a paper invitation: paper, digital. -table_contact [schema_public role_account role_anonymous table_account_public] 1970-01-01T00:00:00Z Jonas Thelemann # Add table contact. +enum_language [schema_public] 1970-01-01T00:00:00Z Jonas Thelemann # Supported ISO 639 language codes. +table_contact [schema_public table_account_public enum_language role_account function_invoker_account_id] 1970-01-01T00:00:00Z Jonas Thelemann # Add table contact. table_invitation [schema_public table_event table_contact] 1970-01-01T00:00:00Z Jonas Thelemann # Add table invitation. -function_events_invited [privilege_execute_revoke schema_private schema_public table_invitation table_contact role_account role_anonymous] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that returns all event ids for which the invoker is invited. +function_events_invited [privilege_execute_revoke schema_private schema_public function_invoker_account_id table_invitation table_contact role_account role_anonymous] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that returns all event ids for which the invoker is invited. function_invitation_claim_array [privilege_execute_revoke schema_public table_invitation table_contact table_account_block role_account role_anonymous] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that returns the current invitation claims as UUID array. function_invitation_contact_ids [privilege_execute_revoke schema_public table_invitation function_invitation_claim_array function_events_organized role_account role_anonymous] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that returns all event ids for which the invoker is invited. -table_contact_policy [schema_public table_contact role_account role_anonymous function_invitation_contact_ids] 1970-01-01T00:00:00Z Jonas Thelemann # Add policy for table contact. +table_contact_policy [schema_public table_contact role_account role_anonymous function_invoker_account_id function_invitation_contact_ids] 1970-01-01T00:00:00Z Jonas Thelemann # Add policy for table contact. function_invitee_count [privilege_execute_revoke schema_public table_invitation role_account role_anonymous] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that returns the invitee count for an event. -table_event_policy [schema_public table_event role_account role_anonymous schema_private function_events_invited] 1970-01-01T00:00:00Z Jonas Thelemann # Add policy for table event. +table_event_policy [schema_public table_event role_account role_anonymous function_invitee_count function_invoker_account_id schema_private function_events_invited] 1970-01-01T00:00:00Z Jonas Thelemann # Add policy for table event. index_invitation_event_id [table_invitation] 1970-01-01T00:00:00Z Jonas Thelemann # Add an index to the invitation table's event_id field. index_invitation_contact_id [table_invitation] 1970-01-01T00:00:00Z Jonas Thelemann # Add an index to the invitation table's contact_id field. -function_event_invitee_count_maximum [privilege_execute_revoke schema_public table_event function_invitee_count schema_private function_events_invited role_account role_anonymous] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that returns the maximum invitee count of an accessible event. -table_invitation_policy [schema_public table_invitation role_account role_anonymous function_invitation_claim_array function_events_organized function_event_invitee_count_maximum] 1970-01-01T00:00:00Z Jonas Thelemann # Add policy for table contact. +function_event_invitee_count_maximum [privilege_execute_revoke schema_public table_event function_invitee_count function_invoker_account_id schema_private function_events_invited role_account role_anonymous] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that returns the maximum invitee count of an accessible event. +table_invitation_policy [schema_public table_invitation role_account role_anonymous function_invitation_claim_array function_invoker_account_id function_events_organized function_event_invitee_count_maximum] 1970-01-01T00:00:00Z Jonas Thelemann # Add policy for table contact. table_event_grouping [schema_public role_account role_anonymous table_event table_event_group] 1970-01-01T00:00:00Z Jonas Thelemann # Add table event grouping. index_event_grouping_event_id [table_event_grouping] 1970-01-01T00:00:00Z Jonas Thelemann # Add an index to the event grouping table's event_id field. index_event_grouping_event_group_id [table_event_grouping] 1970-01-01T00:00:00Z Jonas Thelemann # Add an index to the event grouping table's event_group_id field. @@ -45,12 +47,12 @@ table_jwt [schema_private] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function to authenticate accounts. function_account_password_change [privilege_execute_revoke schema_public schema_private role_account table_account_private extension_pgcrypto] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that allows to change an account's password. type_event_unlock_response [schema_public type_jwt] 1970-01-01T00:00:00Z Jonas Thelemann # Add a type that is returned by invitation id redemption. -function_event_unlock [privilege_execute_revoke schema_public table_invitation table_event type_event_unlock_response function_invitation_claim_array type_jwt table_jwt] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that assigns an invitation to the current session +function_event_unlock [privilege_execute_revoke schema_public function_invoker_account_id table_event table_invitation function_invitation_claim_array type_jwt table_jwt type_event_unlock_response] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that assigns an invitation to the current session function_jwt_refresh [privilege_execute_revoke schema_public type_jwt table_jwt] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that refreshes tokens. table_upload [schema_public table_account_public] 1970-01-01T00:00:00Z Jonas Thelemann # An upload. function_upload_create [privilege_execute_revoke schema_public schema_private role_account table_upload table_account_private] 1970-01-01T00:00:00Z Jonas Thelemann # Creates an upload with the given size if quota is available. -table_profile_picture [schema_public table_account_public table_upload role_account role_anonymous role_tusd] 1970-01-01T00:00:00Z Jonas Thelemann # Mapping of usernames to upload storage keys. -table_upload_policy [schema_public table_upload role_account role_anonymous role_tusd] 1970-01-01T00:00:00Z Jonas Thelemann # Policies for uploads. +table_profile_picture [schema_public table_account_public table_upload role_account role_anonymous role_tusd function_invoker_account_id] 1970-01-01T00:00:00Z Jonas Thelemann # Mapping of usernames to upload storage keys. +table_upload_policy [schema_public table_upload role_account role_anonymous role_tusd function_invoker_account_id] 1970-01-01T00:00:00Z Jonas Thelemann # Policies for uploads. function_profile_picture_set [privilege_execute_revoke schema_public role_account table_profile_picture] 1970-01-01T00:00:00Z Jonas Thelemann # Sets the picture with the given storage key as the invoker's profile picture. function_event_delete [privilege_execute_revoke schema_public role_account table_account_private table_event extension_pgcrypto] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that allows to delete an event. function_account_delete [privilege_execute_revoke schema_public role_account table_account_private table_event extension_pgcrypto] 1970-01-01T00:00:00Z Jonas Thelemann # Add a function that allows to delete an account. @@ -67,9 +69,28 @@ role_grafana [database_grafana] 1970-01-01T00:00:00Z Jonas Thelemann # Achievement enumeration. table_achievement_code [schema_private schema_public enum_achievement_type] 1970-01-01T00:00:00Z Jonas Thelemann # Codes that unlock achievements. table_achievement [schema_public table_account_public enum_achievement_type role_account role_anonymous] 1970-01-01T00:00:00Z Jonas Thelemann # Achievement unlocks by user. -function_achievement_unlock [privilege_execute_revoke schema_public enum_achievement_type schema_private table_achievement_code table_achievement role_account] 1970-01-01T00:00:00Z Jonas Thelemann # Unlock achievements. +function_achievement_unlock [privilege_execute_revoke schema_public enum_achievement_type function_invoker_account_id schema_private table_achievement_code table_achievement role_account] 1970-01-01T00:00:00Z Jonas Thelemann # Unlock achievements. table_report [schema_public table_account_public table_event table_upload] 1970-01-01T00:00:00Z Marlon # Stores reports made by users on other users, events, or uploads for moderation purposes. -table_report_policy [schema_public table_report role_account] 1970-01-01T00:00:00Z Marlon # Access policies for reports. +table_report_policy [schema_public table_report role_account function_invoker_account_id] 1970-01-01T00:00:00Z Marlon # Access policies for reports. table_legal_term [schema_public role_account role_anonymous] 1970-01-01T00:00:00Z Jonas Thelemann # Legal terms like privacy policies or terms of service. -table_legal_term_acceptance [schema_public table_account_public table_legal_term role_account] 1970-01-01T00:00:00Z Jonas Thelemann # Tracks each user account's acceptance of legal terms and conditions. +table_legal_term_acceptance [schema_public table_account_public table_legal_term role_account function_invoker_account_id] 1970-01-01T00:00:00Z Jonas Thelemann # Tracks each user account's acceptance of legal terms and conditions. +enum_social_network [schema_public] 1970-01-01T00:00:00Z sven # Social networks. +table_account_social_network [schema_public table_account_public enum_social_network] 1970-01-01T00:00:00Z sven # Links accounts to their social media profiles. +table_account_social_network_policy [schema_public table_account_social_network function_invoker_account_id role_account] 1970-01-01T00:00:00Z sven # Row level security policies for table account_social_network. +enum_event_size [schema_public] 1970-01-01T00:00:00Z Sven Thelemann # Possible event sizes: small, medium, large, huge. +table_account_preference_event_size [schema_public table_account_public enum_event_size] 1970-01-01T00:00:00Z Sven Thelemann # Table for the user accounts' preferred event sizes (M:N relationship). +table_account_preference_event_size_policy [schema_public table_account_preference_event_size function_invoker_account_id role_account] 1970-01-01T00:00:00Z Sven Thelemann # Security policy for table account_event_size_pref. +table_event_upload [schema_public table_event table_upload] 1970-01-01T00:00:00Z Sven Thelemann # Add table event_upload. +table_event_upload_policy [schema_public table_event_upload role_account role_anonymous table_event table_upload] 1970-01-01T00:00:00Z Sven Thelemann # Grants and policies for table event_upload. +view_invitation_flat [schema_public table_invitation table_contact table_event role_account role_anonymous] 1970-01-01T00:00:00Z Sven Thelemann # View returning flattened invitations. +table_event_category [schema_public] 1970-01-01T00:00:00Z sven # Event categories. +table_event_category_policy [schema_public table_event_category role_anonymous role_account] 1970-01-01T00:00:00Z marlon # Row level security policies for table event_category. +table_account_interest [schema_public table_account_public table_event_category] 1970-01-01T00:00:00Z marlon # Event categories a user account is interested in (M:N relationship). +table_account_interest_policy [schema_public table_account_interest role_account] 1970-01-01T00:00:00Z marlon # Row level security policies for table account_interest. +table_event_category_mapping [schema_public table_event table_event_category] 1970-01-01T00:00:00Z marlon # Mapping events to categories (M:N relationship). +table_event_category_mapping_policy [schema_public table_event_category_mapping role_anonymous role_account table_event]1970-01-01T00:00:00Z marlon # Row level security policies for table table_event_category_mapping. +table_event_recommendation [schema_public table_account_public table_event] 1970-01-01T00:00:00Z marlon # Events recommended to a user account (M:N relationship). +table_event_recommendation_policy [schema_public table_event_recommendation role_account] 1970-01-01T00:00:00Z marlon # Row level security policies for table event_recommendation. +table_event_favourite [schema_public table_account_public table_event] 1970-01-01T00:00:00Z Sven Thelemann # A table for the user accounts' favourite events. +table_event_favourite_policy [schema_public table_account_public table_event role_account] 1970-01-01T00:00:00Z Sven Thelemann # Policy for table event_favourite. test_account_blocking [schema_test] 1970-01-01T00:00:00Z Sven Thelemann # Test cases for account blocking. diff --git a/src/verify/database_grafana.sql b/src/verify/database_grafana.sql index adda2520..09570d2d 100644 --- a/src/verify/database_grafana.sql +++ b/src/verify/database_grafana.sql @@ -1,5 +1,3 @@ --- Verify maevsi:database_grafana on pg - BEGIN; DO $$ diff --git a/src/verify/enum_achievement_type.sql b/src/verify/enum_achievement_type.sql index 3401c66c..71b77334 100644 --- a/src/verify/enum_achievement_type.sql +++ b/src/verify/enum_achievement_type.sql @@ -1,5 +1,3 @@ --- Verify maevsi:enum_achievement_type on pg - BEGIN; DO $$ diff --git a/src/verify/enum_event_size.sql b/src/verify/enum_event_size.sql new file mode 100644 index 00000000..e032368d --- /dev/null +++ b/src/verify/enum_event_size.sql @@ -0,0 +1,8 @@ +BEGIN; + +DO $$ +BEGIN + ASSERT (SELECT pg_catalog.has_type_privilege('maevsi.event_size', 'USAGE')); +END $$; + +ROLLBACK; diff --git a/src/verify/enum_event_visibility.sql b/src/verify/enum_event_visibility.sql index 12847236..e7170f43 100644 --- a/src/verify/enum_event_visibility.sql +++ b/src/verify/enum_event_visibility.sql @@ -1,5 +1,3 @@ --- Verify maevsi:enum_event_visibility on pg - BEGIN; DO $$ diff --git a/src/verify/enum_invitation_feedback.sql b/src/verify/enum_invitation_feedback.sql index 8b2758fb..e4547970 100644 --- a/src/verify/enum_invitation_feedback.sql +++ b/src/verify/enum_invitation_feedback.sql @@ -1,5 +1,3 @@ --- Verify maevsi:enum_invitation_feedback on pg - BEGIN; DO $$ diff --git a/src/verify/enum_invitation_feedback_paper.sql b/src/verify/enum_invitation_feedback_paper.sql index daa412e3..32ac0c4f 100644 --- a/src/verify/enum_invitation_feedback_paper.sql +++ b/src/verify/enum_invitation_feedback_paper.sql @@ -1,5 +1,3 @@ --- Verify maevsi:enum_paper_invitation_feedback on pg - BEGIN; DO $$ diff --git a/src/verify/enum_language.sql b/src/verify/enum_language.sql new file mode 100644 index 00000000..56726d96 --- /dev/null +++ b/src/verify/enum_language.sql @@ -0,0 +1,8 @@ +BEGIN; + +DO $$ +BEGIN + ASSERT (SELECT pg_catalog.has_type_privilege('maevsi.language', 'USAGE')); +END $$; + +ROLLBACK; diff --git a/src/verify/enum_social_network.sql b/src/verify/enum_social_network.sql new file mode 100644 index 00000000..5c99fe24 --- /dev/null +++ b/src/verify/enum_social_network.sql @@ -0,0 +1,8 @@ +BEGIN; + +DO $$ +BEGIN + ASSERT (SELECT pg_catalog.has_type_privilege('maevsi.social_network', 'USAGE')); +END $$; + +ROLLBACK; diff --git a/src/verify/extension_pgcrypto.sql b/src/verify/extension_pgcrypto.sql index 4881f191..bbaf6fb3 100644 --- a/src/verify/extension_pgcrypto.sql +++ b/src/verify/extension_pgcrypto.sql @@ -1,5 +1,3 @@ --- Verify maevsi:extension_pgcrypto on pg - BEGIN; SELECT 1/count(*) FROM pg_extension WHERE extname = 'pgcrypto'; diff --git a/src/verify/function_account_delete.sql b/src/verify/function_account_delete.sql index bcfdf170..c279ac2d 100644 --- a/src/verify/function_account_delete.sql +++ b/src/verify/function_account_delete.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_account_delete on pg - BEGIN; DO $$ diff --git a/src/verify/function_account_email_address_verification.sql b/src/verify/function_account_email_address_verification.sql index c5c51024..1a728a76 100644 --- a/src/verify/function_account_email_address_verification.sql +++ b/src/verify/function_account_email_address_verification.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_account_email_address_verification on pg - BEGIN; DO $$ diff --git a/src/verify/function_account_password_change.sql b/src/verify/function_account_password_change.sql index a65da5c9..9f22f382 100644 --- a/src/verify/function_account_password_change.sql +++ b/src/verify/function_account_password_change.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_account_password_change on pg - BEGIN; DO $$ diff --git a/src/verify/function_account_password_reset.sql b/src/verify/function_account_password_reset.sql index 1568876b..7d2b239a 100644 --- a/src/verify/function_account_password_reset.sql +++ b/src/verify/function_account_password_reset.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_account_password_reset on pg - BEGIN; DO $$ diff --git a/src/verify/function_account_password_reset_request.sql b/src/verify/function_account_password_reset_request.sql index 9535b1ca..3abc805b 100644 --- a/src/verify/function_account_password_reset_request.sql +++ b/src/verify/function_account_password_reset_request.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_account_password_reset_request on pg - BEGIN; DO $$ diff --git a/src/verify/function_account_registration.sql b/src/verify/function_account_registration.sql index ccd2eb0c..40559d88 100644 --- a/src/verify/function_account_registration.sql +++ b/src/verify/function_account_registration.sql @@ -1,11 +1,90 @@ --- Verify maevsi:function_account_registration on pg - BEGIN; +SAVEPOINT function_privileges_for_roles; +DO $$ +BEGIN + IF NOT (SELECT pg_catalog.has_function_privilege('maevsi_account', 'maevsi.account_registration(TEXT, TEXT, TEXT, TEXT)', 'EXECUTE')) THEN + RAISE EXCEPTION 'Test function_privileges_for_roles failed: maevsi_account does not have EXECUTE privilege'; + END IF; + + IF NOT (SELECT pg_catalog.has_function_privilege('maevsi_anonymous', 'maevsi.account_registration(TEXT, TEXT, TEXT, TEXT)', 'EXECUTE')) THEN + RAISE EXCEPTION 'Test function_privileges_for_roles failed: maevsi_anonymous does not have EXECUTE privilege'; + END IF; +END $$; +ROLLBACK TO SAVEPOINT function_privileges_for_roles; + +SAVEPOINT account_registration; +DO $$ +BEGIN + PERFORM maevsi.account_registration('username', 'email@example.com', 'password', 'en'); +END $$; +ROLLBACK TO SAVEPOINT account_registration; + +SAVEPOINT password_length; +DO $$ +BEGIN + PERFORM maevsi.account_registration('username', 'email@example.com', 'short', 'en'); + RAISE EXCEPTION 'Test failed: Password length not enforced'; +EXCEPTION WHEN invalid_parameter_value THEN + NULL; +END $$; +ROLLBACK TO SAVEPOINT password_length; + +SAVEPOINT username_uniqueness; DO $$ BEGIN - ASSERT (SELECT pg_catalog.has_function_privilege('maevsi_account', 'maevsi.account_registration(TEXT, TEXT, TEXT, TEXT)', 'EXECUTE')); - ASSERT (SELECT pg_catalog.has_function_privilege('maevsi_anonymous', 'maevsi.account_registration(TEXT, TEXT, TEXT, TEXT)', 'EXECUTE')); + PERFORM maevsi.account_registration('username-duplicate', 'diff@example.com', 'password', 'en'); + PERFORM maevsi.account_registration('username-duplicate', 'erent@example.com', 'password', 'en'); + RAISE EXCEPTION 'Test failed: Duplicate username not enforced'; +EXCEPTION WHEN unique_violation THEN + NULL; +END $$; +ROLLBACK TO SAVEPOINT username_uniqueness; + +SAVEPOINT email_uniqueness; +DO $$ +BEGIN + PERFORM maevsi.account_registration('username-diff', 'duplicate@example.com', 'password', 'en'); + PERFORM maevsi.account_registration('username-erent', 'duplicate@example.com', 'password', 'en'); + RAISE EXCEPTION 'Test failed: Duplicate email not enforced'; +EXCEPTION WHEN unique_violation THEN + NULL; +END $$; +ROLLBACK TO SAVEPOINT email_uniqueness; + +SAVEPOINT username_null; +DO $$ +BEGIN + PERFORM maevsi.account_registration(NULL, 'email@example.com', 'password', 'en'); + RAISE EXCEPTION 'Test failed: NULL username allowed'; +EXCEPTION WHEN OTHERS THEN + NULL; +END $$; +ROLLBACK TO SAVEPOINT username_null; + +SAVEPOINT username_length; +DO $$ +BEGIN + PERFORM maevsi.account_registration('', 'email@example.com', 'password', 'en'); + RAISE EXCEPTION 'Test failed: Empty username allowed'; +EXCEPTION WHEN OTHERS THEN + NULL; +END $$; +ROLLBACK TO SAVEPOINT username_length; + +SAVEPOINT notification; +DO $$ +BEGIN + PERFORM maevsi.account_registration('username-8b973f', 'email@example.com', 'password', 'en'); + + IF NOT EXISTS ( + SELECT 1 FROM maevsi_private.notification + WHERE channel = 'account_registration' + AND payload::jsonb -> 'account' ->> 'username' = 'username-8b973f' + ) THEN + RAISE EXCEPTION 'Test failed: Notification not generated'; + END IF; END $$; +ROLLBACK TO SAVEPOINT notification; ROLLBACK; diff --git a/src/verify/function_account_registration_refresh.sql b/src/verify/function_account_registration_refresh.sql index 46f36f4e..1354ff63 100644 --- a/src/verify/function_account_registration_refresh.sql +++ b/src/verify/function_account_registration_refresh.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_account_registration_refresh on pg - BEGIN; DO $$ diff --git a/src/verify/function_account_upload_quota_bytes.sql b/src/verify/function_account_upload_quota_bytes.sql index 891c3d7b..2f93e90a 100644 --- a/src/verify/function_account_upload_quota_bytes.sql +++ b/src/verify/function_account_upload_quota_bytes.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_account_upload_quota_bytes on pg - BEGIN; DO $$ diff --git a/src/verify/function_achievement_unlock.sql b/src/verify/function_achievement_unlock.sql index bc89a752..56af53cf 100644 --- a/src/verify/function_achievement_unlock.sql +++ b/src/verify/function_achievement_unlock.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_achievement_unlock on pg - BEGIN; DO $$ diff --git a/src/verify/function_authenticate.sql b/src/verify/function_authenticate.sql index f5c15f2a..ac60b706 100644 --- a/src/verify/function_authenticate.sql +++ b/src/verify/function_authenticate.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_authenticate on pg - BEGIN; DO $$ diff --git a/src/verify/function_event_delete.sql b/src/verify/function_event_delete.sql index 2126da0b..6a3b7619 100644 --- a/src/verify/function_event_delete.sql +++ b/src/verify/function_event_delete.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_event_delete on pg - BEGIN; DO $$ diff --git a/src/verify/function_event_invitee_count_maximum.sql b/src/verify/function_event_invitee_count_maximum.sql index cc5af36a..92cdee9c 100644 --- a/src/verify/function_event_invitee_count_maximum.sql +++ b/src/verify/function_event_invitee_count_maximum.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_event_invitee_count_maximum on pg - BEGIN; DO $$ diff --git a/src/verify/function_event_is_existing.sql b/src/verify/function_event_is_existing.sql index 85fa741e..a6610129 100644 --- a/src/verify/function_event_is_existing.sql +++ b/src/verify/function_event_is_existing.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_event_is_existing on pg - BEGIN; DO $$ diff --git a/src/verify/function_event_unlock.sql b/src/verify/function_event_unlock.sql index fcf377fa..8d86751e 100644 --- a/src/verify/function_event_unlock.sql +++ b/src/verify/function_event_unlock.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_event_unlock on pg - BEGIN; DO $$ diff --git a/src/verify/function_events_invited.sql b/src/verify/function_events_invited.sql index e1c5f6e1..16bf3f48 100644 --- a/src/verify/function_events_invited.sql +++ b/src/verify/function_events_invited.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_events_invited on pg - BEGIN; DO $$ diff --git a/src/verify/function_events_organized.sql b/src/verify/function_events_organized.sql index b3e778c0..b96438e0 100644 --- a/src/verify/function_events_organized.sql +++ b/src/verify/function_events_organized.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_events_organized on pg - BEGIN; DO $$ diff --git a/src/verify/function_invitation_claim_array.sql b/src/verify/function_invitation_claim_array.sql index 7e5865c8..2a28bbc7 100644 --- a/src/verify/function_invitation_claim_array.sql +++ b/src/verify/function_invitation_claim_array.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_invitation_claim_array on pg - BEGIN; DO $$ diff --git a/src/verify/function_invitation_contact_ids.sql b/src/verify/function_invitation_contact_ids.sql index 9a1a30e6..510eb0e3 100644 --- a/src/verify/function_invitation_contact_ids.sql +++ b/src/verify/function_invitation_contact_ids.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_invitation_contact_ids on pg - BEGIN; DO $$ diff --git a/src/verify/function_invite.sql b/src/verify/function_invite.sql index d3449f73..12b5c2a9 100644 --- a/src/verify/function_invite.sql +++ b/src/verify/function_invite.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_invite on pg - BEGIN; DO $$ diff --git a/src/verify/function_invitee_count.sql b/src/verify/function_invitee_count.sql index 15c1fa4b..57936144 100644 --- a/src/verify/function_invitee_count.sql +++ b/src/verify/function_invitee_count.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_invitee_count on pg - BEGIN; DO $$ diff --git a/src/verify/function_invoker_account_id.sql b/src/verify/function_invoker_account_id.sql new file mode 100644 index 00000000..570f90db --- /dev/null +++ b/src/verify/function_invoker_account_id.sql @@ -0,0 +1,9 @@ +BEGIN; + +DO $$ +BEGIN + ASSERT (SELECT pg_catalog.has_function_privilege('maevsi_account', 'maevsi.invoker_account_id()', 'EXECUTE')); + ASSERT (SELECT pg_catalog.has_function_privilege('maevsi_anonymous', 'maevsi.invoker_account_id()', 'EXECUTE')); +END $$; + +ROLLBACK; diff --git a/src/verify/function_jwt_refresh.sql b/src/verify/function_jwt_refresh.sql index 14c5c133..6b7f8861 100644 --- a/src/verify/function_jwt_refresh.sql +++ b/src/verify/function_jwt_refresh.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_jwt_refresh on pg - BEGIN; DO $$ diff --git a/src/verify/function_notification_acknowledge.sql b/src/verify/function_notification_acknowledge.sql index 19424a4a..dd365c0d 100644 --- a/src/verify/function_notification_acknowledge.sql +++ b/src/verify/function_notification_acknowledge.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_notification_acknowledge on pg - BEGIN; DO $$ diff --git a/src/verify/function_profile_picture_set.sql b/src/verify/function_profile_picture_set.sql index d900dbf4..2092532c 100644 --- a/src/verify/function_profile_picture_set.sql +++ b/src/verify/function_profile_picture_set.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_profile_picture_set on pg - BEGIN; DO $$ diff --git a/src/verify/function_upload_create.sql b/src/verify/function_upload_create.sql index fd1798ac..c2d531d3 100644 --- a/src/verify/function_upload_create.sql +++ b/src/verify/function_upload_create.sql @@ -1,5 +1,3 @@ --- Verify maevsi:function_upload_create on pg - BEGIN; DO $$ diff --git a/src/verify/index_event_author_username.sql b/src/verify/index_event_author_username.sql index 4500625e..60cd3893 100644 --- a/src/verify/index_event_author_username.sql +++ b/src/verify/index_event_author_username.sql @@ -1,5 +1,3 @@ --- Verify maevsi:index_event_author_account_id on pg - BEGIN; SELECT 1/COUNT(*) diff --git a/src/verify/index_event_group_author_username.sql b/src/verify/index_event_group_author_username.sql index ac098583..4da705ab 100644 --- a/src/verify/index_event_group_author_username.sql +++ b/src/verify/index_event_group_author_username.sql @@ -1,5 +1,3 @@ --- Verify maevsi:index_event_group_author_id on pg - BEGIN; SELECT 1/COUNT(*) diff --git a/src/verify/index_event_grouping_event_group_id.sql b/src/verify/index_event_grouping_event_group_id.sql index a67fffb8..83673658 100644 --- a/src/verify/index_event_grouping_event_group_id.sql +++ b/src/verify/index_event_grouping_event_group_id.sql @@ -1,5 +1,3 @@ --- Verify maevsi:index_event_grouping_event_group_id on pg - BEGIN; SELECT 1/COUNT(*) diff --git a/src/verify/index_event_grouping_event_id.sql b/src/verify/index_event_grouping_event_id.sql index 575865a4..cc2fea40 100644 --- a/src/verify/index_event_grouping_event_id.sql +++ b/src/verify/index_event_grouping_event_id.sql @@ -1,5 +1,3 @@ --- Verify maevsi:index_event_grouping_event_id on pg - BEGIN; SELECT 1/COUNT(*) diff --git a/src/verify/index_invitation_contact_id.sql b/src/verify/index_invitation_contact_id.sql index 09eb6d39..3fea6688 100644 --- a/src/verify/index_invitation_contact_id.sql +++ b/src/verify/index_invitation_contact_id.sql @@ -1,5 +1,3 @@ --- Verify maevsi:index_invitation_contact_id on pg - BEGIN; SELECT 1/COUNT(*) diff --git a/src/verify/index_invitation_event_id.sql b/src/verify/index_invitation_event_id.sql index 470f05f6..de8bf56b 100644 --- a/src/verify/index_invitation_event_id.sql +++ b/src/verify/index_invitation_event_id.sql @@ -1,5 +1,3 @@ --- Verify maevsi:index_invitation_event_id on pg - BEGIN; SELECT 1/COUNT(*) diff --git a/src/verify/privilege_execute_revoke.sql b/src/verify/privilege_execute_revoke.sql index ad667cdd..6d177a04 100644 --- a/src/verify/privilege_execute_revoke.sql +++ b/src/verify/privilege_execute_revoke.sql @@ -1,7 +1,5 @@ --- Verify maevsi:privilege_execute_revoke on pg - BEGIN; --- XXX Add verifications here. +-- TODO: Add verifications here (https://github.com/maevsi/sqitch/issues/22) ROLLBACK; diff --git a/src/verify/role_account.sql b/src/verify/role_account.sql index 10bbc3c9..ab7f3703 100644 --- a/src/verify/role_account.sql +++ b/src/verify/role_account.sql @@ -1,5 +1,3 @@ --- Verify maevsi:role_account on pg - BEGIN; DO $$ diff --git a/src/verify/role_anonymous.sql b/src/verify/role_anonymous.sql index 36579de2..d0761647 100644 --- a/src/verify/role_anonymous.sql +++ b/src/verify/role_anonymous.sql @@ -1,5 +1,3 @@ --- Verify maevsi:role_anonymous on pg - BEGIN; DO $$ diff --git a/src/verify/role_grafana.sql b/src/verify/role_grafana.sql index 6515b1ca..5ed4f2ea 100644 --- a/src/verify/role_grafana.sql +++ b/src/verify/role_grafana.sql @@ -1,5 +1,3 @@ --- Verify maevsi:role_grafana on pg - \connect grafana BEGIN; diff --git a/src/verify/role_postgraphile.sql b/src/verify/role_postgraphile.sql index bfac7d85..37885e49 100644 --- a/src/verify/role_postgraphile.sql +++ b/src/verify/role_postgraphile.sql @@ -1,5 +1,3 @@ --- Verify maevsi:role_postgraphile on pg - BEGIN; DO $$ diff --git a/src/verify/role_tusd.sql b/src/verify/role_tusd.sql index b40da8a5..9fbd834a 100644 --- a/src/verify/role_tusd.sql +++ b/src/verify/role_tusd.sql @@ -1,5 +1,3 @@ --- Verify maevsi:role_tusd on pg - BEGIN; DO $$ diff --git a/src/verify/schema_private.sql b/src/verify/schema_private.sql index 29010006..be764224 100644 --- a/src/verify/schema_private.sql +++ b/src/verify/schema_private.sql @@ -1,5 +1,3 @@ --- Verify maevsi:schema_private on pg - BEGIN; DO $$ diff --git a/src/verify/schema_public.sql b/src/verify/schema_public.sql index 885898c6..9310de70 100644 --- a/src/verify/schema_public.sql +++ b/src/verify/schema_public.sql @@ -1,5 +1,3 @@ --- Verify maevsi:schema_public on pg - BEGIN; DO $$ diff --git a/src/verify/table_account_block.sql b/src/verify/table_account_block.sql index 378bac13..df2445a6 100644 --- a/src/verify/table_account_block.sql +++ b/src/verify/table_account_block.sql @@ -1,6 +1,3 @@ - --- Verify maevsi:table_account_block on pg - BEGIN; SELECT id, diff --git a/src/verify/table_account_block_policy.sql b/src/verify/table_account_block_policy.sql index b21bdede..d0f8e224 100644 --- a/src/verify/table_account_block_policy.sql +++ b/src/verify/table_account_block_policy.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_account_block_policy on pg - BEGIN; DO $$ diff --git a/src/verify/table_account_interest.sql b/src/verify/table_account_interest.sql new file mode 100644 index 00000000..12c34884 --- /dev/null +++ b/src/verify/table_account_interest.sql @@ -0,0 +1,7 @@ +BEGIN; + +SELECT account_id, + category +FROM maevsi.account_interest WHERE FALSE; + +ROLLBACK; diff --git a/src/verify/table_account_interest_policy.sql b/src/verify/table_account_interest_policy.sql new file mode 100644 index 00000000..7aef5fd4 --- /dev/null +++ b/src/verify/table_account_interest_policy.sql @@ -0,0 +1,19 @@ +BEGIN; + +DO $$ +BEGIN + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.account_interest', 'SELECT')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.account_interest', 'INSERT')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.account_interest', 'DELETE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.account_interest', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.account_interest', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.account_interest', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.account_interest', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.account_interest', 'DELETE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.account_interest', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.account_interest', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.account_interest', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.account_interest', 'DELETE')); +END $$; + +ROLLBACK; diff --git a/src/verify/table_account_preference_event_size.sql b/src/verify/table_account_preference_event_size.sql new file mode 100644 index 00000000..34a2b129 --- /dev/null +++ b/src/verify/table_account_preference_event_size.sql @@ -0,0 +1,8 @@ +BEGIN; + +SELECT created_at, + account_id, + event_size +FROM maevsi.account_preference_event_size WHERE FALSE; + +ROLLBACK; diff --git a/src/verify/table_account_preference_event_size_policy.sql b/src/verify/table_account_preference_event_size_policy.sql new file mode 100644 index 00000000..a4ad4882 --- /dev/null +++ b/src/verify/table_account_preference_event_size_policy.sql @@ -0,0 +1,19 @@ +BEGIN; + +DO $$ +BEGIN + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.account_preference_event_size', 'SELECT')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.account_preference_event_size', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.account_preference_event_size', 'UPDATE')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.account_preference_event_size', 'DELETE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.account_preference_event_size', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.account_preference_event_size', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.account_preference_event_size', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.account_preference_event_size', 'DELETE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.account_preference_event_size', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.account_preference_event_size', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.account_preference_event_size', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.account_preference_event_size', 'DELETE')); +END $$; + +ROLLBACK; diff --git a/src/verify/table_account_private.sql b/src/verify/table_account_private.sql index cc9a0c1a..173df64e 100644 --- a/src/verify/table_account_private.sql +++ b/src/verify/table_account_private.sql @@ -1,8 +1,7 @@ --- Verify maevsi:table_account_private on pg - BEGIN; SELECT id, + birth_date, created, email_address, email_address_verification, diff --git a/src/verify/table_account_public.sql b/src/verify/table_account_public.sql index 470a92e8..4ea4c773 100644 --- a/src/verify/table_account_public.sql +++ b/src/verify/table_account_public.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_account_public on pg - BEGIN; SELECT id, diff --git a/src/verify/table_account_social_network.sql b/src/verify/table_account_social_network.sql new file mode 100644 index 00000000..eab2abfe --- /dev/null +++ b/src/verify/table_account_social_network.sql @@ -0,0 +1,9 @@ +BEGIN; + +SELECT + account_id, + social_network + social_network_username +FROM maevsi.account_social_network WHERE FALSE; + +ROLLBACK; diff --git a/src/verify/table_account_social_network_policy.sql b/src/verify/table_account_social_network_policy.sql new file mode 100644 index 00000000..c7395552 --- /dev/null +++ b/src/verify/table_account_social_network_policy.sql @@ -0,0 +1,101 @@ +BEGIN; + +SAVEPOINT select_account; +DO $$ +BEGIN + SET LOCAL role TO maevsi_account; + PERFORM * FROM maevsi.account_social_network; +END $$; +ROLLBACK TO SAVEPOINT select_account; + +SAVEPOINT select_anonymous; +DO $$ +BEGIN + SET LOCAL role TO maevsi_anonymous; + PERFORM * FROM maevsi.account_social_network; +END $$; +ROLLBACK TO SAVEPOINT select_anonymous; + +SAVEPOINT insert_account; +DO $$ +BEGIN + INSERT INTO maevsi_private.account(id, email_address, password_hash) VALUES ('00000000-0000-0000-0000-000000000000', 'email@example.com', '$2a$06$xdJFoht/HQ/4798obSknNOc6hiBe60HXriyW/Oa3Ch7Oo3F.9WGLe'); + INSERT INTO maevsi.account(id, username) VALUES ('00000000-0000-0000-0000-000000000000', 'username'); + + SET LOCAL role TO maevsi_account; + SET LOCAL jwt.claims.account_id TO '00000000-0000-0000-0000-000000000000'; + INSERT INTO maevsi.account_social_network(account_id, social_network, social_network_username) + VALUES ('00000000-0000-0000-0000-000000000000', 'instagram', 'username'); +END $$; +ROLLBACK TO SAVEPOINT insert_account; + +SAVEPOINT insert_anonymous; +DO $$ +BEGIN + INSERT INTO maevsi_private.account(id, email_address, password_hash) VALUES ('00000000-0000-0000-0000-000000000000', 'email@example.com', '$2a$06$xdJFoht/HQ/4798obSknNOc6hiBe60HXriyW/Oa3Ch7Oo3F.9WGLe'); + INSERT INTO maevsi.account(id, username) VALUES ('00000000-0000-0000-0000-000000000000', 'username'); + + SET LOCAL role TO maevsi_anonymous; + INSERT INTO maevsi.account_social_network(account_id, social_network, social_network_username) + VALUES ('00000000-0000-0000-0000-000000000000', 'instagram', 'username'); + RAISE EXCEPTION 'Test insert_anonymous failed: Anonymous users should not be able to insert'; +EXCEPTION WHEN others THEN + NULL; +END $$; +ROLLBACK TO SAVEPOINT insert_anonymous; + +SAVEPOINT update_account; +DO $$ +BEGIN + INSERT INTO maevsi_private.account(id, email_address, password_hash) VALUES ('00000000-0000-0000-0000-000000000000', 'email@example.com', '$2a$06$xdJFoht/HQ/4798obSknNOc6hiBe60HXriyW/Oa3Ch7Oo3F.9WGLe'); + INSERT INTO maevsi.account(id, username) VALUES ('00000000-0000-0000-0000-000000000000', 'username'); + INSERT INTO maevsi.account_social_network(account_id, social_network, social_network_username) VALUES ('00000000-0000-0000-0000-000000000000', 'instagram', 'username'); + + SET LOCAL role TO maevsi_account; + UPDATE maevsi.account_social_network SET social_network_username = 'username-updated'; +END $$; +ROLLBACK TO SAVEPOINT update_account; + +SAVEPOINT insert_anonymous; +DO $$ +BEGIN + INSERT INTO maevsi_private.account(id, email_address, password_hash) VALUES ('00000000-0000-0000-0000-000000000000', 'email@example.com', '$2a$06$xdJFoht/HQ/4798obSknNOc6hiBe60HXriyW/Oa3Ch7Oo3F.9WGLe'); + INSERT INTO maevsi.account(id, username) VALUES ('00000000-0000-0000-0000-000000000000', 'username'); + INSERT INTO maevsi.account_social_network(account_id, social_network, social_network_username) VALUES ('00000000-0000-0000-0000-000000000000', 'instagram', 'username'); + + SET LOCAL role TO maevsi_anonymous; + UPDATE maevsi.account_social_network SET social_network_username = 'username-updated'; + RAISE EXCEPTION 'Test update_anonymous failed: Anonymous users should not be able to update'; +EXCEPTION WHEN others THEN + NULL; +END $$; +ROLLBACK TO SAVEPOINT insert_anonymous; + +SAVEPOINT delete_account; +DO $$ +BEGIN + INSERT INTO maevsi_private.account(id, email_address, password_hash) VALUES ('00000000-0000-0000-0000-000000000000', 'email@example.com', '$2a$06$xdJFoht/HQ/4798obSknNOc6hiBe60HXriyW/Oa3Ch7Oo3F.9WGLe'); + INSERT INTO maevsi.account(id, username) VALUES ('00000000-0000-0000-0000-000000000000', 'username'); + INSERT INTO maevsi.account_social_network(account_id, social_network, social_network_username) VALUES ('00000000-0000-0000-0000-000000000000', 'instagram', 'username'); + + SET LOCAL role TO maevsi_account; + DELETE FROM maevsi.account_social_network; +END $$; +ROLLBACK TO SAVEPOINT delete_account; + +SAVEPOINT delete_anonymous; +DO $$ +BEGIN + INSERT INTO maevsi_private.account(id, email_address, password_hash) VALUES ('00000000-0000-0000-0000-000000000000', 'email@example.com', '$2a$06$xdJFoht/HQ/4798obSknNOc6hiBe60HXriyW/Oa3Ch7Oo3F.9WGLe'); + INSERT INTO maevsi.account(id, username) VALUES ('00000000-0000-0000-0000-000000000000', 'username'); + INSERT INTO maevsi.account_social_network(account_id, social_network, social_network_username) VALUES ('00000000-0000-0000-0000-000000000000', 'instagram', 'username'); + + SET LOCAL role TO maevsi_anonymous; + DELETE FROM maevsi.account_social_network; + RAISE EXCEPTION 'Test delete_anonymous failed: Anonymous users should not be able to delete'; +EXCEPTION WHEN others THEN + NULL; +END $$; +ROLLBACK TO SAVEPOINT delete_anonymous; + +ROLLBACK; diff --git a/src/verify/table_achievement.sql b/src/verify/table_achievement.sql index 6fd3de9e..d43b5e0f 100644 --- a/src/verify/table_achievement.sql +++ b/src/verify/table_achievement.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_achievement on pg - BEGIN; SELECT id, diff --git a/src/verify/table_achievement_code.sql b/src/verify/table_achievement_code.sql index e2253338..2e513b89 100644 --- a/src/verify/table_achievement_code.sql +++ b/src/verify/table_achievement_code.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_achievement_code on pg - BEGIN; SELECT id, diff --git a/src/verify/table_contact.sql b/src/verify/table_contact.sql index c3024cd6..caade761 100644 --- a/src/verify/table_contact.sql +++ b/src/verify/table_contact.sql @@ -1,17 +1,19 @@ --- Verify maevsi:table_contact on pg - BEGIN; SELECT id, + created_at, account_id, - "address", + address, author_account_id, email_address, email_address_hash, first_name, + language, last_name, + nickname, phone_number, - "url" + timezone, + url FROM maevsi.contact WHERE FALSE; ROLLBACK; diff --git a/src/verify/table_contact_policy.sql b/src/verify/table_contact_policy.sql index c4fb93e8..774dedca 100644 --- a/src/verify/table_contact_policy.sql +++ b/src/verify/table_contact_policy.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_contact_policy on pg - BEGIN; DO $$ diff --git a/src/verify/table_event.sql b/src/verify/table_event.sql index bb273324..58f89ce2 100644 --- a/src/verify/table_event.sql +++ b/src/verify/table_event.sql @@ -1,20 +1,19 @@ --- Verify maevsi:table_event on pg - BEGIN; SELECT id, + created_at, author_account_id, - "description", + description, "end", invitee_count_maximum, is_archived, is_in_person, is_remote, - "location", - "name", + location, + name, slug, - "start", - "url", + start, + url, visibility FROM maevsi.event WHERE FALSE; diff --git a/src/verify/table_event_category.sql b/src/verify/table_event_category.sql new file mode 100644 index 00000000..8d180230 --- /dev/null +++ b/src/verify/table_event_category.sql @@ -0,0 +1,6 @@ +BEGIN; + +SELECT category +FROM maevsi.event_category WHERE FALSE; + +ROLLBACK; diff --git a/src/verify/table_event_category_mapping.sql b/src/verify/table_event_category_mapping.sql new file mode 100644 index 00000000..e8955543 --- /dev/null +++ b/src/verify/table_event_category_mapping.sql @@ -0,0 +1,7 @@ +BEGIN; + +SELECT event_id, + category +FROM maevsi.event_category_mapping WHERE FALSE; + +ROLLBACK; diff --git a/src/verify/table_event_category_mapping_policy.sql b/src/verify/table_event_category_mapping_policy.sql new file mode 100644 index 00000000..297d538f --- /dev/null +++ b/src/verify/table_event_category_mapping_policy.sql @@ -0,0 +1,19 @@ +BEGIN; + +DO $$ +BEGIN + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_category_mapping', 'SELECT')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_category_mapping', 'INSERT')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_category_mapping', 'DELETE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_category_mapping', 'UPDATE')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_category_mapping', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_category_mapping', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_category_mapping', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_category_mapping', 'DELETE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_category_mapping', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_category_mapping', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_category_mapping', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_category_mapping', 'DELETE')); +END $$; + +ROLLBACK; diff --git a/src/verify/table_event_category_policy.sql b/src/verify/table_event_category_policy.sql new file mode 100644 index 00000000..c2c8fa67 --- /dev/null +++ b/src/verify/table_event_category_policy.sql @@ -0,0 +1,19 @@ +BEGIN; + +DO $$ +BEGIN + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_category', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_category', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_category', 'DELETE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_category', 'UPDATE')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_category', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_category', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_category', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_category', 'DELETE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_category', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_category', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_category', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_category', 'DELETE')); +END $$; + +ROLLBACK; diff --git a/src/verify/table_event_favourite.sql b/src/verify/table_event_favourite.sql new file mode 100644 index 00000000..d8a84704 --- /dev/null +++ b/src/verify/table_event_favourite.sql @@ -0,0 +1,7 @@ +BEGIN; + +SELECT account_id, + event_id +FROM maevsi.event_favourite WHERE FALSE; + +ROLLBACK; diff --git a/src/verify/table_event_favourite_policy.sql b/src/verify/table_event_favourite_policy.sql new file mode 100644 index 00000000..5bfddb43 --- /dev/null +++ b/src/verify/table_event_favourite_policy.sql @@ -0,0 +1,19 @@ +BEGIN; + +DO $$ +BEGIN + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_favourite', 'SELECT')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_favourite', 'INSERT')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_favourite', 'DELETE')); + ASSERT NOT(SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_favourite', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_favourite', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_favourite', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_favourite', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_favourite', 'DELETE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_favourite', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_favourite', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_favourite', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_favourite', 'DELETE')); +END $$; + +ROLLBACK; diff --git a/src/verify/table_event_group.sql b/src/verify/table_event_group.sql index 58d12615..80491c8a 100644 --- a/src/verify/table_event_group.sql +++ b/src/verify/table_event_group.sql @@ -1,8 +1,7 @@ --- Verify maevsi:table_event_group on pg - BEGIN; SELECT id, + created_at, author_account_id, "description", is_archived, diff --git a/src/verify/table_event_grouping.sql b/src/verify/table_event_grouping.sql index 7862644e..ea13c2ca 100644 --- a/src/verify/table_event_grouping.sql +++ b/src/verify/table_event_grouping.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_event_grouping on pg - BEGIN; SELECT id, diff --git a/src/verify/table_event_policy.sql b/src/verify/table_event_policy.sql index 7b9ecd53..28c83f1d 100644 --- a/src/verify/table_event_policy.sql +++ b/src/verify/table_event_policy.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_event_policy on pg - BEGIN; DO $$ diff --git a/src/verify/table_event_recommendation.sql b/src/verify/table_event_recommendation.sql new file mode 100644 index 00000000..12516886 --- /dev/null +++ b/src/verify/table_event_recommendation.sql @@ -0,0 +1,9 @@ +BEGIN; + +SELECT account_id, + event_id, + score, + predicted_score +FROM maevsi.event_recommendation WHERE FALSE; + +ROLLBACK; diff --git a/src/verify/table_event_recommendation_policy.sql b/src/verify/table_event_recommendation_policy.sql new file mode 100644 index 00000000..29a6ecc4 --- /dev/null +++ b/src/verify/table_event_recommendation_policy.sql @@ -0,0 +1,19 @@ +BEGIN; + +DO $$ +BEGIN + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_recommendation', 'SELECT')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_recommendation', 'INSERT')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_recommendation', 'DELETE')); + ASSERT NOT(SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_recommendation', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_recommendation', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_recommendation', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_recommendation', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_recommendation', 'DELETE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_recommendation', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_recommendation', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_recommendation', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_recommendation', 'DELETE')); +END $$; + +ROLLBACK; diff --git a/src/verify/table_event_upload.sql b/src/verify/table_event_upload.sql new file mode 100644 index 00000000..8845a723 --- /dev/null +++ b/src/verify/table_event_upload.sql @@ -0,0 +1,6 @@ +BEGIN; + +SELECT id, + event_id, + upload_id +FROM maevsi.event_upload WHERE FALSE; diff --git a/src/verify/table_event_upload_policy.sql b/src/verify/table_event_upload_policy.sql new file mode 100644 index 00000000..3ee96242 --- /dev/null +++ b/src/verify/table_event_upload_policy.sql @@ -0,0 +1,19 @@ +BEGIN; + +DO $$ +BEGIN + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_upload', 'SELECT')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_upload', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_upload', 'UPDATE')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_account', 'maevsi.event_upload', 'DELETE')); + ASSERT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_upload', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_upload', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_upload', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_anonymous', 'maevsi.event_upload', 'DELETE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_upload', 'SELECT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_upload', 'INSERT')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_upload', 'UPDATE')); + ASSERT NOT (SELECT pg_catalog.has_table_privilege('maevsi_tusd', 'maevsi.event_upload', 'DELETE')); +END $$; + +ROLLBACK; diff --git a/src/verify/table_invitation.sql b/src/verify/table_invitation.sql index 294c1043..4cc5e972 100644 --- a/src/verify/table_invitation.sql +++ b/src/verify/table_invitation.sql @@ -1,8 +1,9 @@ --- Verify maevsi:table_invitation on pg - BEGIN; SELECT id, + created_at, + updated_at, + updated_by, event_id, feedback, feedback_paper diff --git a/src/verify/table_invitation_policy.sql b/src/verify/table_invitation_policy.sql index 930fe347..02b8f540 100644 --- a/src/verify/table_invitation_policy.sql +++ b/src/verify/table_invitation_policy.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_invitation_policy on pg - BEGIN; DO $$ diff --git a/src/verify/table_jwt.sql b/src/verify/table_jwt.sql index 7446ef84..9c8c8ebc 100644 --- a/src/verify/table_jwt.sql +++ b/src/verify/table_jwt.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_jwt on pg - BEGIN; SELECT id, diff --git a/src/verify/table_legal_term.sql b/src/verify/table_legal_term.sql index 48e1d77d..c455c1e3 100644 --- a/src/verify/table_legal_term.sql +++ b/src/verify/table_legal_term.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_legal_term on pg - BEGIN; SELECT id, diff --git a/src/verify/table_legal_term_acceptance.sql b/src/verify/table_legal_term_acceptance.sql index 1e663476..7784a84d 100644 --- a/src/verify/table_legal_term_acceptance.sql +++ b/src/verify/table_legal_term_acceptance.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_legal_term_acceptance on pg - BEGIN; SELECT id, diff --git a/src/verify/table_notification.sql b/src/verify/table_notification.sql index b5958612..5577bb9f 100644 --- a/src/verify/table_notification.sql +++ b/src/verify/table_notification.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_notification on pg - BEGIN; SELECT id, diff --git a/src/verify/table_profile_picture.sql b/src/verify/table_profile_picture.sql index fb6f12a2..e8cba816 100644 --- a/src/verify/table_profile_picture.sql +++ b/src/verify/table_profile_picture.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_profile_picture on pg - BEGIN; SELECT id, diff --git a/src/verify/table_report.sql b/src/verify/table_report.sql index 39981d66..4cd29e5a 100644 --- a/src/verify/table_report.sql +++ b/src/verify/table_report.sql @@ -1,14 +1,12 @@ --- Verify maevsi:table_report on pg - BEGIN; SELECT id, + created_at, author_account_id, reason, target_account_id, target_event_id, - target_upload_id, - created_at + target_upload_id FROM maevsi.report WHERE FALSE; ROLLBACK; diff --git a/src/verify/table_report_policy.sql b/src/verify/table_report_policy.sql index 660f426a..bc124fa9 100644 --- a/src/verify/table_report_policy.sql +++ b/src/verify/table_report_policy.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_report_policy on pg - BEGIN; DO $$ diff --git a/src/verify/table_upload.sql b/src/verify/table_upload.sql index 03dbfc40..65639b7d 100644 --- a/src/verify/table_upload.sql +++ b/src/verify/table_upload.sql @@ -1,11 +1,12 @@ --- Verify maevsi:table_upload on pg - BEGIN; SELECT id, + created_at, account_id, + name, size_byte, - storage_key + storage_key, + type FROM maevsi.upload WHERE FALSE; ROLLBACK; diff --git a/src/verify/table_upload_policy.sql b/src/verify/table_upload_policy.sql index 35def160..6d5fa077 100644 --- a/src/verify/table_upload_policy.sql +++ b/src/verify/table_upload_policy.sql @@ -1,5 +1,3 @@ --- Verify maevsi:table_upload on pg - BEGIN; DO $$ diff --git a/src/verify/type_event_unlock_response.sql b/src/verify/type_event_unlock_response.sql index 0c581533..db3cb1ee 100644 --- a/src/verify/type_event_unlock_response.sql +++ b/src/verify/type_event_unlock_response.sql @@ -1,5 +1,3 @@ --- Verify maevsi:type_event_unlock_response on pg - BEGIN; DO $$ diff --git a/src/verify/type_jwt.sql b/src/verify/type_jwt.sql index b2f62e9a..e5526fd6 100644 --- a/src/verify/type_jwt.sql +++ b/src/verify/type_jwt.sql @@ -1,5 +1,3 @@ --- Verify maevsi:type_jwt on pg - BEGIN; DO $$ diff --git a/src/verify/view_invitation_flat.sql b/src/verify/view_invitation_flat.sql new file mode 100644 index 00000000..1eadd915 --- /dev/null +++ b/src/verify/view_invitation_flat.sql @@ -0,0 +1,35 @@ +BEGIN; + +SELECT + invitation_id, + invitation_contact_id, + invitation_event_id, + invitation_feedback, + invitation_feedback_paper, + contact_id, + contact_account_id, + contact_address, + contact_author_account_id, + contact_email_address, + contact_email_address_hash, + contact_first_name, + contact_last_name, + contact_phone_number, + contact_url, + event_id, + event_author_account_id, + event_description, + event_start, + event_end, + event_invitee_count_maximum, + event_is_archived, + event_is_in_person, + event_is_remote, + event_location, + event_name, + event_slug, + event_url, + event_visibility +FROM maevsi.invitation_flat WHERE FALSE; + +ROLLBACK; diff --git a/test/data.patch b/test/data.patch new file mode 100644 index 00000000..cc09630c --- /dev/null +++ b/test/data.patch @@ -0,0 +1,237 @@ +diff --git a/src/deploy/data_test.sql b/src/deploy/data_test.sql +new file mode 100644 +index 0000000..5276242 +--- /dev/null ++++ b/src/deploy/data_test.sql +@@ -0,0 +1,191 @@ ++-- Deploy maevsi:data_test to pg ++BEGIN; ++ ++DO $$ ++DECLARE _account_id_jonas UUID; ++ ++_account_id_peter UUID; ++ ++_contact_id_jonas UUID; ++ ++_contact_id_peter UUID; ++ ++BEGIN ++SELECT maevsi.account_registration( ++ 'jonas', ++ 'mail+sqitch-1@maev.si', ++ 'testtest', ++ 'en' ++ ) INTO _account_id_jonas; ++ ++PERFORM maevsi.account_email_address_verification( ++ ( ++ SELECT email_address_verification ++ FROM maevsi_private.account ++ WHERE id = _account_id_jonas ++ ) ++); ++ ++SELECT maevsi.account_registration( ++ 'peter', ++ 'mail+sqitch-2@maev.si', ++ 'testtest', ++ 'de' ++ ) INTO _account_id_peter; ++ ++SELECT id ++FROM maevsi.contact ++WHERE account_id = _account_id_jonas ++ AND author_account_id = _account_id_jonas INTO _contact_id_jonas; ++ ++SELECT id ++FROM maevsi.contact ++WHERE account_id = _account_id_peter ++ AND author_account_id = _account_id_peter INTO _contact_id_peter; ++ ++INSERT INTO maevsi.contact ( ++ "id", ++ "address", ++ "email_address", ++ "first_name", ++ "last_name", ++ "author_account_id" ++ ) ++VALUES ( ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a5a', ++ e'A B\n12345 D', ++ 'mail+sqitch-3@maev.si', ++ 'Max', ++ 'Mustermann', ++ _account_id_jonas ++ ); ++ ++INSERT INTO maevsi.event ( ++ "id", ++ "name", ++ "slug", ++ "visibility", ++ "invitee_count_maximum", ++ "author_account_id", ++ "description", ++ "start", ++ "end" ++ ) ++VALUES ( ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a6a', ++ 'Limited', ++ 'limited', ++ 'public', ++ 2, ++ _account_id_jonas, ++ 'Event with limited capacity.', ++ '2020-11-23 02:00:00.000000+00', ++ '2020-11-23 09:00:00.000000+00' ++ ); ++ ++INSERT INTO maevsi.event ( ++ "id", ++ "name", ++ "slug", ++ "visibility", ++ "author_account_id", ++ "start", ++ "end" ++ ) ++VALUES ( ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a6b', ++ 'Foreign Invited', ++ 'foreign-invited', ++ 'public', ++ _account_id_peter, ++ '2020-11-27 03:54:29.090009+00', ++ '2020-11-27 05:56:23.090009+00' ++ ); ++ ++INSERT INTO maevsi.event ( ++ "id", ++ "name", ++ "slug", ++ "visibility", ++ "author_account_id", ++ "start", ++ "end" ++ ) ++VALUES ( ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a6c', ++ 'Foreign Uninvited', ++ 'foreign-uninvited', ++ 'public', ++ _account_id_peter, ++ '2020-11-27 03:54:29.090009+00', ++ '2020-11-27 05:56:23.090009+00' ++ ); ++ ++INSERT INTO maevsi.event ( ++ "id", ++ "name", ++ "slug", ++ "visibility", ++ "author_account_id", ++ "description", ++ "location", ++ "start" ++ ) ++VALUES ( ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a6d', ++ 'Private Party', ++ 'e2', ++ 'private', ++ _account_id_jonas, ++ 'Offices parties lasting outward nothing age few resolve. Impression to discretion understood to we interested he excellence. Him remarkably use projection collecting. Going about eat forty world has round miles. Attention affection at my preferred offending shameless me if agreeable. Life lain held calm and true neat she. Much feet each so went no from. Truth began maids linen an mr to after.', ++ 'Schutz- und Grillhütte Frommershausen, 34246 Vellmar', ++ '2019-11-27 03:54:29.090009+00' ++ ); ++ ++INSERT INTO maevsi.invitation ( ++ "id", ++ "event_id", ++ "contact_id", ++ "feedback", ++ "feedback_paper" ++ ) ++VALUES ( ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a7a', ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a6a', ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a5a', ++ 'accepted', ++ 'paper' ++ ); ++ ++INSERT INTO maevsi.invitation ( ++ "id", ++ "event_id", ++ "contact_id", ++ "feedback", ++ "feedback_paper" ++ ) ++VALUES ( ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a7b', ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a6d', ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a5a', ++ 'canceled', ++ 'digital' ++ ); ++ ++INSERT INTO maevsi.invitation ("id", "event_id", "contact_id") ++VALUES ( ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a7c', ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a6b', ++ _contact_id_jonas ++ ); ++ ++INSERT INTO maevsi.invitation ("id", "event_id", "contact_id") ++VALUES ( ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a7d', ++ '59462df6-10a9-11ea-bf8e-0f50c4d91a6a', ++ _contact_id_peter ++ ); ++ ++END $$; ++ ++COMMIT; +diff --git a/src/revert/data_test.sql b/src/revert/data_test.sql +new file mode 100644 +index 0000000..50ae98c +--- /dev/null ++++ b/src/revert/data_test.sql +@@ -0,0 +1,12 @@ ++-- Revert maevsi:data_test from pg ++ ++BEGIN; ++ ++DELETE FROM maevsi.profile_picture; ++DELETE FROM maevsi.upload; ++DELETE FROM maevsi.invitation; ++DELETE FROM maevsi.event; ++DELETE FROM maevsi.contact; ++DELETE FROM maevsi_private.account; ++ ++COMMIT; +diff --git a/src/sqitch.plan b/src/sqitch.plan +index e30d708..9c4498f 100644 +--- a/src/sqitch.plan ++++ b/src/sqitch.plan +@@ -88,3 +88,4 @@ table_event_category_mapping [schema_public table_event table_event_category] 19 + table_event_category_mapping_policy [schema_public table_event_category_mapping role_anonymous role_account table_event]1970-01-01T00:00:00Z marlon # Row level security policies for table table_event_category_mapping. + table_event_recommendation [schema_public table_account_public table_event] 1970-01-01T00:00:00Z marlon # Events recommended to a user account (M:N relationship). + table_event_recommendation_policy [schema_public table_event_recommendation role_account] 1970-01-01T00:00:00Z marlon # Row level security policies for table event_recommendation. ++data_test 1970-01-01T00:00:00Z Jonas Thelemann # Add test data. +diff --git a/src/verify/data_test.sql b/src/verify/data_test.sql +new file mode 100644 +index 0000000..274d00b +--- /dev/null ++++ b/src/verify/data_test.sql +@@ -0,0 +1,7 @@ ++-- Verify maevsi:data_test on pg ++ ++BEGIN; ++ ++ ++ ++ROLLBACK; diff --git a/schema/schema-update.sh b/test/schema/schema-update.sh similarity index 70% rename from schema/schema-update.sh rename to test/schema/schema-update.sh index 8425572a..19c94248 100755 --- a/schema/schema-update.sh +++ b/test/schema/schema-update.sh @@ -3,7 +3,7 @@ THIS=$(dirname "$(readlink -f "$0")") image=maevsi/sqitch -sudo docker build -t "$image:build" --target build "$THIS/.." # --no-cache --progress plain +sudo docker build -t "$image:build" --target test-build "$THIS/../.." # --no-cache --progress plain container_id="$(sudo docker create $image:build)" sudo docker cp "$container_id:/srv/app/schema.sql" "$THIS/schema.definition.sql" diff --git a/schema/schema.definition.sql b/test/schema/schema.definition.sql similarity index 80% rename from schema/schema.definition.sql rename to test/schema/schema.definition.sql index e7e2bc51..1005efd7 100644 --- a/schema/schema.definition.sql +++ b/test/schema/schema.definition.sql @@ -111,6 +111,27 @@ ALTER TYPE maevsi.achievement_type OWNER TO postgres; COMMENT ON TYPE maevsi.achievement_type IS 'Achievements that can be unlocked by users.'; +-- +-- Name: event_size; Type: TYPE; Schema: maevsi; Owner: postgres +-- + +CREATE TYPE maevsi.event_size AS ENUM ( + 'small', + 'medium', + 'large', + 'huge' +); + + +ALTER TYPE maevsi.event_size OWNER TO postgres; + +-- +-- Name: TYPE event_size; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON TYPE maevsi.event_size IS 'Possible event sizes: small, medium, large, huge.'; + + -- -- Name: jwt; Type: TYPE; Schema: maevsi; Owner: postgres -- @@ -198,6 +219,46 @@ ALTER TYPE maevsi.invitation_feedback_paper OWNER TO postgres; COMMENT ON TYPE maevsi.invitation_feedback_paper IS 'Possible choices on how to receive a paper invitation: none, paper, digital.'; +-- +-- Name: language; Type: TYPE; Schema: maevsi; Owner: postgres +-- + +CREATE TYPE maevsi.language AS ENUM ( + 'de', + 'en' +); + + +ALTER TYPE maevsi.language OWNER TO postgres; + +-- +-- Name: TYPE language; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON TYPE maevsi.language IS 'Supported ISO 639 language codes.'; + + +-- +-- Name: social_network; Type: TYPE; Schema: maevsi; Owner: postgres +-- + +CREATE TYPE maevsi.social_network AS ENUM ( + 'facebook', + 'instagram', + 'tiktok', + 'x' +); + + +ALTER TYPE maevsi.social_network OWNER TO postgres; + +-- +-- Name: TYPE social_network; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON TYPE maevsi.social_network IS 'Social networks.'; + + -- -- Name: account_delete(text); Type: FUNCTION; Schema: maevsi; Owner: postgres -- @@ -251,7 +312,7 @@ BEGIN RAISE 'Unknown verification code!' USING ERRCODE = 'no_data_found'; END IF; - IF (_account.email_address_verification_valid_until < NOW()) THEN + IF (_account.email_address_verification_valid_until < CURRENT_TIMESTAMP) THEN RAISE 'Verification code expired!' USING ERRCODE = 'object_not_in_prerequisite_state'; END IF; @@ -328,7 +389,7 @@ BEGIN RAISE 'Unknown reset code!' USING ERRCODE = 'no_data_found'; END IF; - IF (_account.password_reset_verification_valid_until < NOW()) THEN + IF (_account.password_reset_verification_valid_until < CURRENT_TIMESTAMP) THEN RAISE 'Reset code expired!' USING ERRCODE = 'object_not_in_prerequisite_state'; END IF; @@ -404,30 +465,30 @@ COMMENT ON FUNCTION maevsi.account_password_reset_request(email_address text, la CREATE FUNCTION maevsi.account_registration(username text, email_address text, password text, language text) RETURNS uuid LANGUAGE plpgsql STRICT SECURITY DEFINER - AS $_$ + AS $$ DECLARE _new_account_private maevsi_private.account; _new_account_public maevsi.account; _new_account_notify RECORD; BEGIN - IF (char_length($3) < 8) THEN + IF (char_length(account_registration.password) < 8) THEN RAISE 'Password too short!' USING ERRCODE = 'invalid_parameter_value'; END IF; - IF (EXISTS (SELECT 1 FROM maevsi.account WHERE account.username = $1)) THEN + IF (EXISTS (SELECT 1 FROM maevsi.account WHERE account.username = account_registration.username)) THEN RAISE 'An account with this username already exists!' USING ERRCODE = 'unique_violation'; END IF; - IF (EXISTS (SELECT 1 FROM maevsi_private.account WHERE account.email_address = $2)) THEN + IF (EXISTS (SELECT 1 FROM maevsi_private.account WHERE account.email_address = account_registration.email_address)) THEN RAISE 'An account with this email address already exists!' USING ERRCODE = 'unique_violation'; END IF; INSERT INTO maevsi_private.account(email_address, password_hash, last_activity) VALUES - ($2, maevsi.crypt($3, maevsi.gen_salt('bf')), NOW()) + (account_registration.email_address, maevsi.crypt(account_registration.password, maevsi.gen_salt('bf')), CURRENT_TIMESTAMP) RETURNING * INTO _new_account_private; INSERT INTO maevsi.account(id, username) VALUES - (_new_account_private.id, $1) + (_new_account_private.id, account_registration.username) RETURNING * INTO _new_account_public; SELECT @@ -443,13 +504,13 @@ BEGIN 'account_registration', jsonb_pretty(jsonb_build_object( 'account', row_to_json(_new_account_notify), - 'template', jsonb_build_object('language', $4) + 'template', jsonb_build_object('language', account_registration.language) )) ); RETURN _new_account_public.id; END; -$_$; +$$; ALTER FUNCTION maevsi.account_registration(username text, email_address text, password text, language text) OWNER TO postgres; @@ -545,7 +606,7 @@ DECLARE _achievement maevsi.achievement_type; _achievement_id UUID; BEGIN - _account_id := NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID; + _account_id := maevsi.invoker_account_id(); SELECT achievement FROM maevsi_private.achievement_code @@ -595,7 +656,7 @@ CREATE FUNCTION maevsi.authenticate(username text, password text) RETURNS maevsi DECLARE _account_id UUID; _jwt_id UUID := gen_random_uuid(); - _jwt_exp BIGINT := EXTRACT(EPOCH FROM ((SELECT date_trunc('second', NOW()::TIMESTAMP)) + COALESCE(current_setting('maevsi.jwt_expiry_duration', true), '1 day')::INTERVAL)); + _jwt_exp BIGINT := EXTRACT(EPOCH FROM ((SELECT date_trunc('second', CURRENT_TIMESTAMP::TIMESTAMP)) + COALESCE(current_setting('maevsi.jwt_expiry_duration', true), '1 day')::INTERVAL)); _jwt maevsi.jwt; BEGIN IF ($1 = '' AND $2 = '') THEN @@ -660,6 +721,7 @@ SET default_table_access_method = heap; CREATE TABLE maevsi.event ( id uuid DEFAULT gen_random_uuid() NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, author_account_id uuid NOT NULL, description text, "end" timestamp with time zone, @@ -699,6 +761,14 @@ COMMENT ON COLUMN maevsi.event.id IS '@omit create,update The event''s internal id.'; +-- +-- Name: COLUMN event.created_at; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event.created_at IS '@omit create,update +Timestamp of when the event was created, defaults to the current timestamp.'; + + -- -- Name: COLUMN event.author_account_id; Type: COMMENT; Schema: maevsi; Owner: postgres -- @@ -856,9 +926,9 @@ BEGIN ) ) OR ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND - "event".author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + "event".author_account_id = maevsi.invoker_account_id() ) OR "event".id IN (SELECT maevsi_private.events_invited()) ) @@ -919,7 +989,7 @@ BEGIN _jwt_id := current_setting('jwt.claims.id', true)::UUID; _jwt := ( _jwt_id, - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID, -- prevent empty string cast to UUID + maevsi.invoker_account_id(), -- prevent empty string cast to UUID current_setting('jwt.claims.account_username', true)::TEXT, current_setting('jwt.claims.exp', true)::BIGINT, (SELECT ARRAY(SELECT DISTINCT UNNEST(maevsi.invitation_claim_array() || $1) ORDER BY 1)), @@ -981,7 +1051,7 @@ CREATE FUNCTION maevsi.events_organized() RETURNS TABLE(event_id uuid) DECLARE account_id UUID; BEGIN - account_id := NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID; + account_id := maevsi.invoker_account_id(); RETURN QUERY SELECT id FROM maevsi.event @@ -1208,6 +1278,28 @@ ALTER FUNCTION maevsi.invitee_count(event_id uuid) OWNER TO postgres; COMMENT ON FUNCTION maevsi.invitee_count(event_id uuid) IS 'Returns the invitee count for an event.'; +-- +-- Name: invoker_account_id(); Type: FUNCTION; Schema: maevsi; Owner: postgres +-- + +CREATE FUNCTION maevsi.invoker_account_id() RETURNS uuid + LANGUAGE plpgsql STABLE STRICT SECURITY DEFINER + AS $$ +BEGIN + RETURN NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID; +END; +$$; + + +ALTER FUNCTION maevsi.invoker_account_id() OWNER TO postgres; + +-- +-- Name: FUNCTION invoker_account_id(); Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON FUNCTION maevsi.invoker_account_id() IS 'Returns the session''s account id.'; + + -- -- Name: jwt_refresh(uuid); Type: FUNCTION; Schema: maevsi; Owner: postgres -- @@ -1216,7 +1308,7 @@ CREATE FUNCTION maevsi.jwt_refresh(jwt_id uuid) RETURNS maevsi.jwt LANGUAGE plpgsql STRICT SECURITY DEFINER AS $_$ DECLARE - _epoch_now BIGINT := EXTRACT(EPOCH FROM (SELECT date_trunc('second', NOW()::TIMESTAMP))); + _epoch_now BIGINT := EXTRACT(EPOCH FROM (SELECT date_trunc('second', CURRENT_TIMESTAMP::TIMESTAMP))); _jwt maevsi.jwt; BEGIN SELECT (token).id, (token).account_id, (token).account_username, (token)."exp", (token).invitations, (token).role INTO _jwt @@ -1228,7 +1320,7 @@ BEGIN RETURN NULL; ELSE UPDATE maevsi_private.jwt - SET token.exp = EXTRACT(EPOCH FROM ((SELECT date_trunc('second', NOW()::TIMESTAMP)) + COALESCE(current_setting('maevsi.jwt_expiry_duration', true), '1 day')::INTERVAL)) + SET token.exp = EXTRACT(EPOCH FROM ((SELECT date_trunc('second', CURRENT_TIMESTAMP::TIMESTAMP)) + COALESCE(current_setting('maevsi.jwt_expiry_duration', true), '1 day')::INTERVAL)) WHERE id = $1; UPDATE maevsi_private.account @@ -1336,15 +1428,15 @@ CREATE FUNCTION maevsi.trigger_contact_update_account_id() RETURNS trigger BEGIN IF ( -- invoked without account it - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NULL + maevsi.invoker_account_id() IS NULL OR -- invoked with account it -- and ( -- updating own account's contact - OLD.account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + OLD.account_id = maevsi.invoker_account_id() AND - OLD.author_account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + OLD.author_account_id = maevsi.invoker_account_id() AND ( -- trying to detach from account @@ -1387,12 +1479,12 @@ BEGIN OLD.id = ANY (maevsi.invitation_claim_array()) OR ( - NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID IS NOT NULL + maevsi.invoker_account_id() IS NOT NULL AND OLD.contact_id IN ( SELECT id FROM maevsi.contact - WHERE contact.account_id = NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID + WHERE contact.account_id = maevsi.invoker_account_id() ) ) ) @@ -1406,6 +1498,8 @@ BEGIN THEN RAISE 'You''re only allowed to alter these rows: %!', whitelisted_cols USING ERRCODE = 'insufficient_privilege'; ELSE + NEW.updated_at = CURRENT_TIMESTAMP; + NEW.updated_by = maevsi.invoker_account_id(); RETURN NEW; END IF; END $$; @@ -1426,9 +1520,13 @@ COMMENT ON FUNCTION maevsi.trigger_invitation_update() IS 'Checks if the caller CREATE TABLE maevsi.upload ( id uuid DEFAULT gen_random_uuid() NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, account_id uuid NOT NULL, + name text, size_byte bigint NOT NULL, storage_key text, + type text DEFAULT 'image'::text NOT NULL, + CONSTRAINT upload_name_check CHECK (((char_length(name) > 0) AND (char_length(name) < 300))), CONSTRAINT upload_size_byte_check CHECK ((size_byte > 0)) ); @@ -1450,6 +1548,14 @@ COMMENT ON COLUMN maevsi.upload.id IS '@omit create,update The upload''s internal id.'; +-- +-- Name: COLUMN upload.created_at; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.upload.created_at IS '@omit create,update +Timestamp of when the upload was created, defaults to the current timestamp.'; + + -- -- Name: COLUMN upload.account_id; Type: COMMENT; Schema: maevsi; Owner: postgres -- @@ -1457,6 +1563,13 @@ The upload''s internal id.'; COMMENT ON COLUMN maevsi.upload.account_id IS 'The uploader''s account id.'; +-- +-- Name: COLUMN upload.name; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.upload.name IS 'The name of the uploaded file.'; + + -- -- Name: COLUMN upload.size_byte; Type: COMMENT; Schema: maevsi; Owner: postgres -- @@ -1471,6 +1584,13 @@ COMMENT ON COLUMN maevsi.upload.size_byte IS 'The upload''s size in bytes.'; COMMENT ON COLUMN maevsi.upload.storage_key IS 'The upload''s storage key.'; +-- +-- Name: COLUMN upload.type; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.upload.type IS 'The type of the uploaded file, default is ''image''.'; + + -- -- Name: upload_create(bigint); Type: FUNCTION; Schema: maevsi; Owner: postgres -- @@ -1523,7 +1643,7 @@ CREATE FUNCTION maevsi_private.account_email_address_verification_valid_until() NEW.email_address_verification_valid_until = NULL; ELSE IF ((OLD IS NULL) OR (OLD.email_address_verification IS DISTINCT FROM NEW.email_address_verification)) THEN - NEW.email_address_verification_valid_until = (SELECT (NOW() + INTERVAL '1 day')::TIMESTAMP); + NEW.email_address_verification_valid_until = (SELECT (CURRENT_TIMESTAMP + INTERVAL '1 day')::TIMESTAMP); END IF; END IF; @@ -1553,7 +1673,7 @@ CREATE FUNCTION maevsi_private.account_password_reset_verification_valid_until() NEW.password_reset_verification_valid_until = NULL; ELSE IF ((OLD IS NULL) OR (OLD.password_reset_verification IS DISTINCT FROM NEW.password_reset_verification)) THEN - NEW.password_reset_verification_valid_until = (SELECT (NOW() + INTERVAL '2 hours')::TIMESTAMP); + NEW.password_reset_verification_valid_until = (SELECT (CURRENT_TIMESTAMP + INTERVAL '2 hours')::TIMESTAMP); END IF; END IF; @@ -1581,7 +1701,7 @@ CREATE FUNCTION maevsi_private.events_invited() RETURNS TABLE(event_id uuid) DECLARE jwt_account_id UUID; BEGIN - jwt_account_id := NULLIF(current_setting('jwt.claims.account_id', true), '')::UUID; + jwt_account_id := maevsi.invoker_account_id(); RETURN QUERY SELECT i.event_id FROM maevsi.invitation i @@ -2015,6 +2135,122 @@ COMMENT ON COLUMN maevsi.account_block.created_at IS '@omit create,update,delete The timestamp when the blocking was created.'; +-- +-- Name: account_interest; Type: TABLE; Schema: maevsi; Owner: postgres +-- + +CREATE TABLE maevsi.account_interest ( + account_id uuid NOT NULL, + category text NOT NULL +); + + +ALTER TABLE maevsi.account_interest OWNER TO postgres; + +-- +-- Name: TABLE account_interest; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON TABLE maevsi.account_interest IS 'Event categories a user account is interested in (M:N relationship).'; + + +-- +-- Name: COLUMN account_interest.account_id; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.account_interest.account_id IS 'A user account id.'; + + +-- +-- Name: COLUMN account_interest.category; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.account_interest.category IS 'An event category.'; + + +-- +-- Name: account_preference_event_size; Type: TABLE; Schema: maevsi; Owner: postgres +-- + +CREATE TABLE maevsi.account_preference_event_size ( + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + account_id uuid NOT NULL, + event_size maevsi.event_size NOT NULL +); + + +ALTER TABLE maevsi.account_preference_event_size OWNER TO postgres; + +-- +-- Name: TABLE account_preference_event_size; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON TABLE maevsi.account_preference_event_size IS 'Table for the user accounts'' preferred event sizes (M:N relationship).'; + + +-- +-- Name: COLUMN account_preference_event_size.created_at; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.account_preference_event_size.created_at IS '@omit create,update +Timestamp of when the event size preference was created, defaults to the current timestamp.'; + + +-- +-- Name: COLUMN account_preference_event_size.account_id; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.account_preference_event_size.account_id IS 'The account''s internal id.'; + + +-- +-- Name: COLUMN account_preference_event_size.event_size; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.account_preference_event_size.event_size IS 'A preferred event sized'; + + +-- +-- Name: account_social_network; Type: TABLE; Schema: maevsi; Owner: postgres +-- + +CREATE TABLE maevsi.account_social_network ( + account_id uuid NOT NULL, + social_network maevsi.social_network NOT NULL, + social_network_username text NOT NULL +); + + +ALTER TABLE maevsi.account_social_network OWNER TO postgres; + +-- +-- Name: TABLE account_social_network; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON TABLE maevsi.account_social_network IS 'Links accounts to their social media profiles. Each entry represents a specific social network and associated username for an account.'; + + +-- +-- Name: COLUMN account_social_network.account_id; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.account_social_network.account_id IS 'The unique identifier of the account.'; + + +-- +-- Name: COLUMN account_social_network.social_network; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.account_social_network.social_network IS 'The social network to which the account is linked.'; + + +-- +-- Name: COLUMN account_social_network.social_network_username; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.account_social_network.social_network_username IS 'The username of the account on the specified social network.'; + + -- -- Name: achievement; Type: TABLE; Schema: maevsi; Owner: postgres -- @@ -2071,20 +2307,26 @@ COMMENT ON COLUMN maevsi.achievement.level IS 'The achievement unlock''s level.' CREATE TABLE maevsi.contact ( id uuid DEFAULT gen_random_uuid() NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, account_id uuid, address text, author_account_id uuid NOT NULL, email_address text, email_address_hash text GENERATED ALWAYS AS (md5(lower("substring"(email_address, '\S(?:.*\S)*'::text)))) STORED, first_name text, + language maevsi.language, last_name text, + nickname text, phone_number text, + timezone text, url text, CONSTRAINT contact_address_check CHECK (((char_length(address) > 0) AND (char_length(address) < 300))), CONSTRAINT contact_email_address_check CHECK ((char_length(email_address) < 255)), CONSTRAINT contact_first_name_check CHECK (((char_length(first_name) > 0) AND (char_length(first_name) < 100))), CONSTRAINT contact_last_name_check CHECK (((char_length(last_name) > 0) AND (char_length(last_name) < 100))), + CONSTRAINT contact_nickname_check CHECK (((char_length(nickname) > 0) AND (char_length(nickname) < 100))), CONSTRAINT contact_phone_number_check CHECK ((phone_number ~ '^\+(?:[0-9] ?){6,14}[0-9]$'::text)), + CONSTRAINT contact_timezone_check CHECK ((timezone ~ '^([+-](0[0-9]|1[0-4]):[0-5][0-9]|Z)$'::text)), CONSTRAINT contact_url_check CHECK (((char_length(url) < 300) AND (url ~ '^https:\/\/'::text))) ); @@ -2106,6 +2348,14 @@ COMMENT ON COLUMN maevsi.contact.id IS '@omit create,update The contact''s internal id.'; +-- +-- Name: COLUMN contact.created_at; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.contact.created_at IS '@omit create,update +Timestamp of when the contact was created, defaults to the current timestamp.'; + + -- -- Name: COLUMN contact.account_id; Type: COMMENT; Schema: maevsi; Owner: postgres -- @@ -2149,6 +2399,13 @@ The contact''s email address''s md5 hash.'; COMMENT ON COLUMN maevsi.contact.first_name IS 'The contact''s first name.'; +-- +-- Name: COLUMN contact.language; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.contact.language IS 'The contact''s language.'; + + -- -- Name: COLUMN contact.last_name; Type: COMMENT; Schema: maevsi; Owner: postgres -- @@ -2156,11 +2413,25 @@ COMMENT ON COLUMN maevsi.contact.first_name IS 'The contact''s first name.'; COMMENT ON COLUMN maevsi.contact.last_name IS 'The contact''s last name.'; +-- +-- Name: COLUMN contact.nickname; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.contact.nickname IS 'The contact''s nickname.'; + + -- -- Name: COLUMN contact.phone_number; Type: COMMENT; Schema: maevsi; Owner: postgres -- -COMMENT ON COLUMN maevsi.contact.phone_number IS 'The contact''s international phone number.'; +COMMENT ON COLUMN maevsi.contact.phone_number IS 'The contact''s international phone number in E.164 format (https://wikipedia.org/wiki/E.164).'; + + +-- +-- Name: COLUMN contact.timezone; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.contact.timezone IS 'The contact''s ISO 8601 timezone, e.g. `+02:00`, `-05:30` or `Z`.'; -- @@ -2170,12 +2441,104 @@ COMMENT ON COLUMN maevsi.contact.phone_number IS 'The contact''s international p COMMENT ON COLUMN maevsi.contact.url IS 'The contact''s website url.'; +-- +-- Name: event_category; Type: TABLE; Schema: maevsi; Owner: postgres +-- + +CREATE TABLE maevsi.event_category ( + category text NOT NULL +); + + +ALTER TABLE maevsi.event_category OWNER TO postgres; + +-- +-- Name: TABLE event_category; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON TABLE maevsi.event_category IS 'Event categories.'; + + +-- +-- Name: COLUMN event_category.category; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_category.category IS 'A category name.'; + + +-- +-- Name: event_category_mapping; Type: TABLE; Schema: maevsi; Owner: postgres +-- + +CREATE TABLE maevsi.event_category_mapping ( + event_id uuid NOT NULL, + category text NOT NULL +); + + +ALTER TABLE maevsi.event_category_mapping OWNER TO postgres; + +-- +-- Name: TABLE event_category_mapping; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON TABLE maevsi.event_category_mapping IS 'Mapping events to categories (M:N relationship).'; + + +-- +-- Name: COLUMN event_category_mapping.event_id; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_category_mapping.event_id IS 'An event id.'; + + +-- +-- Name: COLUMN event_category_mapping.category; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_category_mapping.category IS 'A category name.'; + + +-- +-- Name: event_favourite; Type: TABLE; Schema: maevsi; Owner: postgres +-- + +CREATE TABLE maevsi.event_favourite ( + account_id uuid NOT NULL, + event_id uuid NOT NULL +); + + +ALTER TABLE maevsi.event_favourite OWNER TO postgres; + +-- +-- Name: TABLE event_favourite; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON TABLE maevsi.event_favourite IS 'The user accounts'' favourite events.'; + + +-- +-- Name: COLUMN event_favourite.account_id; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_favourite.account_id IS 'A user account id.'; + + +-- +-- Name: COLUMN event_favourite.event_id; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_favourite.event_id IS 'The ID of an event which the user marked as a favourite.'; + + -- -- Name: event_group; Type: TABLE; Schema: maevsi; Owner: postgres -- CREATE TABLE maevsi.event_group ( id uuid DEFAULT gen_random_uuid() NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, author_account_id uuid NOT NULL, description text, is_archived boolean DEFAULT false NOT NULL, @@ -2204,6 +2567,14 @@ COMMENT ON COLUMN maevsi.event_group.id IS '@omit create,update The event group''s internal id.'; +-- +-- Name: COLUMN event_group.created_at; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_group.created_at IS '@omit create,update +Timestamp of when the event group was created, defaults to the current timestamp.'; + + -- -- Name: COLUMN event_group.author_account_id; Type: COMMENT; Schema: maevsi; Owner: postgres -- @@ -2283,15 +2654,111 @@ COMMENT ON COLUMN maevsi.event_grouping.event_id IS 'The event grouping''s inter -- --- Name: invitation; Type: TABLE; Schema: maevsi; Owner: postgres +-- Name: event_recommendation; Type: TABLE; Schema: maevsi; Owner: postgres -- -CREATE TABLE maevsi.invitation ( - id uuid DEFAULT gen_random_uuid() NOT NULL, - contact_id uuid NOT NULL, +CREATE TABLE maevsi.event_recommendation ( + account_id uuid NOT NULL, event_id uuid NOT NULL, - feedback maevsi.invitation_feedback, - feedback_paper maevsi.invitation_feedback_paper + score real, + predicted_score real +); + + +ALTER TABLE maevsi.event_recommendation OWNER TO postgres; + +-- +-- Name: TABLE event_recommendation; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON TABLE maevsi.event_recommendation IS 'Events recommended to a user account (M:N relationship).'; + + +-- +-- Name: COLUMN event_recommendation.account_id; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_recommendation.account_id IS 'A user account id.'; + + +-- +-- Name: COLUMN event_recommendation.event_id; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_recommendation.event_id IS 'The predicted score of the recommendation.'; + + +-- +-- Name: COLUMN event_recommendation.score; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_recommendation.score IS 'An event id.'; + + +-- +-- Name: COLUMN event_recommendation.predicted_score; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_recommendation.predicted_score IS 'The score of the recommendation.'; + + +-- +-- Name: event_upload; Type: TABLE; Schema: maevsi; Owner: postgres +-- + +CREATE TABLE maevsi.event_upload ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + event_id uuid NOT NULL, + upload_id uuid NOT NULL +); + + +ALTER TABLE maevsi.event_upload OWNER TO postgres; + +-- +-- Name: TABLE event_upload; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON TABLE maevsi.event_upload IS 'An assignment of an uploaded content (e.g. an image) to an event.'; + + +-- +-- Name: COLUMN event_upload.id; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_upload.id IS '@omit create,update +The event''s internal id for which the invitation is valid.'; + + +-- +-- Name: COLUMN event_upload.event_id; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_upload.event_id IS '@omit update +The event''s internal id for which the invitation is valid.'; + + +-- +-- Name: COLUMN event_upload.upload_id; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.event_upload.upload_id IS '@omit update +The internal id of the uploaded content.'; + + +-- +-- Name: invitation; Type: TABLE; Schema: maevsi; Owner: postgres +-- + +CREATE TABLE maevsi.invitation ( + id uuid DEFAULT gen_random_uuid() NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at timestamp with time zone, + updated_by uuid, + contact_id uuid NOT NULL, + event_id uuid NOT NULL, + feedback maevsi.invitation_feedback, + feedback_paper maevsi.invitation_feedback_paper ); @@ -2312,6 +2779,30 @@ COMMENT ON COLUMN maevsi.invitation.id IS '@omit create,update The invitations''s internal id.'; +-- +-- Name: COLUMN invitation.created_at; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.invitation.created_at IS '@omit create,update +Timestamp of when the invitation was created, defaults to the current timestamp.'; + + +-- +-- Name: COLUMN invitation.updated_at; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.invitation.updated_at IS '@omit create,update +Timestamp of when the invitation was last updated.'; + + +-- +-- Name: COLUMN invitation.updated_by; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.invitation.updated_by IS '@omit create,update +The id of the account which last updated the invitation. `NULL` if the invitation was updated by an anonymous user.'; + + -- -- Name: COLUMN invitation.contact_id; Type: COMMENT; Schema: maevsi; Owner: postgres -- @@ -2340,6 +2831,54 @@ COMMENT ON COLUMN maevsi.invitation.feedback IS 'The invitation''s general feedb COMMENT ON COLUMN maevsi.invitation.feedback_paper IS 'The invitation''s paper feedback status.'; +-- +-- Name: invitation_flat; Type: VIEW; Schema: maevsi; Owner: postgres +-- + +CREATE VIEW maevsi.invitation_flat WITH (security_invoker='true') AS + SELECT invitation.id AS invitation_id, + invitation.contact_id AS invitation_contact_id, + invitation.event_id AS invitation_event_id, + invitation.feedback AS invitation_feedback, + invitation.feedback_paper AS invitation_feedback_paper, + contact.id AS contact_id, + contact.account_id AS contact_account_id, + contact.address AS contact_address, + contact.author_account_id AS contact_author_account_id, + contact.email_address AS contact_email_address, + contact.email_address_hash AS contact_email_address_hash, + contact.first_name AS contact_first_name, + contact.last_name AS contact_last_name, + contact.phone_number AS contact_phone_number, + contact.url AS contact_url, + event.id AS event_id, + event.author_account_id AS event_author_account_id, + event.description AS event_description, + event.start AS event_start, + event."end" AS event_end, + event.invitee_count_maximum AS event_invitee_count_maximum, + event.is_archived AS event_is_archived, + event.is_in_person AS event_is_in_person, + event.is_remote AS event_is_remote, + event.location AS event_location, + event.name AS event_name, + event.slug AS event_slug, + event.url AS event_url, + event.visibility AS event_visibility + FROM ((maevsi.invitation + JOIN maevsi.contact ON ((invitation.contact_id = contact.id))) + JOIN maevsi.event ON ((invitation.event_id = event.id))); + + +ALTER VIEW maevsi.invitation_flat OWNER TO postgres; + +-- +-- Name: VIEW invitation_flat; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON VIEW maevsi.invitation_flat IS 'View returning flattened invitations.'; + + -- -- Name: legal_term; Type: TABLE; Schema: maevsi; Owner: postgres -- @@ -2419,7 +2958,7 @@ ALTER TABLE maevsi.legal_term_acceptance OWNER TO postgres; -- Name: TABLE legal_term_acceptance; Type: COMMENT; Schema: maevsi; Owner: postgres -- -COMMENT ON TABLE maevsi.legal_term_acceptance IS 'Tracks each user account''s acceptance of legal terms and conditions.'; +COMMENT ON TABLE maevsi.legal_term_acceptance IS '@omit update,delete\nTracks each user account''s acceptance of legal terms and conditions.'; -- @@ -2500,12 +3039,12 @@ COMMENT ON COLUMN maevsi.profile_picture.upload_id IS 'The upload''s id.'; CREATE TABLE maevsi.report ( id uuid DEFAULT gen_random_uuid() NOT NULL, + created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, author_account_id uuid NOT NULL, reason text NOT NULL, target_account_id uuid, target_event_id uuid, target_upload_id uuid, - created_at timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, CONSTRAINT report_check CHECK ((num_nonnulls(target_account_id, target_event_id, target_upload_id) = 1)), CONSTRAINT report_reason_check CHECK (((char_length(reason) > 0) AND (char_length(reason) < 2000))) ); @@ -2529,6 +3068,14 @@ COMMENT ON COLUMN maevsi.report.id IS '@omit create Unique identifier for the report, generated randomly using UUIDs.'; +-- +-- Name: COLUMN report.created_at; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON COLUMN maevsi.report.created_at IS '@omit create +Timestamp of when the report was created, defaults to the current timestamp.'; + + -- -- Name: COLUMN report.author_account_id; Type: COMMENT; Schema: maevsi; Owner: postgres -- @@ -2564,14 +3111,6 @@ COMMENT ON COLUMN maevsi.report.target_event_id IS 'The ID of the event being re COMMENT ON COLUMN maevsi.report.target_upload_id IS 'The ID of the upload being reported, if applicable.'; --- --- Name: COLUMN report.created_at; Type: COMMENT; Schema: maevsi; Owner: postgres --- - -COMMENT ON COLUMN maevsi.report.created_at IS '@omit create -Timestamp of when the report was created, defaults to the current timestamp.'; - - -- -- Name: CONSTRAINT report_check ON report; Type: COMMENT; Schema: maevsi; Owner: postgres -- @@ -2592,11 +3131,12 @@ COMMENT ON CONSTRAINT report_reason_check ON maevsi.report IS 'Ensures the reaso CREATE TABLE maevsi_private.account ( id uuid DEFAULT gen_random_uuid() NOT NULL, - created timestamp without time zone DEFAULT now() NOT NULL, + birth_date date, + created timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, email_address text NOT NULL, email_address_verification uuid DEFAULT gen_random_uuid(), email_address_verification_valid_until timestamp without time zone, - last_activity timestamp without time zone DEFAULT now() NOT NULL, + last_activity timestamp without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, password_hash text NOT NULL, password_reset_verification uuid, password_reset_verification_valid_until timestamp without time zone, @@ -2621,6 +3161,13 @@ COMMENT ON TABLE maevsi_private.account IS 'Private account data.'; COMMENT ON COLUMN maevsi_private.account.id IS 'The account''s internal id.'; +-- +-- Name: COLUMN account.birth_date; Type: COMMENT; Schema: maevsi_private; Owner: postgres +-- + +COMMENT ON COLUMN maevsi_private.account.birth_date IS 'The account owner''s date of birth.'; + + -- -- Name: COLUMN account.created; Type: COMMENT; Schema: maevsi_private; Owner: postgres -- @@ -2768,7 +3315,7 @@ CREATE TABLE maevsi_private.notification ( channel text NOT NULL, is_acknowledged boolean, payload text NOT NULL, - "timestamp" timestamp with time zone DEFAULT now() NOT NULL, + "timestamp" timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, CONSTRAINT notification_payload_check CHECK ((octet_length(payload) <= 8000)) ); @@ -3329,6 +3876,14 @@ ALTER TABLE ONLY maevsi.account_block ADD CONSTRAINT account_block_pkey PRIMARY KEY (id); +-- +-- Name: account_interest account_interest_pkey; Type: CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.account_interest + ADD CONSTRAINT account_interest_pkey PRIMARY KEY (account_id, category); + + -- -- Name: account account_pkey; Type: CONSTRAINT; Schema: maevsi; Owner: postgres -- @@ -3337,6 +3892,29 @@ ALTER TABLE ONLY maevsi.account ADD CONSTRAINT account_pkey PRIMARY KEY (id); +-- +-- Name: account_preference_event_size account_preference_event_size_pkey; Type: CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.account_preference_event_size + ADD CONSTRAINT account_preference_event_size_pkey PRIMARY KEY (account_id, event_size); + + +-- +-- Name: account_social_network account_social_network_pkey; Type: CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.account_social_network + ADD CONSTRAINT account_social_network_pkey PRIMARY KEY (account_id, social_network); + + +-- +-- Name: CONSTRAINT account_social_network_pkey ON account_social_network; Type: COMMENT; Schema: maevsi; Owner: postgres +-- + +COMMENT ON CONSTRAINT account_social_network_pkey ON maevsi.account_social_network IS 'Ensures uniqueness by combining the account ID and social network, allowing each account to have a single entry per social network.'; + + -- -- Name: account account_username_key; Type: CONSTRAINT; Schema: maevsi; Owner: postgres -- @@ -3385,6 +3963,30 @@ ALTER TABLE ONLY maevsi.event ADD CONSTRAINT event_author_account_id_slug_key UNIQUE (author_account_id, slug); +-- +-- Name: event_category_mapping event_category_mapping_pkey; Type: CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_category_mapping + ADD CONSTRAINT event_category_mapping_pkey PRIMARY KEY (event_id, category); + + +-- +-- Name: event_category event_category_pkey; Type: CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_category + ADD CONSTRAINT event_category_pkey PRIMARY KEY (category); + + +-- +-- Name: event_favourite event_favourite_pkey; Type: CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_favourite + ADD CONSTRAINT event_favourite_pkey PRIMARY KEY (account_id, event_id); + + -- -- Name: event_group event_group_author_account_id_slug_key; Type: CONSTRAINT; Schema: maevsi; Owner: postgres -- @@ -3425,6 +4027,30 @@ ALTER TABLE ONLY maevsi.event ADD CONSTRAINT event_pkey PRIMARY KEY (id); +-- +-- Name: event_recommendation event_recommendation_pkey; Type: CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_recommendation + ADD CONSTRAINT event_recommendation_pkey PRIMARY KEY (account_id, event_id); + + +-- +-- Name: event_upload event_upload_event_id_upload_id_key; Type: CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_upload + ADD CONSTRAINT event_upload_event_id_upload_id_key UNIQUE (event_id, upload_id); + + +-- +-- Name: event_upload event_upload_pkey; Type: CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_upload + ADD CONSTRAINT event_upload_pkey PRIMARY KEY (id); + + -- -- Name: invitation invitation_event_id_contact_id_key; Type: CONSTRAINT; Schema: maevsi; Owner: postgres -- @@ -3798,6 +4424,38 @@ ALTER TABLE ONLY maevsi.account ADD CONSTRAINT account_id_fkey FOREIGN KEY (id) REFERENCES maevsi_private.account(id) ON DELETE CASCADE; +-- +-- Name: account_interest account_interest_account_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.account_interest + ADD CONSTRAINT account_interest_account_id_fkey FOREIGN KEY (account_id) REFERENCES maevsi.account(id) ON DELETE CASCADE; + + +-- +-- Name: account_interest account_interest_category_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.account_interest + ADD CONSTRAINT account_interest_category_fkey FOREIGN KEY (category) REFERENCES maevsi.event_category(category) ON DELETE CASCADE; + + +-- +-- Name: account_preference_event_size account_preference_event_size_account_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.account_preference_event_size + ADD CONSTRAINT account_preference_event_size_account_id_fkey FOREIGN KEY (account_id) REFERENCES maevsi.account(id); + + +-- +-- Name: account_social_network account_social_network_account_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.account_social_network + ADD CONSTRAINT account_social_network_account_id_fkey FOREIGN KEY (account_id) REFERENCES maevsi.account(id) ON DELETE CASCADE; + + -- -- Name: achievement achievement_account_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres -- @@ -3830,6 +4488,38 @@ ALTER TABLE ONLY maevsi.event ADD CONSTRAINT event_author_account_id_fkey FOREIGN KEY (author_account_id) REFERENCES maevsi.account(id); +-- +-- Name: event_category_mapping event_category_mapping_category_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_category_mapping + ADD CONSTRAINT event_category_mapping_category_fkey FOREIGN KEY (category) REFERENCES maevsi.event_category(category) ON DELETE CASCADE; + + +-- +-- Name: event_category_mapping event_category_mapping_event_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_category_mapping + ADD CONSTRAINT event_category_mapping_event_id_fkey FOREIGN KEY (event_id) REFERENCES maevsi.event(id) ON DELETE CASCADE; + + +-- +-- Name: event_favourite event_favourite_account_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_favourite + ADD CONSTRAINT event_favourite_account_id_fkey FOREIGN KEY (account_id) REFERENCES maevsi.account(id) ON DELETE CASCADE; + + +-- +-- Name: event_favourite event_favourite_event_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_favourite + ADD CONSTRAINT event_favourite_event_id_fkey FOREIGN KEY (event_id) REFERENCES maevsi.event(id) ON DELETE CASCADE; + + -- -- Name: event_group event_group_author_account_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres -- @@ -3854,6 +4544,38 @@ ALTER TABLE ONLY maevsi.event_grouping ADD CONSTRAINT event_grouping_event_id_fkey FOREIGN KEY (event_id) REFERENCES maevsi.event(id); +-- +-- Name: event_recommendation event_recommendation_account_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_recommendation + ADD CONSTRAINT event_recommendation_account_id_fkey FOREIGN KEY (account_id) REFERENCES maevsi.account(id) ON DELETE CASCADE; + + +-- +-- Name: event_recommendation event_recommendation_event_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_recommendation + ADD CONSTRAINT event_recommendation_event_id_fkey FOREIGN KEY (event_id) REFERENCES maevsi.event(id) ON DELETE CASCADE; + + +-- +-- Name: event_upload event_upload_event_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_upload + ADD CONSTRAINT event_upload_event_id_fkey FOREIGN KEY (event_id) REFERENCES maevsi.event(id); + + +-- +-- Name: event_upload event_upload_upload_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.event_upload + ADD CONSTRAINT event_upload_upload_id_fkey FOREIGN KEY (upload_id) REFERENCES maevsi.upload(id); + + -- -- Name: invitation invitation_contact_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres -- @@ -3870,6 +4592,14 @@ ALTER TABLE ONLY maevsi.invitation ADD CONSTRAINT invitation_event_id_fkey FOREIGN KEY (event_id) REFERENCES maevsi.event(id); +-- +-- Name: invitation invitation_updated_by_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE ONLY maevsi.invitation + ADD CONSTRAINT invitation_updated_by_fkey FOREIGN KEY (updated_by) REFERENCES maevsi.account(id); + + -- -- Name: legal_term_acceptance legal_term_acceptance_account_id_fkey; Type: FK CONSTRAINT; Schema: maevsi; Owner: postgres -- @@ -4016,6 +4746,60 @@ CREATE POLICY account_block_insert ON maevsi.account_block FOR INSERT WITH CHECK CREATE POLICY account_block_select ON maevsi.account_block FOR SELECT USING (((author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) OR (blocked_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))); +-- +-- Name: account_interest; Type: ROW SECURITY; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE maevsi.account_interest ENABLE ROW LEVEL SECURITY; + +-- +-- Name: account_interest account_interest_delete; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY account_interest_delete ON maevsi.account_interest FOR DELETE USING ((account_id = maevsi.invoker_account_id())); + + +-- +-- Name: account_interest account_interest_insert; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY account_interest_insert ON maevsi.account_interest FOR INSERT WITH CHECK ((account_id = maevsi.invoker_account_id())); + + +-- +-- Name: account_interest account_interest_select; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY account_interest_select ON maevsi.account_interest FOR SELECT USING ((account_id = maevsi.invoker_account_id())); + + +-- +-- Name: account_preference_event_size; Type: ROW SECURITY; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE maevsi.account_preference_event_size ENABLE ROW LEVEL SECURITY; + +-- +-- Name: account_preference_event_size account_preference_event_size_delete; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY account_preference_event_size_delete ON maevsi.account_preference_event_size FOR DELETE USING ((account_id = maevsi.invoker_account_id())); + + +-- +-- Name: account_preference_event_size account_preference_event_size_insert; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY account_preference_event_size_insert ON maevsi.account_preference_event_size FOR INSERT WITH CHECK ((account_id = maevsi.invoker_account_id())); + + +-- +-- Name: account_preference_event_size account_preference_event_size_select; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY account_preference_event_size_select ON maevsi.account_preference_event_size FOR SELECT USING ((account_id = maevsi.invoker_account_id())); + + -- -- Name: account account_select; Type: POLICY; Schema: maevsi; Owner: postgres -- @@ -4023,6 +4807,33 @@ CREATE POLICY account_block_select ON maevsi.account_block FOR SELECT USING (((a CREATE POLICY account_select ON maevsi.account FOR SELECT USING (true); +-- +-- Name: account_social_network; Type: ROW SECURITY; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE maevsi.account_social_network ENABLE ROW LEVEL SECURITY; + +-- +-- Name: account_social_network account_social_network_delete; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY account_social_network_delete ON maevsi.account_social_network FOR DELETE USING ((account_id = maevsi.invoker_account_id())); + + +-- +-- Name: account_social_network account_social_network_insert; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY account_social_network_insert ON maevsi.account_social_network FOR INSERT WITH CHECK ((account_id = maevsi.invoker_account_id())); + + +-- +-- Name: account_social_network account_social_network_update; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY account_social_network_update ON maevsi.account_social_network FOR UPDATE USING ((account_id = maevsi.invoker_account_id())); + + -- -- Name: achievement; Type: ROW SECURITY; Schema: maevsi; Owner: postgres -- @@ -4046,29 +4857,29 @@ ALTER TABLE maevsi.contact ENABLE ROW LEVEL SECURITY; -- Name: contact contact_delete; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY contact_delete ON maevsi.contact FOR DELETE USING ((((NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid IS NOT NULL) AND (author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) AND (account_id IS DISTINCT FROM (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))); +CREATE POLICY contact_delete ON maevsi.contact FOR DELETE USING (((maevsi.invoker_account_id() IS NOT NULL) AND (author_account_id = maevsi.invoker_account_id()) AND (account_id IS DISTINCT FROM maevsi.invoker_account_id()))); -- -- Name: contact contact_insert; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY contact_insert ON maevsi.contact FOR INSERT WITH CHECK (((author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) AND (NOT (account_id IN ( SELECT account_block.blocked_account_id +CREATE POLICY contact_insert ON maevsi.contact FOR INSERT WITH CHECK (((author_account_id = maevsi.invoker_account_id()) AND (NOT (account_id IN ( SELECT account_block.blocked_account_id FROM maevsi.account_block - WHERE (account_block.author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid)))))); + WHERE (account_block.author_account_id = maevsi.invoker_account_id())))))); -- -- Name: contact contact_select; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY contact_select ON maevsi.contact FOR SELECT USING ((((account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) AND (NOT (author_account_id IN ( SELECT account_block.blocked_account_id +CREATE POLICY contact_select ON maevsi.contact FOR SELECT USING ((((account_id = maevsi.invoker_account_id()) AND (NOT (author_account_id IN ( SELECT account_block.blocked_account_id FROM maevsi.account_block - WHERE (account_block.author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) + WHERE (account_block.author_account_id = maevsi.invoker_account_id()) UNION ALL SELECT account_block.author_account_id FROM maevsi.account_block - WHERE (account_block.blocked_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))))) OR ((author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) AND ((account_id IS NULL) OR (NOT (account_id IN ( SELECT account_block.blocked_account_id + WHERE (account_block.blocked_account_id = maevsi.invoker_account_id()))))) OR ((author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) AND ((account_id IS NULL) OR (NOT (account_id IN ( SELECT account_block.blocked_account_id FROM maevsi.account_block WHERE (account_block.author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) UNION ALL @@ -4081,9 +4892,9 @@ UNION ALL -- Name: contact contact_update; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY contact_update ON maevsi.contact FOR UPDATE USING (((author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) AND (NOT (account_id IN ( SELECT account_block.blocked_account_id +CREATE POLICY contact_update ON maevsi.contact FOR UPDATE USING (((author_account_id = maevsi.invoker_account_id()) AND (NOT (account_id IN ( SELECT account_block.blocked_account_id FROM maevsi.account_block - WHERE (account_block.author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid)))))); + WHERE (account_block.author_account_id = maevsi.invoker_account_id())))))); -- @@ -4092,6 +4903,52 @@ CREATE POLICY contact_update ON maevsi.contact FOR UPDATE USING (((author_accoun ALTER TABLE maevsi.event ENABLE ROW LEVEL SECURITY; +-- +-- Name: event_category_mapping; Type: ROW SECURITY; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE maevsi.event_category_mapping ENABLE ROW LEVEL SECURITY; + +-- +-- Name: event_category_mapping event_category_mapping_delete; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY event_category_mapping_delete ON maevsi.event_category_mapping FOR DELETE USING (((maevsi.invoker_account_id() IS NOT NULL) AND (( SELECT event.author_account_id + FROM maevsi.event + WHERE (event.id = event_category_mapping.event_id)) = maevsi.invoker_account_id()))); + + +-- +-- Name: event_category_mapping event_category_mapping_insert; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY event_category_mapping_insert ON maevsi.event_category_mapping FOR INSERT WITH CHECK (((maevsi.invoker_account_id() IS NOT NULL) AND (( SELECT event.author_account_id + FROM maevsi.event + WHERE (event.id = event_category_mapping.event_id)) = maevsi.invoker_account_id()))); + + +-- +-- Name: event_category_mapping event_category_mapping_select; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY event_category_mapping_select ON maevsi.event_category_mapping FOR SELECT USING ((((maevsi.invoker_account_id() IS NOT NULL) AND (( SELECT event.author_account_id + FROM maevsi.event + WHERE (event.id = event_category_mapping.event_id)) = maevsi.invoker_account_id())) OR (event_id IN ( SELECT maevsi_private.events_invited() AS events_invited)))); + + +-- +-- Name: event_favourite; Type: ROW SECURITY; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE maevsi.event_favourite ENABLE ROW LEVEL SECURITY; + +-- +-- Name: event_favourite event_favourite_select; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY event_favourite_select ON maevsi.event_favourite FOR SELECT USING (((maevsi.invoker_account_id() IS NOT NULL) AND (account_id = maevsi.invoker_account_id()))); + + -- -- Name: event_group; Type: ROW SECURITY; Schema: maevsi; Owner: postgres -- @@ -4108,7 +4965,20 @@ ALTER TABLE maevsi.event_grouping ENABLE ROW LEVEL SECURITY; -- Name: event event_insert; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY event_insert ON maevsi.event FOR INSERT WITH CHECK ((((NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid IS NOT NULL) AND (author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))); +CREATE POLICY event_insert ON maevsi.event FOR INSERT WITH CHECK (((maevsi.invoker_account_id() IS NOT NULL) AND (author_account_id = maevsi.invoker_account_id()))); + + +-- +-- Name: event_recommendation; Type: ROW SECURITY; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE maevsi.event_recommendation ENABLE ROW LEVEL SECURITY; + +-- +-- Name: event_recommendation event_recommendation_select; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY event_recommendation_select ON maevsi.event_recommendation FOR SELECT USING (((maevsi.invoker_account_id() IS NOT NULL) AND (account_id = maevsi.invoker_account_id()))); -- @@ -4117,18 +4987,52 @@ CREATE POLICY event_insert ON maevsi.event FOR INSERT WITH CHECK ((((NULLIF(curr CREATE POLICY event_select ON maevsi.event FOR SELECT USING ((((visibility = 'public'::maevsi.event_visibility) AND ((invitee_count_maximum IS NULL) OR (invitee_count_maximum > maevsi.invitee_count(id))) AND (NOT (author_account_id IN ( SELECT account_block.blocked_account_id FROM maevsi.account_block - WHERE (account_block.author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) + WHERE (account_block.author_account_id = maevsi.invoker_account_id()) UNION ALL SELECT account_block.author_account_id FROM maevsi.account_block - WHERE (account_block.blocked_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))))) OR (author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) OR (id IN ( SELECT maevsi_private.events_invited() AS events_invited)))); + WHERE (account_block.blocked_account_id = maevsi.invoker_account_id()))))) OR (author_account_id = maevsi.invoker_account_id()) OR (id IN ( SELECT maevsi_private.events_invited() AS events_invited)))); -- -- Name: event event_update; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY event_update ON maevsi.event FOR UPDATE USING ((((NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid IS NOT NULL) AND (author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))); +CREATE POLICY event_update ON maevsi.event FOR UPDATE USING (((maevsi.invoker_account_id() IS NOT NULL) AND (author_account_id = maevsi.invoker_account_id()))); + + +-- +-- Name: event_upload; Type: ROW SECURITY; Schema: maevsi; Owner: postgres +-- + +ALTER TABLE maevsi.event_upload ENABLE ROW LEVEL SECURITY; + +-- +-- Name: event_upload event_upload_delete; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY event_upload_delete ON maevsi.event_upload FOR DELETE USING ((event_id IN ( SELECT event.id + FROM maevsi.event + WHERE (event.author_account_id = maevsi.invoker_account_id())))); + + +-- +-- Name: event_upload event_upload_insert; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY event_upload_insert ON maevsi.event_upload FOR INSERT WITH CHECK (((event_id IN ( SELECT event.id + FROM maevsi.event + WHERE (event.author_account_id = maevsi.invoker_account_id()))) AND (upload_id IN ( SELECT upload.id + FROM maevsi.upload + WHERE (upload.account_id = maevsi.invoker_account_id()))))); + + +-- +-- Name: event_upload event_upload_select; Type: POLICY; Schema: maevsi; Owner: postgres +-- + +CREATE POLICY event_upload_select ON maevsi.event_upload FOR SELECT USING ((event_id IN ( SELECT event.id + FROM maevsi.event))); -- @@ -4150,12 +5054,12 @@ CREATE POLICY invitation_delete ON maevsi.invitation FOR DELETE USING ((event_id CREATE POLICY invitation_insert ON maevsi.invitation FOR INSERT WITH CHECK (((event_id IN ( SELECT maevsi.events_organized() AS events_organized)) AND ((maevsi.event_invitee_count_maximum(event_id) IS NULL) OR (maevsi.event_invitee_count_maximum(event_id) > maevsi.invitee_count(event_id))) AND (contact_id IN ( SELECT contact.id FROM maevsi.contact - WHERE (contact.author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) + WHERE (contact.author_account_id = maevsi.invoker_account_id()) EXCEPT SELECT c.id FROM (maevsi.contact c JOIN maevsi.account_block b ON (((c.account_id = b.blocked_account_id) AND (c.author_account_id = b.author_account_id)))) - WHERE (c.author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))))); + WHERE (c.author_account_id = maevsi.invoker_account_id()))))); -- @@ -4164,20 +5068,20 @@ EXCEPT CREATE POLICY invitation_select ON maevsi.invitation FOR SELECT USING (((id = ANY (maevsi.invitation_claim_array())) OR (contact_id IN ( SELECT contact.id FROM maevsi.contact - WHERE (contact.account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) + WHERE (contact.account_id = maevsi.invoker_account_id()) EXCEPT SELECT c.id FROM (maevsi.contact c JOIN maevsi.account_block b ON (((c.account_id = b.author_account_id) AND (c.author_account_id = b.blocked_account_id)))) - WHERE (c.account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))) OR ((event_id IN ( SELECT maevsi.events_organized() AS events_organized)) AND (contact_id IN ( SELECT c.id + WHERE (c.account_id = maevsi.invoker_account_id()))) OR ((event_id IN ( SELECT maevsi.events_organized() AS events_organized)) AND (contact_id IN ( SELECT c.id FROM maevsi.contact c WHERE ((c.account_id IS NULL) OR (NOT (c.account_id IN ( SELECT account_block.blocked_account_id FROM maevsi.account_block - WHERE (account_block.author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) + WHERE (account_block.author_account_id = maevsi.invoker_account_id()) UNION ALL SELECT account_block.author_account_id FROM maevsi.account_block - WHERE (account_block.blocked_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid)))))))))); + WHERE (account_block.blocked_account_id = maevsi.invoker_account_id())))))))))); -- @@ -4186,20 +5090,20 @@ EXCEPT CREATE POLICY invitation_update ON maevsi.invitation FOR UPDATE USING (((id = ANY (maevsi.invitation_claim_array())) OR (contact_id IN ( SELECT contact.id FROM maevsi.contact - WHERE (contact.account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) + WHERE (contact.account_id = maevsi.invoker_account_id()) EXCEPT SELECT c.id FROM (maevsi.contact c JOIN maevsi.account_block b ON (((c.account_id = b.author_account_id) AND (c.author_account_id = b.blocked_account_id)))) - WHERE (c.account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))) OR ((event_id IN ( SELECT maevsi.events_organized() AS events_organized)) AND (contact_id IN ( SELECT c.id + WHERE (c.account_id = maevsi.invoker_account_id()))) OR ((event_id IN ( SELECT maevsi.events_organized() AS events_organized)) AND (contact_id IN ( SELECT c.id FROM maevsi.contact c WHERE ((c.account_id IS NULL) OR (NOT (c.account_id IN ( SELECT account_block.blocked_account_id FROM maevsi.account_block - WHERE (account_block.author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid) + WHERE (account_block.author_account_id = maevsi.invoker_account_id()) UNION ALL SELECT account_block.author_account_id FROM maevsi.account_block - WHERE (account_block.blocked_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid)))))))))); + WHERE (account_block.blocked_account_id = maevsi.invoker_account_id())))))))))); -- @@ -4218,14 +5122,14 @@ ALTER TABLE maevsi.legal_term_acceptance ENABLE ROW LEVEL SECURITY; -- Name: legal_term_acceptance legal_term_acceptance_insert; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY legal_term_acceptance_insert ON maevsi.legal_term_acceptance FOR INSERT WITH CHECK ((((NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid IS NOT NULL) AND (account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))); +CREATE POLICY legal_term_acceptance_insert ON maevsi.legal_term_acceptance FOR INSERT WITH CHECK (((maevsi.invoker_account_id() IS NOT NULL) AND (account_id = maevsi.invoker_account_id()))); -- -- Name: legal_term_acceptance legal_term_acceptance_select; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY legal_term_acceptance_select ON maevsi.legal_term_acceptance FOR SELECT USING ((((NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid IS NOT NULL) AND (account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))); +CREATE POLICY legal_term_acceptance_select ON maevsi.legal_term_acceptance FOR SELECT USING (((maevsi.invoker_account_id() IS NOT NULL) AND (account_id = maevsi.invoker_account_id()))); -- @@ -4245,14 +5149,14 @@ ALTER TABLE maevsi.profile_picture ENABLE ROW LEVEL SECURITY; -- Name: profile_picture profile_picture_delete; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY profile_picture_delete ON maevsi.profile_picture FOR DELETE USING (((( SELECT CURRENT_USER AS "current_user") = 'maevsi_tusd'::name) OR (((NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid IS NOT NULL) AND (account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid)))); +CREATE POLICY profile_picture_delete ON maevsi.profile_picture FOR DELETE USING (((( SELECT CURRENT_USER AS "current_user") = 'maevsi_tusd'::name) OR ((maevsi.invoker_account_id() IS NOT NULL) AND (account_id = maevsi.invoker_account_id())))); -- -- Name: profile_picture profile_picture_insert; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY profile_picture_insert ON maevsi.profile_picture FOR INSERT WITH CHECK ((((NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid IS NOT NULL) AND (account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))); +CREATE POLICY profile_picture_insert ON maevsi.profile_picture FOR INSERT WITH CHECK (((maevsi.invoker_account_id() IS NOT NULL) AND (account_id = maevsi.invoker_account_id()))); -- @@ -4266,7 +5170,7 @@ CREATE POLICY profile_picture_select ON maevsi.profile_picture FOR SELECT USING -- Name: profile_picture profile_picture_update; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY profile_picture_update ON maevsi.profile_picture FOR UPDATE USING ((((NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid IS NOT NULL) AND (account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))); +CREATE POLICY profile_picture_update ON maevsi.profile_picture FOR UPDATE USING (((maevsi.invoker_account_id() IS NOT NULL) AND (account_id = maevsi.invoker_account_id()))); -- @@ -4279,14 +5183,14 @@ ALTER TABLE maevsi.report ENABLE ROW LEVEL SECURITY; -- Name: report report_insert; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY report_insert ON maevsi.report FOR INSERT WITH CHECK ((((NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid IS NOT NULL) AND (author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))); +CREATE POLICY report_insert ON maevsi.report FOR INSERT WITH CHECK (((maevsi.invoker_account_id() IS NOT NULL) AND (author_account_id = maevsi.invoker_account_id()))); -- -- Name: report report_select; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY report_select ON maevsi.report FOR SELECT USING ((((NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid IS NOT NULL) AND (author_account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid))); +CREATE POLICY report_select ON maevsi.report FOR SELECT USING (((maevsi.invoker_account_id() IS NOT NULL) AND (author_account_id = maevsi.invoker_account_id()))); -- @@ -4306,7 +5210,7 @@ CREATE POLICY upload_delete_using ON maevsi.upload FOR DELETE USING ((( SELECT C -- Name: upload upload_select_using; Type: POLICY; Schema: maevsi; Owner: postgres -- -CREATE POLICY upload_select_using ON maevsi.upload FOR SELECT USING (((( SELECT CURRENT_USER AS "current_user") = 'maevsi_tusd'::name) OR (((NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid IS NOT NULL) AND (account_id = (NULLIF(current_setting('jwt.claims.account_id'::text, true), ''::text))::uuid)) OR (id IN ( SELECT profile_picture.upload_id +CREATE POLICY upload_select_using ON maevsi.upload FOR SELECT USING (((( SELECT CURRENT_USER AS "current_user") = 'maevsi_tusd'::name) OR ((maevsi.invoker_account_id() IS NOT NULL) AND (account_id = maevsi.invoker_account_id())) OR (id IN ( SELECT profile_picture.upload_id FROM maevsi.profile_picture)))); @@ -4623,6 +5527,15 @@ GRANT ALL ON FUNCTION maevsi.invitee_count(event_id uuid) TO maevsi_account; GRANT ALL ON FUNCTION maevsi.invitee_count(event_id uuid) TO maevsi_anonymous; +-- +-- Name: FUNCTION invoker_account_id(); Type: ACL; Schema: maevsi; Owner: postgres +-- + +REVOKE ALL ON FUNCTION maevsi.invoker_account_id() FROM PUBLIC; +GRANT ALL ON FUNCTION maevsi.invoker_account_id() TO maevsi_account; +GRANT ALL ON FUNCTION maevsi.invoker_account_id() TO maevsi_anonymous; + + -- -- Name: FUNCTION jwt_refresh(jwt_id uuid); Type: ACL; Schema: maevsi; Owner: postgres -- @@ -4947,6 +5860,28 @@ GRANT SELECT,INSERT ON TABLE maevsi.account_block TO maevsi_account; GRANT SELECT ON TABLE maevsi.account_block TO maevsi_anonymous; +-- +-- Name: TABLE account_interest; Type: ACL; Schema: maevsi; Owner: postgres +-- + +GRANT SELECT,INSERT,DELETE ON TABLE maevsi.account_interest TO maevsi_account; + + +-- +-- Name: TABLE account_preference_event_size; Type: ACL; Schema: maevsi; Owner: postgres +-- + +GRANT SELECT,INSERT,DELETE ON TABLE maevsi.account_preference_event_size TO maevsi_account; + + +-- +-- Name: TABLE account_social_network; Type: ACL; Schema: maevsi; Owner: postgres +-- + +GRANT SELECT ON TABLE maevsi.account_social_network TO maevsi_anonymous; +GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE maevsi.account_social_network TO maevsi_account; + + -- -- Name: TABLE achievement; Type: ACL; Schema: maevsi; Owner: postgres -- @@ -4963,6 +5898,29 @@ GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE maevsi.contact TO maevsi_account; GRANT SELECT ON TABLE maevsi.contact TO maevsi_anonymous; +-- +-- Name: TABLE event_category; Type: ACL; Schema: maevsi; Owner: postgres +-- + +GRANT SELECT ON TABLE maevsi.event_category TO maevsi_anonymous; +GRANT SELECT ON TABLE maevsi.event_category TO maevsi_account; + + +-- +-- Name: TABLE event_category_mapping; Type: ACL; Schema: maevsi; Owner: postgres +-- + +GRANT SELECT ON TABLE maevsi.event_category_mapping TO maevsi_anonymous; +GRANT SELECT,INSERT,DELETE ON TABLE maevsi.event_category_mapping TO maevsi_account; + + +-- +-- Name: TABLE event_favourite; Type: ACL; Schema: maevsi; Owner: postgres +-- + +GRANT SELECT,INSERT,DELETE ON TABLE maevsi.event_favourite TO maevsi_account; + + -- -- Name: TABLE event_group; Type: ACL; Schema: maevsi; Owner: postgres -- @@ -4979,6 +5937,21 @@ GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE maevsi.event_grouping TO maevsi_accou GRANT SELECT ON TABLE maevsi.event_grouping TO maevsi_anonymous; +-- +-- Name: TABLE event_recommendation; Type: ACL; Schema: maevsi; Owner: postgres +-- + +GRANT SELECT,INSERT,DELETE ON TABLE maevsi.event_recommendation TO maevsi_account; + + +-- +-- Name: TABLE event_upload; Type: ACL; Schema: maevsi; Owner: postgres +-- + +GRANT SELECT,INSERT,DELETE ON TABLE maevsi.event_upload TO maevsi_account; +GRANT SELECT ON TABLE maevsi.event_upload TO maevsi_anonymous; + + -- -- Name: TABLE invitation; Type: ACL; Schema: maevsi; Owner: postgres -- @@ -4987,6 +5960,14 @@ GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE maevsi.invitation TO maevsi_account; GRANT SELECT,UPDATE ON TABLE maevsi.invitation TO maevsi_anonymous; +-- +-- Name: TABLE invitation_flat; Type: ACL; Schema: maevsi; Owner: postgres +-- + +GRANT SELECT ON TABLE maevsi.invitation_flat TO maevsi_account; +GRANT SELECT ON TABLE maevsi.invitation_flat TO maevsi_anonymous; + + -- -- Name: TABLE legal_term; Type: ACL; Schema: maevsi; Owner: postgres --