wip: currently rewriting the project as a full stack application tangled.org/kacaii.dev/sigo
gleam

:bulb: mention when a function spawns a new process

+45 -42
+1 -2
src/app/domain/brigade.gleam
··· 2 2 import app/domain/user 3 3 import app/web/context.{type Context} 4 4 import app/web/socket/message as msg 5 - import gleam/erlang/process 6 5 import gleam/list 7 6 import gleam/result 8 7 import group_registry ··· 19 18 use returned <- result.map(sql.query_members_id(ctx.db, brigade_id)) 20 19 21 20 use row <- list.each(returned.rows) 22 - process.spawn(fn() { user.broadcast(registry, row.id, message) }) 21 + user.broadcast(registry, row.id, message) 23 22 }
+5 -2
src/app/domain/occurrence.gleam
··· 20 20 use returned <- result.map(sql.query_participants(ctx.db, occ_id)) 21 21 22 22 use row <- list.each(returned.rows) 23 - process.spawn(fn() { user.broadcast(registry, row.user_id, message) }) 23 + user.broadcast(registry, row.user_id, message) 24 24 } 25 25 26 26 ///  Notify subscribed users that a new occurrence has been added 27 + /// 28 + /// 󱓊 Spawns a new process 27 29 pub fn notify_new_occurrence( 28 30 registry registry: group_registry.GroupRegistry(msg.Msg), 29 31 new id: uuid.Uuid, ··· 34 36 35 37 use subject <- list.each(members) 36 38 process.spawn(fn() { 37 - process.send(subject, msg.Domain(msg.OccurrenceCreated(id:, category:))) 39 + let msg = msg.Domain(msg.OccurrenceCreated(id:, category:)) 40 + process.send(subject, msg) 38 41 }) 39 42 }
+26 -25
src/app/domain/user.gleam
··· 19 19 /// 󰗹 Authentication failed 20 20 Authentication(AuthenticationError) 21 21 ///  User is authentication but lacks permissions 22 - Authorization( 22 + AuthorizationError( 23 23 user_uuid: uuid.Uuid, 24 24 user_role: role.Role, 25 25 authorized_roles: List(role.Role), ··· 40 40 InvalidUUID(String) 41 41 } 42 42 43 - ///  Broadcast a message to an user 43 + ///  Broadcast an arbitrary message to an user 44 + /// 45 + /// 󱓊 Spawns a new process 44 46 pub fn broadcast( 45 47 registry: group_registry.GroupRegistry(msg.Msg), 46 48 user_id: uuid.Uuid, ··· 63 65 |> result.map_error(DataBase), 64 66 ) 65 67 66 - case list.first(returned.rows) { 67 - Error(_) -> Error(RoleNotFound) 68 - Ok(row) -> 69 - Ok(case row.user_role { 70 - sql.Admin -> role.Admin 71 - sql.Analyst -> role.Analyst 72 - sql.Captain -> role.Captain 73 - sql.Developer -> role.Developer 74 - sql.Firefighter -> role.Firefighter 75 - sql.Sargeant -> role.Sargeant 76 - }) 68 + use row <- result.map( 69 + list.first(returned.rows) 70 + |> result.replace_error(RoleNotFound), 71 + ) 72 + 73 + case row.user_role { 74 + sql.Admin -> role.Admin 75 + sql.Analyst -> role.Analyst 76 + sql.Captain -> role.Captain 77 + sql.Developer -> role.Developer 78 + sql.Firefighter -> role.Firefighter 79 + sql.Sargeant -> role.Sargeant 77 80 } 78 81 } 79 82 ··· 99 102 cookie_name cookie_name: String, 100 103 authorized_roles authorized_roles: List(role.Role), 101 104 ) -> Result(#(uuid.Uuid, role.Role), AccessControlError) { 102 - //  Indentify who is sending the request 103 105 use user_uuid <- result.try( 104 - extract_uuid(request:, cookie_name:) 106 + extract_uuid(request, cookie_name) 105 107 |> result.map_error(Authentication), 106 108 ) 107 109 ··· 111 113 // 󰈞 Check if that role has authorization 112 114 use user_role <- result.map( 113 115 list.find(authorized_roles, fn(authorized) { user_role == authorized }) 114 - |> result.replace_error(Authorization( 116 + |> result.replace_error(AuthorizationError( 115 117 user_uuid:, 116 118 user_role:, 117 119 authorized_roles:, ··· 124 126 pub fn handle_authentication_error(err: AuthenticationError) { 125 127 case err { 126 128 InvalidUUID(id) -> 127 - wisp.response(401) 128 - |> wisp.set_body(wisp.Text("ID de usuário inválido: " <> id)) 129 + wisp.Text("ID de usuário inválido: " <> id) 130 + |> wisp.set_body(wisp.response(401), _) 129 131 MissingCookie -> 130 - wisp.response(401) 131 - |> wisp.set_body(wisp.Text("Cookie de autenticação ausente")) 132 + "Cookie de autenticação ausente" 133 + |> wisp.Text 134 + |> wisp.set_body(wisp.response(401), _) 132 135 } 133 136 } 134 137 ··· 141 144 |> wisp.Text 142 145 |> wisp.set_body(wisp.response(401), _) 143 146 144 - InvalidRole(str) -> { 145 - let body = "Usuário autenticado possui cargo inválido: " <> str 146 - wisp.Text(body) 147 + InvalidRole(str) -> 148 + wisp.Text("Usuário autenticado possui cargo inválido: " <> str) 147 149 |> wisp.set_body(wisp.response(401), _) 148 - } 149 150 150 - Authorization(user_uuid:, user_role:, authorized_roles:) -> { 151 + AuthorizationError(user_uuid:, user_role:, authorized_roles:) -> { 151 152 role.log_unauthorized_access_attempt( 152 153 request: req, 153 154 user_uuid:,
+11 -13
src/app/domain/user/delete_user.gleam
··· 63 63 ctx: Context, 64 64 target_id: String, 65 65 ) -> Result(String, DeleteUserError) { 66 - // User that is going to be deleted 67 66 use target_user_uuid <- result.try( 68 67 uuid.from_string(target_id) 69 68 |> result.replace_error(InvalidUserUuid(target_id)), ··· 79 78 |> result.map_error(AccessControl), 80 79 ) 81 80 82 - // Check if the authenticated user is trying to delete theirself 83 81 case uuid.to_string(user_uuid) == target_id { 84 82 True -> Error(CantDeleteSelf) 85 83 False -> { ··· 88 86 |> result.map_error(DataBase), 89 87 ) 90 88 91 - case list.first(returned.rows) { 92 - Error(_) -> Error(UserNotFound(user_uuid)) 93 - Ok(row) -> { 94 - json.object([ 95 - #("id", json.string(uuid.to_string(row.id))), 96 - #("full_name", json.string(row.full_name)), 97 - ]) 98 - |> json.to_string 99 - |> Ok 100 - } 101 - } 89 + use row <- result.map( 90 + list.first(returned.rows) 91 + |> result.replace_error(UserNotFound(user_uuid)), 92 + ) 93 + 94 + [ 95 + #("id", json.string(uuid.to_string(row.id))), 96 + #("full_name", json.string(row.full_name)), 97 + ] 98 + |> json.object 99 + |> json.to_string 102 100 } 103 101 } 104 102 }
+2
src/app/web/socket.gleam
··· 74 74 } 75 75 76 76 ///  Broadcast a message to all active users 77 + /// 78 + /// 󱓊 Spawns a new process 77 79 pub fn broadcast( 78 80 registry registry: group_registry.GroupRegistry(msg.Msg), 79 81 message message: msg.Msg,