mail based rss feed aggregator
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

add `is_admin` to user

ollie 30e2fa60 1eca98c8

+57 -18
+2 -1
db/migrations/20260331190734_initialize.sql
··· 18 18 ( 19 19 id uuid PRIMARY KEY NOT NULL UNIQUE, 20 20 email TEXT NOT NULL UNIQUE, 21 - password_hash BLOB NOT NULL 21 + password_hash BLOB NOT NULL, 22 + is_admin TINYINT NOT NULL 22 23 ); 23 24 24 25 CREATE TABLE subscriptions
+2 -1
db/schema.sql
··· 3 3 ( 4 4 id uuid PRIMARY KEY NOT NULL UNIQUE, 5 5 email TEXT NOT NULL UNIQUE, 6 - password_hash BLOB NOT NULL 6 + password_hash BLOB NOT NULL, 7 + is_admin TINYINT NOT NULL 7 8 ); 8 9 CREATE TABLE subscriptions 9 10 (
+18 -4
src/eater/database.gleam
··· 113 113 pub fn add_user( 114 114 user user: user.User, 115 115 into on: sqlight.Connection, 116 - ) -> Result(Nil, sqlight.Error) { 116 + ) -> Result(user.User, sqlight.Error) { 117 117 let #(sql, with) = 118 118 sql.add_user( 119 119 id: user.id |> uuid.to_bit_array, 120 120 email: user.email, 121 121 password_hash: user.password_hash, 122 + is_admin: case user.is_admin { 123 + True -> 1 124 + False -> 0 125 + }, 122 126 ) 123 127 124 128 let with = list.map(with, parrot_to_sqlight) 125 129 126 130 sqlight.query(sql, on:, with:, expecting: decode.success("")) 127 - |> result.replace(Nil) 131 + |> result.replace(user) 128 132 } 129 133 130 134 /// gets a list of all users from the database ··· 142 146 let assert Ok(id) = uuid.from_bit_array(user.id) 143 147 as "invalid UUID from db UUID column?!" 144 148 145 - user.User(id, user.email, user.password_hash) 149 + let is_admin = case user.is_admin { 150 + 1 -> True 151 + _ -> False 152 + } 153 + 154 + user.User(id, user.email, user.password_hash, is_admin:) 146 155 }) 147 156 |> Ok 148 157 } ··· 166 175 let assert Ok(id) = uuid.from_bit_array(user.id) 167 176 as "invalid UUID from db UUID column?!" 168 177 169 - user.User(id, user.email, user.password_hash) 178 + let is_admin = case user.is_admin { 179 + 1 -> True 180 + _ -> False 181 + } 182 + 183 + user.User(id, user.email, user.password_hash, is_admin:) 170 184 |> Ok 171 185 } 172 186 }
+18 -8
src/eater/sql.gleam
··· 70 70 id id: BitArray, 71 71 email email: String, 72 72 password_hash password_hash: BitArray, 73 + is_admin is_admin: Int, 73 74 ) { 74 75 let sql = 75 76 " 76 77 INSERT INTO users ( 77 78 id, 78 79 email, 79 - password_hash 80 + password_hash, 81 + is_admin 80 82 ) 81 83 values 82 - (?, ?, ?)" 84 + (?, ?, ?, ?)" 83 85 #(sql, [ 84 86 dev.ParamBitArray(id), 85 87 dev.ParamString(email), 86 88 dev.ParamBitArray(password_hash), 89 + dev.ParamInt(is_admin), 87 90 ]) 88 91 } 89 92 90 93 pub type AllUsers { 91 - AllUsers(id: BitArray, email: String, password_hash: BitArray) 94 + AllUsers(id: BitArray, email: String, password_hash: BitArray, is_admin: Int) 92 95 } 93 96 94 97 pub fn all_users() { 95 - let sql = "SELECT id, email, password_hash FROM users" 98 + let sql = "SELECT id, email, password_hash, is_admin FROM users" 96 99 #(sql, [], all_users_decoder()) 97 100 } 98 101 ··· 100 103 use id <- decode.field(0, decode.bit_array) 101 104 use email <- decode.field(1, decode.string) 102 105 use password_hash <- decode.field(2, decode.bit_array) 103 - decode.success(AllUsers(id:, email:, password_hash:)) 106 + use is_admin <- decode.field(3, decode.int) 107 + decode.success(AllUsers(id:, email:, password_hash:, is_admin:)) 104 108 } 105 109 106 110 pub type UserByEmail { 107 - UserByEmail(id: BitArray, email: String, password_hash: BitArray) 111 + UserByEmail( 112 + id: BitArray, 113 + email: String, 114 + password_hash: BitArray, 115 + is_admin: Int, 116 + ) 108 117 } 109 118 110 119 pub fn user_by_email(email email: String) { 111 120 let sql = 112 - "SELECT id, email, password_hash FROM users WHERE users.email = ? LIMIT 1" 121 + "SELECT id, email, password_hash, is_admin FROM users WHERE users.email = ? LIMIT 1" 113 122 #(sql, [dev.ParamString(email)], user_by_email_decoder()) 114 123 } 115 124 ··· 117 126 use id <- decode.field(0, decode.bit_array) 118 127 use email <- decode.field(1, decode.string) 119 128 use password_hash <- decode.field(2, decode.bit_array) 120 - decode.success(UserByEmail(id:, email:, password_hash:)) 129 + use is_admin <- decode.field(3, decode.int) 130 + decode.success(UserByEmail(id:, email:, password_hash:, is_admin:)) 121 131 } 122 132 123 133 pub type WasUpdateSentToUser {
+3 -2
src/eater/sql/users.sql
··· 17 17 INSERT INTO users ( 18 18 id, 19 19 email, 20 - password_hash 20 + password_hash, 21 + is_admin 21 22 ) 22 23 values 23 - (?, ?, ?); 24 + (?, ?, ?, ?); 24 25 25 26 26 27 -- name: AllUsers :many
+14 -2
src/eater/user.gleam
··· 17 17 import youid/uuid 18 18 19 19 pub type User { 20 - User(id: uuid.Uuid, email: String, password_hash: BitArray) 20 + User(id: uuid.Uuid, email: String, password_hash: BitArray, is_admin: Bool) 21 21 } 22 22 23 23 /// creates a new user with a uuid 24 24 /// 25 25 pub fn new(email email: String, password_hash password_hash: BitArray) { 26 - User(uuid.v7(), email:, password_hash:) 26 + User(uuid.v7(), email:, password_hash:, is_admin: False) 27 + } 28 + 29 + /// promote a user to admin status 30 + /// 31 + pub fn promote(user) { 32 + User(..user, is_admin: True) 33 + } 34 + 35 + /// demote an admin to user status 36 + /// 37 + pub fn demote(user) { 38 + User(..user, is_admin: False) 27 39 } 28 40 29 41 /// hash a string password