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

:heavy_minus_sign: remove `glight`

+30 -138
-1
gleam.toml
··· 28 28 argus = ">= 1.0.3 and < 2.0.0" 29 29 cors_builder = ">= 2.0.6 and < 3.0.0" 30 30 gleam_time = ">= 1.5.0 and < 2.0.0" 31 - glight = ">= 2.1.1 and < 3.0.0" 32 31 global_value = ">= 1.0.0 and < 2.0.0" 33 32 argv = ">= 1.0.2 and < 2.0.0" 34 33 simplifile = ">= 2.3.0 and < 3.0.0"
+1 -6
manifest.toml
··· 5 5 { name = "argus", version = "1.0.3", build_tools = ["gleam"], requirements = ["jargon"], otp_app = "argus", source = "hex", outer_checksum = "522A932BE147A78720A1AF95348544F604E900E788FF3D84DDF9F18DC7767819" }, 6 6 { name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" }, 7 7 { name = "backoff", version = "1.1.6", build_tools = ["rebar3"], requirements = [], otp_app = "backoff", source = "hex", outer_checksum = "CF0CFFF8995FB20562F822E5CC47D8CCF664C5ECDC26A684CBE85C225F9D7C39" }, 8 - { name = "birl", version = "1.8.0", build_tools = ["gleam"], requirements = ["gleam_regexp", "gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "2AC7BA26F998E3DFADDB657148BD5DDFE966958AD4D6D6957DD0D22E5B56C400" }, 9 8 { name = "cors_builder", version = "2.0.6", build_tools = ["gleam"], requirements = ["gleam_http", "gleam_stdlib", "mist", "wisp"], otp_app = "cors_builder", source = "hex", outer_checksum = "DBB16790F8FBF859242812FFC74E2719AC8F8D55F0A4CB5F4A064C87109B6021" }, 10 9 { name = "directories", version = "1.2.0", build_tools = ["gleam"], requirements = ["envoy", "gleam_stdlib", "platform", "simplifile"], otp_app = "directories", source = "hex", outer_checksum = "D13090CFCDF6759B87217E8DDD73A75903A700148A82C1D33799F333E249BF9E" }, 11 10 { name = "envoy", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "850DA9D29D2E5987735872A2B5C81035146D7FE19EFC486129E44440D03FD832" }, ··· 27 26 { name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" }, 28 27 { name = "gleeunit", version = "1.9.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "DA9553CE58B67924B3C631F96FE3370C49EB6D6DC6B384EC4862CC4AAA718F3C" }, 29 28 { name = "glexer", version = "2.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "splitter"], otp_app = "glexer", source = "hex", outer_checksum = "40A1FB0919FA080AD6C5809B4C7DBA545841CAAC8168FACDFA0B0667C22475CC" }, 30 - { name = "glight", version = "2.2.0", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_otp", "gleam_stdlib", "jsx", "logging"], otp_app = "glight", source = "hex", outer_checksum = "DB1FC2B770C86437A3932851AC8D7F8C32646E7CD4A8730A2B0AAA9B74E4AD90" }, 31 29 { name = "glisten", version = "8.0.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging", "telemetry"], otp_app = "glisten", source = "hex", outer_checksum = "534BB27C71FB9E506345A767C0D76B17A9E9199934340C975DC003C710E3692D" }, 32 30 { name = "global_value", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "global_value", source = "hex", outer_checksum = "23F74C91A7B819C43ABCCBF49DAD5BB8799D81F2A3736BA9A534BD47F309FF4F" }, 33 31 { name = "gramps", version = "6.0.0", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "8B7195978FBFD30B43DF791A8A272041B81E45D245314D7A41FC57237AA882A0" }, ··· 35 33 { name = "houdini", version = "1.2.0", build_tools = ["gleam"], requirements = [], otp_app = "houdini", source = "hex", outer_checksum = "5DB1053F1AF828049C2B206D4403C18970ABEF5C18671CA3C2D2ED0DD64F6385" }, 36 34 { name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" }, 37 35 { name = "jargon", version = "1.0.1", build_tools = ["rebar3"], requirements = [], otp_app = "jargon", source = "hex", outer_checksum = "E969FC304BBC3F69514161DF5F9B6BA71FEF8EACB3B209784BE15FF48EC68689" }, 38 - { name = "jsx", version = "3.1.0", build_tools = ["rebar3"], requirements = [], otp_app = "jsx", source = "hex", outer_checksum = "0C5CC8FDC11B53CC25CF65AC6705AD39E54ECC56D1C22E4ADB8F5A53FB9427F3" }, 39 36 { name = "justin", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "justin", source = "hex", outer_checksum = "7FA0C6DB78640C6DC5FBFD59BF3456009F3F8B485BF6825E97E1EB44E9A1E2CD" }, 40 37 { name = "logging", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "1098FBF10B54B44C2C7FDF0B01C1253CAFACDACABEFB4B0D027803246753E06D" }, 41 38 { name = "marceau", version = "1.3.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "2D1C27504BEF45005F5DFB18591F8610FB4BFA91744878210BDC464412EC44E9" }, ··· 47 44 { name = "pgo", version = "0.20.0", build_tools = ["rebar3"], requirements = ["backoff", "opentelemetry_api", "pg_types"], otp_app = "pgo", source = "hex", outer_checksum = "2F11E6649CEB38E569EF56B16BE1D04874AE5B11A02867080A2817CE423C683B" }, 48 45 { name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" }, 49 46 { name = "pog", version = "4.1.0", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_otp", "gleam_stdlib", "gleam_time", "pgo"], otp_app = "pog", source = "hex", outer_checksum = "E4AFBA39A5FAA2E77291836C9683ADE882E65A06AB28CA7D61AE7A3AD61EBBD5" }, 50 - { name = "ranger", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_yielder"], otp_app = "ranger", source = "hex", outer_checksum = "C8988E8F8CDBD3E7F4D8F2E663EF76490390899C2B2885A6432E942495B3E854" }, 51 47 { name = "simplifile", version = "2.3.1", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "957E0E5B75927659F1D2A1B7B75D7B9BA96FAA8D0C53EA71C4AD9CD0C6B848F6" }, 52 48 { name = "splitter", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "splitter", source = "hex", outer_checksum = "3DFD6B6C49E61EDAF6F7B27A42054A17CFF6CA2135FF553D0CB61C234D281DD0" }, 53 49 { name = "squirrel", version = "4.6.0", build_tools = ["gleam"], requirements = ["argv", "envoy", "eval", "filepath", "glam", "gleam_community_ansi", "gleam_crypto", "gleam_json", "gleam_regexp", "gleam_stdlib", "gleam_time", "glexer", "justin", "mug", "non_empty_list", "pog", "simplifile", "term_size", "tom", "tote", "youid"], otp_app = "squirrel", source = "hex", outer_checksum = "0ED10A868BDD1A5D4B68D99CD1C72DC3F23C6E36E16D33454C5F0C31BAC9CB1E" }, ··· 65 61 cors_builder = { version = ">= 2.0.6 and < 3.0.0" } 66 62 envoy = { version = ">= 1.0.2 and < 2.0.0" } 67 63 formal = { version = ">= 3.0.0 and < 4.0.0" } 64 + gleam_community_ansi = { version = ">= 1.4.3 and < 2.0.0" } 68 65 gleam_crypto = { version = ">= 1.5.1 and < 2.0.0" } 69 66 gleam_erlang = { version = ">= 1.3.0 and < 2.0.0" } 70 67 gleam_http = { version = ">= 4.1.1 and < 5.0.0" } ··· 73 70 gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" } 74 71 gleam_time = { version = ">= 1.5.0 and < 2.0.0" } 75 72 gleeunit = { version = ">= 1.0.0 and < 2.0.0" } 76 - glight = { version = ">= 2.1.1 and < 3.0.0" } 77 73 global_value = { version = ">= 1.0.0 and < 2.0.0" } 78 74 group_registry = { version = ">= 1.0.0 and < 2.0.0" } 79 75 mist = { version = ">= 5.0.3 and < 6.0.0" } ··· 82 78 squirrel = { version = ">= 4.4.1 and < 5.0.0" } 83 79 wisp = { version = ">= 2.0.0 and < 3.0.0" } 84 80 youid = { version = ">= 1.5.1 and < 2.0.0" } 85 - gleam_community_ansi = { version = ">= 1.4.3 and < 2.0.0" }
+1 -2
src/app.gleam
··· 12 12 import app/domain/admin/sql as admin_sql 13 13 import app/http_router 14 14 import app/supervision_tree 15 - import app/web 16 15 import app/web/context.{type Context, Context} 17 16 import app/web/socket 18 17 import envoy ··· 30 29 31 30 /// Application entry 32 31 pub fn main() -> Nil { 33 - web.configure_logger() 32 + wisp.configure_logger() 34 33 35 34 // Enviroment where the code is running on 36 35 let env = case envoy.get("SIGO_PROD") {
+3 -7
src/app/domain/admin/admin_update_user.gleam
··· 51 51 ) -> wisp.Response { 52 52 case query_database(req, ctx, body, user_id) { 53 53 Ok(body) -> wisp.json_response(body, 200) 54 - Error(err) -> handle_error(req, body, err) 54 + Error(err) -> handle_error(body, err) 55 55 } 56 56 } 57 57 ··· 92 92 NotFound(uuid.Uuid) 93 93 } 94 94 95 - fn handle_error( 96 - req: wisp.Request, 97 - body: RequestBody, 98 - err: AdminUpdateUserError, 99 - ) -> wisp.Response { 95 + fn handle_error(body: RequestBody, err: AdminUpdateUserError) -> wisp.Response { 100 96 case err { 101 - AccessControl(err) -> user.handle_access_control_error(req, err) 97 + AccessControl(err) -> user.handle_access_control_error(err) 102 98 103 99 InvalidUuid(id) -> wisp.bad_request("Usuário possui Uuid inválido: " <> id) 104 100
+3 -3
src/app/domain/brigade/register_new_brigade.gleam
··· 94 94 body body: RequestBody, 95 95 ) -> wisp.Response { 96 96 case query_database(request, ctx, body) { 97 - Error(err) -> handle_error(request, err) 97 + Error(err) -> handle_error(err) 98 98 Ok(body) -> wisp.json_response(body, 201) 99 99 } 100 100 } ··· 176 176 assigned_members 177 177 } 178 178 179 - fn handle_error(request request, err err: RegisterBrigadeError) -> wisp.Response { 179 + fn handle_error(err err: RegisterBrigadeError) -> wisp.Response { 180 180 case err { 181 181 InvalidUuid(id) -> wisp.bad_request("Usuário possui UUID inválido: " <> id) 182 182 DataBase(err) -> web.handle_database_error(err) 183 - AccessControl(err) -> user.handle_access_control_error(request, err) 183 + AccessControl(err) -> user.handle_access_control_error(err) 184 184 NotFound -> 185 185 "O Banco de Dados não retornou informações sobre a nova equipe após a inserção" 186 186 |> wisp.Text
+3 -3
src/app/domain/data_analysis/analysis_occurrence_volume.gleam
··· 50 50 use <- wisp.require_method(req, http.Get) 51 51 52 52 case query_database(req, ctx) { 53 - Error(err) -> handle_error(err, req) 53 + Error(err) -> handle_error(err) 54 54 Ok(body) -> wisp.json_response(body, 200) 55 55 } 56 56 } 57 57 58 - fn handle_error(err: AnalysisError, req: wisp.Request) -> wisp.Response { 58 + fn handle_error(err: AnalysisError) -> wisp.Response { 59 59 case err { 60 60 Database(err) -> web.handle_database_error(err) 61 - AccessControl(err) -> user.handle_access_control_error(req, err) 61 + AccessControl(err) -> user.handle_access_control_error(err) 62 62 } 63 63 } 64 64
-25
src/app/domain/role.gleam
··· 1 1 import gleam/dynamic/decode 2 2 import gleam/json 3 3 import gleam/string 4 - import glight 5 - import wisp 6 - import youid/uuid 7 4 8 5 pub type Role { 9 6 Sargeant ··· 68 65 Firefighter -> "firefighter" 69 66 Sargeant -> "sargeant" 70 67 } 71 - } 72 - 73 - /// 󰞏 Log when someone tries to access an endpoint that they dont have permission 74 - pub fn log_unauthorized_access_attempt( 75 - request request: wisp.Request, 76 - user_uuid user_uuid: uuid.Uuid, 77 - user_role user_role: Role, 78 - required required: List(Role), 79 - ) -> Nil { 80 - let required_roles = 81 - required 82 - |> json.array(to_json) 83 - |> json.to_string 84 - 85 - glight.logger() 86 - |> glight.with("path", request.path) 87 - |> glight.with("user", uuid.to_string(user_uuid)) 88 - |> glight.with("role", to_string(user_role)) 89 - |> glight.with("required", required_roles) 90 - |> glight.notice("unauthorized_access_attempt") 91 - 92 - Nil 93 68 } 94 69 95 70 pub fn to_json(role: Role) -> json.Json {
+3 -11
src/app/domain/user.gleam
··· 135 135 } 136 136 } 137 137 138 - pub fn handle_access_control_error(req: wisp.Request, err: AccessControlError) { 138 + pub fn handle_access_control_error(err: AccessControlError) { 139 139 case err { 140 140 Authentication(err) -> handle_authentication_error(err) 141 141 DataBase(err) -> web.handle_database_error(err) ··· 149 149 |> wisp.set_body(wisp.response(401), _) 150 150 151 151 AuthorizationError(user_uuid:, user_role:, authorized_roles:) -> { 152 - role.log_unauthorized_access_attempt( 153 - request: req, 154 - user_uuid:, 155 - user_role:, 156 - required: authorized_roles, 157 - ) 158 - 159 - [ 152 + json.object([ 160 153 #("id", json.string(uuid.to_string(user_uuid))), 161 154 #("user_role", json.string(role.to_string_pt_br(user_role:))), 162 155 #("required", json.array(authorized_roles, role.to_json)), 163 - ] 164 - |> json.object 156 + ]) 165 157 |> json.to_string 166 158 |> wisp.json_response(403) 167 159 }
+3 -3
src/app/domain/user/delete_user.gleam
··· 28 28 29 29 case query_database(req, ctx, user_id) { 30 30 Ok(deleted_user) -> wisp.json_response(deleted_user, 200) 31 - Error(err) -> handle_error(req, err) 31 + Error(err) -> handle_error(err) 32 32 } 33 33 } 34 34 ··· 46 46 CantDeleteSelf 47 47 } 48 48 49 - fn handle_error(req: wisp.Request, err: DeleteUserError) -> wisp.Response { 49 + fn handle_error(err: DeleteUserError) -> wisp.Response { 50 50 case err { 51 51 InvalidUserUuid(invalid_uuid) -> 52 52 wisp.bad_request("Usuário possui Uuid Inválido: " <> invalid_uuid) 53 53 UserNotFound(user_uuid) -> 54 54 wisp.bad_request("Usuário não encontrado: " <> uuid.to_string(user_uuid)) 55 - AccessControl(err) -> user.handle_access_control_error(req, err) 55 + AccessControl(err) -> user.handle_access_control_error(err) 56 56 DataBase(err) -> web.handle_database_error(err) 57 57 CantDeleteSelf -> wisp.bad_request("Um usuário não deve remover a si mesmo") 58 58 }
+3 -3
src/app/domain/user/get_all_user_profiles.gleam
··· 38 38 use <- wisp.require_method(req, http.Get) 39 39 40 40 case query_database(req, ctx) { 41 - Error(err) -> handle_error(req, err) 41 + Error(err) -> handle_error(err) 42 42 Ok(body) -> wisp.json_response(body, 200) 43 43 } 44 44 } ··· 50 50 DataBase(pog.QueryError) 51 51 } 52 52 53 - fn handle_error(req: wisp.Request, err: GetAllUsersError) -> wisp.Response { 53 + fn handle_error(err: GetAllUsersError) -> wisp.Response { 54 54 case err { 55 - AccessControl(err) -> user.handle_access_control_error(req, err) 55 + AccessControl(err) -> user.handle_access_control_error(err) 56 56 DataBase(err) -> web.handle_database_error(err) 57 57 } 58 58 }
-12
src/app/domain/user/login.gleam
··· 16 16 import gleam/list 17 17 import gleam/result 18 18 import gleam/time/duration 19 - import glight 20 19 import pog 21 20 import wisp 22 21 import youid/uuid ··· 131 130 } 132 131 } 133 132 134 - ///  Logs user registration 135 - fn log_login(login: RequestBody) -> Nil { 136 - glight.logger() 137 - |> glight.with("registration", login.registration) 138 - |> glight.info("login") 139 - 140 - Nil 141 - } 142 - 143 133 ///  Check if the provided password matches the one inside our database 144 134 /// Returns the user's UUID if successfull. 145 135 fn query_database( ··· 166 156 sql.Firefighter -> role.Firefighter 167 157 sql.Sargeant -> role.Sargeant 168 158 } 169 - 170 - log_login(data) 171 159 172 160 json.object([ 173 161 #("id", json.string(uuid.to_string(row.id))),
+4 -19
src/app/domain/user/signup.gleam
··· 17 17 import gleam/json 18 18 import gleam/list 19 19 import gleam/result 20 - import glight 21 20 import pog 22 21 import wisp 23 22 import youid/uuid ··· 47 46 48 47 fn handle_body(req: wisp.Request, body: SignUp, ctx: Context) -> wisp.Response { 49 48 case query_database(request: req, ctx:, signup: body) { 50 - Error(err) -> handle_error(req, err) 51 - Ok(new_user) -> { 52 - log_signup(body) 53 - wisp.json_response(new_user, 201) 54 - } 49 + Error(err) -> handle_error(err) 50 + Ok(new_user) -> wisp.json_response(new_user, 201) 55 51 } 56 52 } 57 53 ··· 168 164 }) 169 165 } 170 166 171 - fn log_signup(signup: SignUp) -> Nil { 172 - glight.logger() 173 - |> glight.with("name", signup.name) 174 - |> glight.with("registration", signup.registration) 175 - |> glight.with("phone_number", signup.phone_number) 176 - |> glight.with("email", signup.email) 177 - |> glight.info("signup") 178 - 179 - Nil 180 - } 181 - 182 167 fn handle_database_error(err: pog.QueryError) -> wisp.Response { 183 168 case err { 184 169 pog.ConstraintViolated(_, _, constraint: "user_account_registration_key") -> { ··· 203 188 } 204 189 } 205 190 206 - fn handle_error(req: wisp.Request, err: SignupError) { 191 + fn handle_error(err: SignupError) { 207 192 case err { 208 - AccessControl(err) -> user.handle_access_control_error(req, err) 193 + AccessControl(err) -> user.handle_access_control_error(err) 209 194 DataBase(err) -> handle_database_error(err) 210 195 211 196 HashError -> {
+3 -18
src/app/domain/user/update_user_password.gleam
··· 8 8 import gleam/http 9 9 import gleam/list 10 10 import gleam/result 11 - import glight 12 11 import pog 13 12 import wisp 14 13 import youid/uuid ··· 89 88 request request: wisp.Request, 90 89 ctx ctx: Context, 91 90 form_data form_data: RequestBody, 92 - ) -> Result(Nil, UpdatePasswordError) { 91 + ) -> Result(pog.Returned(Nil), UpdatePasswordError) { 93 92 use user_uuid <- result.try( 94 93 user.extract_uuid(request:, cookie_name: user.uuid_cookie_name) 95 94 |> result.map_error(AccessControl), ··· 128 127 |> result.replace_error(HashError), 129 128 ) 130 129 131 - // 󰚰 Update their password 132 - use _ <- result.map( 133 - sql.update_user_password(ctx.db, user_uuid, hashed_password.encoded_hash) 134 - |> result.map_error(DataBase), 135 - ) 136 - 137 - //  All done! 138 - log_password_update(user_uuid) 130 + sql.update_user_password(ctx.db, user_uuid, hashed_password.encoded_hash) 131 + |> result.map_error(DataBase) 139 132 } 140 133 141 134 fn query_user_password( ··· 201 194 ///  New password must be different from the old one 202 195 MustBeDifferent 203 196 } 204 - 205 - fn log_password_update(user_uuid: uuid.Uuid) -> Nil { 206 - glight.logger() 207 - |> glight.with("user_uuid", uuid.to_string(user_uuid)) 208 - |> glight.info("password_update") 209 - 210 - Nil 211 - }
+3 -3
src/app/domain/user/update_user_status.gleam
··· 44 44 is_active: Bool, 45 45 ) -> wisp.Response { 46 46 case query_database(req, ctx, user_id, is_active) { 47 - Error(err) -> handle_error(req, err) 47 + Error(err) -> handle_error(err) 48 48 Ok(resp) -> wisp.json_response(resp, 200) 49 49 } 50 50 } ··· 99 99 |> json.to_string 100 100 } 101 101 102 - fn handle_error(req: wisp.Request, err: UpdateUserStatusError) -> wisp.Response { 102 + fn handle_error(err: UpdateUserStatusError) -> wisp.Response { 103 103 case err { 104 - AccessControl(err) -> user.handle_access_control_error(req, err) 104 + AccessControl(err) -> user.handle_access_control_error(err) 105 105 DataBase(err) -> web.handle_database_error(err) 106 106 InvalidUuid(user_id) -> { 107 107 let body = "Usuário possui UUID inválido: " <> user_id
-22
src/app/web.gleam
··· 24 24 import gleam/list 25 25 import gleam/result 26 26 import gleam/string 27 - import glight 28 27 import pog 29 28 import wisp 30 29 ··· 35 34 context ctx: context.Context, 36 35 next handler: fn(wisp.Request) -> wisp.Response, 37 36 ) -> wisp.Response { 38 - let path = "/static" 39 37 let request = wisp.method_override(req) 40 38 41 39 use <- wisp.log_request(request) ··· 43 41 use request <- wisp.handle_head(request) 44 42 use request <- cors.wisp_middleware(request, cors_config(ctx)) 45 43 46 - use <- wisp.serve_static(request, under: path, from: ctx.static_directory) 47 44 handler(request) 48 - } 49 - 50 - ///  Configure the Erlang logger 51 - pub fn configure_logger() { 52 - glight.configure([ 53 - glight.Console, 54 - glight.File(log_directory() <> "/server.log"), 55 - ]) 56 - 57 - glight.set_log_level(glight.Debug) 58 - glight.set_is_color(True) 59 - } 60 - 61 - /// Access to log directory 62 - fn log_directory() -> String { 63 - let assert Ok(priv_directory) = wisp.priv_directory("app") 64 - as "Failed to access priv directory" 65 - 66 - priv_directory <> "/log" 67 45 } 68 46 69 47 fn cors_config(ctx: context.Context) -> cors.Cors {