import client/user import gleam/dynamic/decode import gleam/http/request import gleam/json pub opaque type Token { Token( ///  JWT returned from the server and used for authentication. access_token: String, ///  Token type to be included in the request's headers, /// usually set to "bearer". token_type: String, ///  Field containing user information. user: user.User, ) } pub fn decoder() -> decode.Decoder(Token) { decode.one_of(decoder_in_english(), [decoder_in_portuguese()]) } /// How its represented in server-side fn decoder_in_portuguese() -> decode.Decoder(Token) { use access_token <- decode.field("access_token", decode.string) use token_type <- decode.field("token_type", token_type_decoder()) use user <- decode.field("cliente", user.decoder()) decode.success(Token(access_token:, token_type:, user:)) } /// How its represented in client-side fn decoder_in_english() -> decode.Decoder(Token) { use access_token <- decode.field("access_token", decode.string) use token_type <- decode.field("token_type", token_type_decoder()) use user <- decode.field("user", user.decoder()) decode.success(Token(access_token:, token_type:, user:)) } fn token_type_decoder() -> decode.Decoder(String) { use got <- decode.then(decode.string) let want = "bearer" case got == want { True -> decode.success(got) False -> decode.failure(got, "bearer") } } pub fn to_json(self: Token) -> json.Json { json.object([ #("access_token", json.string(self.access_token)), #("token_type", json.string(self.token_type)), #("user", user.to_json(self.user)), ]) } /// Returns the User assigned to the given token /// /// ```gleam /// user(token) /// // -> user.User(id:"123", role: role.Admin, ... ) /// ``` pub fn user(self: Token) -> user.User { self.user } /// Set the authorization header of a given request to include the token value. /// /// ```gleam /// let req = /// request.new() /// |> request.set_path("/api/wibble") /// |> request.set_method(http.Get) /// |> set_header(token, _) /// /// rsvp.send(req, Handler) /// ``` pub fn set_header(self: Token, req: request.Request(_)) -> request.Request(_) { let value = to_json(self) |> json.to_string request.set_header(req, "authorization", "bearer " <> value) }