Skip to content

Commit

Permalink
bump decode; clean up / fix user module
Browse files Browse the repository at this point in the history
  • Loading branch information
rawhat committed Jul 7, 2024
1 parent b961aad commit 9ea7c18
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 52 deletions.
4 changes: 2 additions & 2 deletions manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ packages = [
{ name = "backoff", version = "1.1.6", build_tools = ["rebar3"], requirements = [], otp_app = "backoff", source = "hex", outer_checksum = "CF0CFFF8995FB20562F822E5CC47D8CCF664C5ECDC26A684CBE85C225F9D7C39" },
{ name = "bigben", version = "1.0.0", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "bigben", source = "hex", outer_checksum = "8E5A98FA6E981EEEF016C40F1CDFADA095927CAF6CAAA0C7E295EED02FC95947" },
{ name = "birl", version = "1.7.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "5C66647D62BCB11FE327E7A6024907C4A17954EF22865FE0940B54A852446D01" },
{ name = "decode", version = "0.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "decode", source = "hex", outer_checksum = "D31AAB8C8B9DDEFC62A41FA5FB1B1851A0C04E882ACF22A96462E8761844D145" },
{ name = "decode", version = "0.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "decode", source = "hex", outer_checksum = "965F517F67B8C172CA27A5C8E34C73733139E8C9E64736181B8C3179281F9793" },
{ name = "exception", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "F5580D584F16A20B7FCDCABF9E9BE9A2C1F6AC4F9176FA6DD0B63E3B20D450AA" },
{ name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" },
{ name = "gleam_community_ansi", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "FE79E08BF97009729259B6357EC058315B6FBB916FAD1C2FF9355115FEB0D3A4" },
Expand All @@ -17,7 +17,7 @@ packages = [
{ name = "gleam_javascript", version = "0.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_javascript", source = "hex", outer_checksum = "483631D3001FCE8EB12ADEAD5E1B808440038E96F93DA7A32D326C82F480C0B2" },
{ name = "gleam_json", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "CB10B0E7BF44282FB25162F1A24C1A025F6B93E777CCF238C4017E4EEF2CDE97" },
{ name = "gleam_otp", version = "0.10.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "0B04FE915ACECE539B317F9652CAADBBC0F000184D586AAAF2D94C100945D72B" },
{ name = "gleam_pgo", version = "0.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "pgo"], otp_app = "gleam_pgo", source = "hex", outer_checksum = "1897C299A05AE3DE6BF6CC92CD1D67FDF8504B15E8826CBEBFD0E4471A698DD3" },
{ name = "gleam_pgo", version = "0.12.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "pgo"], otp_app = "gleam_pgo", source = "hex", outer_checksum = "D66DDF151FF1EBF65F30FB54C8CA938EA52A563811BC67DB53866D1861CE1528" },
{ name = "gleam_stdlib", version = "0.38.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "663CF11861179AF415A625307447775C09404E752FF99A24E2057C835319F1BE" },
{ name = "glint", version = "1.0.0-rc2", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_community_colour", "gleam_stdlib", "snag"], otp_app = "glint", source = "hex", outer_checksum = "FD5C47CE237CA67121F3946ADE7C630750BB67F5E8A4717D2DF5B5EE758CCFDB" },
{ name = "glisten", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "glisten", source = "hex", outer_checksum = "CF3A9383E9BA4A8CBAF2F7B799716290D02F2AC34E7A77556B49376B662B9314" },
Expand Down
45 changes: 30 additions & 15 deletions src/spades/date.gleam
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import decode
import decode.{type Decoder}
import gleam/float
import gleam/int
import gleam/json.{type Json}
import gleam/list.{Continue, Stop}
Expand All @@ -9,22 +10,36 @@ pub type Date {
Date(year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int)
}

pub fn decoder() -> decode.Decoder(Date) {
pub fn decoder() -> Decoder(Date) {
let ymd_decoder =
decode.into({
use year <- decode.parameter
use month <- decode.parameter
use day <- decode.parameter
#(year, month, day)
})
|> decode.field(0, decode.int)
|> decode.field(1, decode.int)
|> decode.field(2, decode.int)

let hms_decoder =
decode.into({
use hour <- decode.parameter
use minute <- decode.parameter
use second <- decode.parameter
#(hour, minute, second)
})
|> decode.field(0, decode.int)
|> decode.field(1, decode.int)
|> decode.field(2, decode.float)

decode.into({
use year <- decode.parameter
use month <- decode.parameter
use day <- decode.parameter
use hour <- decode.parameter
use minute <- decode.parameter
use second <- decode.parameter
Date(year, month, day, hour, minute, second)
use #(year, month, day) <- decode.parameter
use #(hour, minute, second) <- decode.parameter
Date(year, month, day, hour, minute, float.round(second))
})
|> decode.field(0, decode.int)
|> decode.field(1, decode.int)
|> decode.field(2, decode.int)
|> decode.field(3, decode.int)
|> decode.field(4, decode.int)
|> decode.field(5, decode.int)
|> decode.field(0, ymd_decoder)
|> decode.field(1, hms_decoder)
}

pub fn from_string(date_string: String) -> Result(Date, Nil) {
Expand Down
3 changes: 3 additions & 0 deletions src/spades/router.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ pub fn session_middleware(
}
}

import gleam/io

pub fn router(app_req: AppRequest) -> AppResult {
case app_req.req.method, request.path_segments(app_req.req) {
Get, ["assets" as start, ..path] | Get, ["images" as start, ..path] ->
Expand All @@ -113,6 +115,7 @@ pub fn router(app_req: AppRequest) -> AppResult {
json_response(200, session.to_json(value))
|> session.add_cookie_header(value)
})
|> io.debug
|> result.replace_error(empty_response(403))
|> result.unwrap_both
}
Expand Down
53 changes: 18 additions & 35 deletions src/spades/user.gleam
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import decode
import decode.{type Decoder}
import gleam/bit_array
import gleam/crypto.{Sha256}
import gleam/list
Expand All @@ -7,26 +7,34 @@ import gleam/result
import spades/date.{type Date}

pub type User {
User(id: Int, username: String, password_hash: String, inserted_at: Date)
User(id: Int, username: String, inserted_at: Date)
}

pub type PublicUser {
PublicUser(id: Int, username: String, inserted_at: Date)
fn decoder() -> Decoder(User) {
decode.into({
use id <- decode.parameter
use username <- decode.parameter
use inserted_at <- decode.parameter
User(id, username, inserted_at)
})
|> decode.field(0, decode.int)
|> decode.field(1, decode.string)
|> decode.field(2, date.decoder())
}

pub fn create(
db: Connection,
salt: String,
username: String,
password: String,
) -> Result(PublicUser, Nil) {
) -> Result(User, Nil) {
let encoded =
password
|> bit_array.from_string
|> crypto.sign_message(bit_array.from_string(salt), Sha256)

use returned <- result.then(
"insert into users (username, password_hash, created_at) values ($1, $2, now()) returning *"
"insert into users (username, password_hash, created_at) values ($1, $2, now()) returning id, username, created_at"
|> pgo.execute(db, [pgo.text(username), pgo.text(encoded)], decode.from(
decoder(),
_,
Expand All @@ -36,16 +44,13 @@ pub fn create(

let assert [user] = returned.rows

user
|> to_public
|> Ok
Ok(user)
}

pub fn list(db: Connection) -> Result(List(PublicUser), Nil) {
"select id, username, password_hash, created_at from users"
pub fn list(db: Connection) -> Result(List(User), Nil) {
"select id, username, created_at from users"
|> pgo.execute(db, [], decode.from(decoder(), _))
|> result.map(fn(returned) { returned.rows })
|> result.map(fn(rows) { list.map(rows, to_public) })
|> result.replace_error(Nil)
}

Expand All @@ -60,7 +65,7 @@ pub fn login(
|> bit_array.from_string
|> crypto.sign_message(bit_array.from_string(salt), Sha256)

"select id, username, password_hash, created_at from users where username = $1 and password_hash = $2"
"select id, username, created_at from users where username = $1 and password_hash = $2"
|> pgo.execute(db, [pgo.text(username), pgo.text(hashed)], decode.from(
decoder(),
_,
Expand All @@ -69,25 +74,3 @@ pub fn login(
|> result.map(fn(resp) { resp.rows })
|> result.then(list.first(_))
}

pub fn decoder() -> decode.Decoder(User) {
decode.into({
use id <- decode.parameter
use username <- decode.parameter
use password_hash <- decode.parameter
use inserted_at <- decode.parameter
User(id, username, password_hash, inserted_at)
})
|> decode.field(0, decode.int)
|> decode.field(1, decode.string)
|> decode.field(2, decode.string)
|> decode.field(3, date.decoder())
}

fn to_public(user: User) -> PublicUser {
PublicUser(
id: user.id,
username: user.username,
inserted_at: user.inserted_at,
)
}

0 comments on commit 9ea7c18

Please sign in to comment.