numerus/deploy/user.sql

24 lines
608 B
MySQL
Raw Permalink Normal View History

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
-- Deploy numerus:user to pg
-- requires: roles
-- requires: schema_auth
-- requires: email
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
-- requires: language
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
begin;
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
set search_path to auth, numerus, public;
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
create table "user" (
user_id serial primary key,
email email not null unique,
name text not null,
password text not null check (length(password) < 512),
role name not null check (length(role) < 512),
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
lang_tag text not null default 'und' references language,
cookie text not null default '',
cookie_expires_at timestamptz not null default '-infinity'::timestamp,
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
created_at timestamptz not null default current_timestamp
);
commit;