numerus/sqitch.plan

39 lines
4.6 KiB
Plaintext
Raw Normal View History

2023-01-12 18:37:48 +00:00
%syntax-version=1.0.0
Setup authentication schema and user relation User authentication is based on PostgREST’s[0]: There is a noninherit role, authenticator, whose function is only to switch to a different role according to the application’s session. Accordingly, this role has no permission for anything. The roles that this authentication can switch to are guest, invoicer, or admin. Guest is for anonymous users, when they need to login or register; invoicers are regular users; and admin are application’s administrators, that can change other user’s status, when they have to be removed or have they password changed, for example. The user relation is actually inaccessible to all roles and can only be used through a security definer function, login, so that passwords are not accessible from the application. I hesitated on what to use as the user’s primary key. The email seemed a good candiate, because it will be used for login. But something rubs me the wrong way. It is not that they can change because, despite what people on the Internet keeps parroting, they do not need to be “immutable”, PostgreSQL can cascade updates to foreign keys, and people do **not** change email addresses that ofter. What i **do** know is that email addresses should be unique in order to be used for login and password, hovewer i had to decide what “unique” means here, because the domain part is case insensitive, but the local part who knows? I made the arbitrary decision of assuming that the whole address is case sensitive. I have the feeling that this will bite me harder in the ass than using it as the primary key. [0]: https://postgrest.org/en/stable/auth.html
2023-01-13 00:43:20 +00:00
%project=numerus
%uri=https://numerus.tandem.blog/
2023-01-12 18:37:48 +00:00
roles 2023-01-12T18:42:16Z jordi fita mas <jordi@tandem.blog> # Add database roles
schema_auth [roles] 2023-01-12T19:15:55Z jordi fita mas <jordi@tandem.blog> # Add authentication schema
schema_public [roles] 2023-01-12T19:24:29Z jordi fita mas <jordi@tandem.blog> # Set privileges to public schema
schema_numerus [roles] 2023-01-12T22:57:22Z jordi fita mas <jordi@tandem.blog> # Add application schema
extension_citext [schema_public] 2023-01-12T23:03:33Z jordi fita mas <jordi@tandem.blog> # Add citext extension
email [schema_numerus extension_citext] 2023-01-12T23:09:59Z jordi fita mas <jordi@tandem.blog> # Add email domain
Add user_profile view to update the profile with form Since users do not have access to the auth scheme, i had to add a view that selects only the data that they can see of themselves (i.e., no password or cookie). I wanted to use the `request.user.id` setting that i set in check_cookie, but this would be bad because anyone can change that parameter and, since the view is created by the owner, could see and *change* the values of everyone just by knowing their id. Thus, now i use the cookie instead, because it is way harder to figure out, and if you already have it you can just set to your browser and the user is fucked anyway; the database can not help here. I **am** going to use the user id in row level security policies, but not the value coming for the setting but instaed the one in the `user_profile`, since it already is “derived” from the cookie, that’s why i added that column to the view. The profile includes the language, that i do not use it yet to switch the locale, so i had to add a relation of the available languages, for constraint purposes. There is no NULL language, and instead i added the “Undefined” language, with ‘und’ tag’, to represent “do not know/use content negotiation”. The languages in that relation are the same i used to have inside locale.go, because there is no point on having options for languages i do not have the translation for, so i now configure the list of available languages user in content negotiation from that relation. Finally, i have added all font from RemixIcon because that’s what we used in the design and i am going to use quite a lot of them. There is duplication in the views; i will address that in a different commit.
2023-01-22 01:23:09 +00:00
language [schema_numerus] 2023-01-21T20:55:49Z jordi fita mas <jordi@tandem.blog> # Add relation of available languages
user [roles schema_auth email language] 2023-01-12T23:44:03Z jordi fita mas <jordi@tandem.blog> # Create user relation
ensure_role_exists [schema_auth user] 2023-01-12T23:57:59Z jordi fita mas <jordi@tandem.blog> # Add trigger to ensure the users role exists
extension_pgcrypto [schema_auth] 2023-01-13T00:11:50Z jordi fita mas <jordi@tandem.blog> # Add pgcrypto extension
encrypt_password [schema_auth user extension_pgcrypto] 2023-01-13T00:14:30Z jordi fita mas <jordi@tandem.blog> # Add trigger to encrypt users password
login_attempt [schema_auth] 2023-01-17T14:05:49Z jordi fita mas <jordi@tandem.blog> # Add relation to log login attempts
login [roles schema_numerus schema_auth extension_pgcrypto email user login_attempt] 2023-01-13T00:32:32Z jordi fita mas <jordi@tandem.blog> # Add function to login
current_user_cookie [schema_numerus] 2023-01-21T20:16:28Z jordi fita mas <jordi@tandem.blog> # Add function to get the cookie of the current Numerus user
current_user_email [schema_numerus] 2023-01-23T19:11:53Z jordi fita mas <jordi@tandem.blog> # Add function to get the email of the current Numerus user
build_cookie [schema_numerus current_user_email current_user_cookie] 2023-01-23T19:46:13Z jordi fita mas <jordi@tandem.blog> # Add function to build the cookie for the current user
check_cookie [schema_public user build_cookie] 2023-01-17T17:48:49Z jordi fita mas <jordi@tandem.blog> # Add function to check if a user cookie is valid
logout [schema_auth current_user_email current_user_cookie user] 2023-01-17T19:10:21Z jordi fita mas <jordi@tandem.blog> # Add function to logout
set_cookie [schema_public check_cookie] 2023-01-19T11:00:22Z jordi fita mas <jordi@tandem.blog> # Add function to set the role based on the cookie
Add user_profile view to update the profile with form Since users do not have access to the auth scheme, i had to add a view that selects only the data that they can see of themselves (i.e., no password or cookie). I wanted to use the `request.user.id` setting that i set in check_cookie, but this would be bad because anyone can change that parameter and, since the view is created by the owner, could see and *change* the values of everyone just by knowing their id. Thus, now i use the cookie instead, because it is way harder to figure out, and if you already have it you can just set to your browser and the user is fucked anyway; the database can not help here. I **am** going to use the user id in row level security policies, but not the value coming for the setting but instaed the one in the `user_profile`, since it already is “derived” from the cookie, that’s why i added that column to the view. The profile includes the language, that i do not use it yet to switch the locale, so i had to add a relation of the available languages, for constraint purposes. There is no NULL language, and instead i added the “Undefined” language, with ‘und’ tag’, to represent “do not know/use content negotiation”. The languages in that relation are the same i used to have inside locale.go, because there is no point on having options for languages i do not have the translation for, so i now configure the list of available languages user in content negotiation from that relation. Finally, i have added all font from RemixIcon because that’s what we used in the design and i am going to use quite a lot of them. There is duplication in the views; i will address that in a different commit.
2023-01-22 01:23:09 +00:00
available_languages [schema_numerus language] 2023-01-21T21:11:08Z jordi fita mas <jordi@tandem.blog> # Add the initial available languages
user_profile [schema_numerus user current_user_email current_user_cookie] 2023-01-21T23:18:20Z jordi fita mas <jordi@tandem.blog> # Add view for user profile
change_password [schema_numerus user] 2023-01-23T20:22:45Z jordi fita mas <jordi@tandem.blog> # Add function to change the current users password
extension_vat [schema_public] 2023-01-24T10:28:17Z jordi fita mas <jordi@tandem.blog> # Add vat extension
extension_pg_libphonenumber [schema_public] 2023-01-24T13:50:14Z jordi fita mas <jordi@tandem.blog> # Add extension for phone numbers
extension_uri [schema_public] 2023-01-24T14:29:29Z jordi fita mas <jordi@tandem.blog> # Add extension for URIs
currency_code [schema_numerus] 2023-01-24T14:36:04Z jordi fita mas <jordi@tandem.blog> # Add the domain for currency code in ISO 4217
currency [schema_numerus currency_code] 2023-01-24T14:45:26Z jordi fita mas <jordi@tandem.blog> # Add the relation for currencies
available_currencies [schema_numerus currency] 2023-01-24T14:54:18Z jordi fita mas <jordi@tandem.blog> # Add the initial list of available currencies
country_code [schema_numerus] 2023-01-27T18:33:26Z jordi fita mas <jordi@tandem.blog> # Add domain for country codes
country [schema_numerus country_code] 2023-01-27T18:39:44Z jordi fita mas <jordi@tandem.blog> # Add the relation for countries
country_i18n [schema_numerus country_code language country] 2023-01-27T19:20:43Z jordi fita mas <jordi@tandem.blog> # Add table for localization of country names
available_countries [schema_numerus country] 2023-01-27T18:49:28Z jordi fita mas <jordi@tandem.blog> # Add the list of available countries
company [schema_numerus extension_vat email extension_pg_libphonenumber extension_uri currency_code currency country_code country] 2023-01-24T15:03:15Z jordi fita mas <jordi@tandem.blog> # Add the relation for companies
company_user [schema_numerus user company] 2023-01-24T17:50:06Z jordi fita mas <jordi@tandem.blog> # Add the relation of companies and their users