wip: currently rewriting the project as a full stack application tangled.org/kacaii.dev/sigo
gleam
at main 147 lines 3.7 kB view raw
1import app/domain/admin/sql 2import app/domain/user/sql as user_sql 3import app/web 4import app/web/context.{type Context} 5import argus 6import envoy 7import gleam/bool 8import gleam/dynamic/decode 9import gleam/http 10import gleam/list 11import gleam/result 12import pog 13import wisp 14 15const admin_registration = "000" 16 17const admin_password = "aluno" 18 19///  Generate the first admin user 20pub fn handle_request( 21 request req: wisp.Request, 22 ctx ctx: Context, 23) -> wisp.Response { 24 use <- wisp.require_method(req, http.Post) 25 use json_data <- wisp.require_json(req) 26 27 case decode.run(json_data, key_decoder()) { 28 Error(_) -> 29 wisp.unprocessable_content() 30 |> wisp.set_body(wisp.Text("Chave Secreta ausente")) 31 Ok(key) -> 32 case validate_admin_key(ctx, key) { 33 Error(err) -> handle_error(err) 34 Ok(_) -> insert_first_admin(ctx) 35 } 36 } 37} 38 39fn insert_first_admin(ctx: Context) -> wisp.Response { 40 let insert_result = { 41 use hashed_password <- result.try( 42 argus.hasher() 43 |> argus.hash(admin_password, argus.gen_salt()) 44 |> result.replace_error(HashError), 45 ) 46 47 use _ <- result.try( 48 user_sql.insert_new_user( 49 ctx.db, 50 "Drop Table da Silva", 51 admin_registration, 52 "0000000000", 53 "admin@email.com", 54 hashed_password.encoded_hash, 55 user_sql.Admin, 56 ) 57 |> result.map_error(DataBase), 58 ) 59 60 // No need to return anything from this function 61 Ok(Nil) 62 } 63 64 case insert_result { 65 Ok(_) -> 66 wisp.created() 67 |> wisp.set_body(wisp.Text("Primeiro admin criado com sucesso!")) 68 Error(err) -> handle_error(err) 69 } 70} 71 72fn handle_error(err: SetupAdminError) -> wisp.Response { 73 case err { 74 DataBaseNotEmpty -> 75 wisp.bad_request( 76 "O banco de dados precisa estar com a tabela de usuários vazia", 77 ) 78 79 DataBaseReturnedEmptyRow(_) -> 80 wisp.internal_server_error() 81 |> wisp.set_body(wisp.Text( 82 "Não foi possível consultar o número total de usuários cadastrados", 83 )) 84 85 HashError -> 86 wisp.internal_server_error() 87 |> wisp.set_body(wisp.Text( 88 "Ocorreu um erro ao encriptografar a senha do usuário", 89 )) 90 91 IncorrectRequestToken(_) -> 92 wisp.response(403) 93 |> wisp.set_body(wisp.Text("Token Inválido")) 94 95 MissingEnvToken -> 96 wisp.internal_server_error() 97 |> wisp.set_body(wisp.Text( 98 "A variável de ambiente necessária para o acesso a este endpoint se encontra ausente", 99 )) 100 101 DataBase(err) -> web.handle_database_error(err) 102 } 103} 104 105fn validate_admin_key(ctx: Context, key: String) -> Result(Nil, SetupAdminError) { 106 use admin_token <- result.try( 107 envoy.get("ADMIN_TOKEN") 108 |> result.replace_error(MissingEnvToken), 109 ) 110 111 use returned <- result.try( 112 sql.count_total_users(ctx.db) 113 |> result.map_error(DataBase), 114 ) 115 116 use row <- result.try( 117 list.first(returned.rows) 118 |> result.map_error(DataBaseReturnedEmptyRow), 119 ) 120 121 use <- bool.guard(when: row.total > 0, return: Error(DataBaseNotEmpty)) 122 case key == admin_token { 123 True -> Ok(Nil) 124 False -> Error(IncorrectRequestToken(key)) 125 } 126} 127 128fn key_decoder() -> decode.Decoder(String) { 129 use key <- decode.field("key", decode.string) 130 decode.success(key) 131} 132 133/// Setting up default admin can fail 134type SetupAdminError { 135 /// Submitted the wrong access token 136 IncorrectRequestToken(String) 137 /// Env has not been found 138 MissingEnvToken 139 /// An error occurred while accessing the DataBase 140 DataBase(pog.QueryError) 141 /// Failed to count how many users are registered 142 DataBaseReturnedEmptyRow(Nil) 143 /// Database needs to be empty 144 DataBaseNotEmpty 145 /// Failed to hash the admin password 146 HashError 147}