-1
gleam.toml
-1
gleam.toml
-2
manifest.toml
-2
manifest.toml
···
11
11
{ name = "eval", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "eval", source = "hex", outer_checksum = "264DAF4B49DF807F303CA4A4E4EBC012070429E40BE384C58FE094C4958F9BDA" },
12
12
{ name = "exception", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "329D269D5C2A314F7364BD2711372B6F2C58FA6F39981572E5CA68624D291F8C" },
13
13
{ name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
14
-
{ name = "formal", version = "3.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "formal", source = "hex", outer_checksum = "686D0C4C9CB36397DBAC2EC8C6ED9BD0F81B2DF2E88F75A7DB75F56768DDD8FC" },
15
14
{ name = "glam", version = "2.0.3", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glam", source = "hex", outer_checksum = "237C2CE218A2A0A5D46D625F8EF5B78F964BC91018B78D692B17E1AB84295229" },
16
15
{ name = "gleam_community_ansi", version = "1.4.3", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_regexp", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "8A62AE9CC6EA65BEA630D95016D6C07E4F9973565FA3D0DE68DC4200D8E0DD27" },
17
16
{ name = "gleam_community_colour", version = "2.0.2", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "E34DD2C896AC3792151EDA939DA435FF3B69922F33415ED3C4406C932FBE9634" },
···
60
59
argv = { version = ">= 1.0.2 and < 2.0.0" }
61
60
cors_builder = { version = ">= 2.0.6 and < 3.0.0" }
62
61
envoy = { version = ">= 1.0.2 and < 2.0.0" }
63
-
formal = { version = ">= 3.0.0 and < 4.0.0" }
64
62
gleam_community_ansi = { version = ">= 1.4.3 and < 2.0.0" }
65
63
gleam_crypto = { version = ">= 1.5.1 and < 2.0.0" }
66
64
gleam_erlang = { version = ">= 1.3.0 and < 2.0.0" }
+22
-48
src/app/domain/user/signup.gleam
+22
-48
src/app/domain/user/signup.gleam
···
12
12
import app/web
13
13
import app/web/context.{type Context}
14
14
import argus
15
-
import formal/form
15
+
import gleam/dynamic/decode
16
16
import gleam/http
17
17
import gleam/json
18
18
import gleam/list
···
32
32
ctx ctx: Context,
33
33
) -> wisp.Response {
34
34
use <- wisp.require_method(req, http.Post)
35
-
use form_data <- wisp.require_form(req)
36
-
let form_result =
37
-
signup_form()
38
-
|> form.add_values(form_data.values)
39
-
|> form.run
35
+
use body <- wisp.require_json(req)
40
36
41
-
case form_result {
42
-
Error(_) -> wisp.unprocessable_content()
37
+
case decode.run(body, sign_up_decoder()) {
38
+
Error(err) -> web.handle_decode_error(err)
43
39
Ok(body) -> handle_body(req, body, ctx)
44
40
}
45
41
}
···
118
114
phone_number: String,
119
115
email: String,
120
116
password: String,
117
+
confirm_password: String,
121
118
user_role: String,
122
119
)
123
120
}
124
121
125
-
/// ๓ฑ A form that decodes the `SignUp` value.
126
-
fn signup_form() -> form.Form(SignUp) {
127
-
form.new({
128
-
use name <- form.field("nome", {
129
-
form.parse_string |> form.check_not_empty()
130
-
})
131
-
132
-
use registration <- form.field("matricula", {
133
-
form.parse_string |> form.check_not_empty()
134
-
})
135
-
136
-
use phone_number <- form.field("telefone", {
137
-
form.parse_phone_number |> form.check_not_empty()
138
-
})
139
-
140
-
use email <- form.field("email", {
141
-
form.parse_email |> form.check_not_empty()
142
-
})
143
-
144
-
use password <- form.field("senha", {
145
-
form.parse_string |> form.check_not_empty()
146
-
})
147
-
148
-
use _ <- form.field("confirma_senha", {
149
-
form.parse_string |> form.check_confirms(password)
150
-
})
151
-
152
-
use user_role <- form.field("cargo", {
153
-
form.parse_string |> form.check_not_empty()
154
-
})
155
-
156
-
form.success(SignUp(
157
-
name:,
158
-
registration:,
159
-
phone_number:,
160
-
email:,
161
-
password:,
162
-
user_role:,
163
-
))
164
-
})
122
+
fn sign_up_decoder() -> decode.Decoder(SignUp) {
123
+
use name <- decode.field("nome", decode.string)
124
+
use registration <- decode.field("matricula", decode.string)
125
+
use phone_number <- decode.field("telefone", decode.string)
126
+
use email <- decode.field("email", decode.string)
127
+
use password <- decode.field("senha", decode.string)
128
+
use confirm_password <- decode.field("confirma_senha", decode.string)
129
+
use user_role <- decode.field("cargo", decode.string)
130
+
decode.success(SignUp(
131
+
name:,
132
+
registration:,
133
+
phone_number:,
134
+
email:,
135
+
password:,
136
+
confirm_password:,
137
+
user_role:,
138
+
))
165
139
}
166
140
167
141
fn handle_database_error(err: pog.QueryError) -> wisp.Response {
+23
-44
src/app/domain/user/update_user_password.gleam
+23
-44
src/app/domain/user/update_user_password.gleam
···
3
3
import app/web
4
4
import app/web/context.{type Context}
5
5
import argus
6
-
import formal/form
7
6
import gleam/bool
7
+
import gleam/dynamic/decode
8
8
import gleam/http
9
9
import gleam/list
10
10
import gleam/result
···
23
23
ctx ctx: Context,
24
24
) -> wisp.Response {
25
25
use <- wisp.require_method(req, http.Put)
26
-
use form_data <- wisp.require_form(req)
27
-
let form_result =
28
-
update_password_form()
29
-
|> form.add_values(form_data.values)
30
-
|> form.run()
26
+
use body <- wisp.require_json(req)
31
27
32
-
case form_result {
28
+
case decode.run(body, request_body_decoder()) {
33
29
Ok(form_data) -> handle_form_data(request: req, ctx:, form_data:)
34
-
Error(_) -> {
35
-
let resp = wisp.unprocessable_content()
36
-
37
-
"Formulรกrio invรกlido"
38
-
|> wisp.Text
39
-
|> wisp.set_body(resp, _)
40
-
}
30
+
Error(err) -> web.handle_decode_error(err)
41
31
}
42
32
}
43
33
44
34
fn handle_form_data(
45
-
request request: wisp.Request,
35
+
request req: wisp.Request,
46
36
ctx ctx: Context,
47
37
form_data form_data: RequestBody,
48
38
) -> wisp.Response {
49
-
case update_user_password(request:, ctx:, form_data:) {
39
+
case update_user_password(request: req, ctx:, form_data:) {
50
40
Error(err) -> handle_error(err)
51
41
Ok(_) -> {
52
42
let resp = wisp.ok()
···
85
75
}
86
76
87
77
fn update_user_password(
88
-
request request: wisp.Request,
78
+
request req: wisp.Request,
89
79
ctx ctx: Context,
90
80
form_data form_data: RequestBody,
91
81
) -> Result(pog.Returned(Nil), UpdatePasswordError) {
92
82
use user_uuid <- result.try(
93
-
user.extract_uuid(request:, cookie_name: user.uuid_cookie_name)
83
+
user.extract_uuid(request: req, cookie_name: user.uuid_cookie_name)
94
84
|> result.map_error(AccessControl),
95
85
)
96
86
···
149
139
row.password_hash
150
140
}
151
141
152
-
fn update_password_form() -> form.Form(RequestBody) {
153
-
form.new({
154
-
use current_password <- form.field("senhaAtual", {
155
-
form.parse_string |> form.check_not_empty()
156
-
})
157
-
use new_password <- form.field("novaSenha", {
158
-
form.parse_string
159
-
|> form.check_not_empty()
160
-
|> form.check(fn(value) {
161
-
case value == current_password {
162
-
False -> Ok(value)
163
-
True -> Error("Nova senha deve ser diferente da atual")
164
-
}
165
-
})
166
-
})
167
-
168
-
use _ <- form.field("confirmarSenha", {
169
-
form.parse_string |> form.check_confirms(new_password)
170
-
})
171
-
172
-
// Success!
173
-
RequestBody(current_password:, new_password:)
174
-
|> form.success()
175
-
})
142
+
type RequestBody {
143
+
RequestBody(
144
+
current_password: String,
145
+
new_password: String,
146
+
confirm_password: String,
147
+
)
176
148
}
177
149
178
-
type RequestBody {
179
-
RequestBody(current_password: String, new_password: String)
150
+
fn request_body_decoder() -> decode.Decoder(RequestBody) {
151
+
use current_password <- decode.field("senhaAtual", decode.string)
152
+
use new_password <- decode.field("novaSenha", decode.string)
153
+
use confirm_password <- decode.field("confirmarSenha", decode.string)
154
+
decode.success(RequestBody(
155
+
current_password:,
156
+
new_password:,
157
+
confirm_password:,
158
+
))
180
159
}
181
160
182
161
/// ๎ Updating an user's password can fail
+55
-45
test/user_test.gleam
+55
-45
test/user_test.gleam
···
60
60
let dummy_password = wisp.random_string(10)
61
61
let req =
62
62
simulate.browser_request(http.Post, "/admin/signup")
63
-
|> simulate.form_body([
64
-
#("nome", wisp.random_string(10)),
65
-
#("matricula", int.random(111) |> int.to_string),
66
-
#("telefone", int.random(9_999_999_999) |> int.to_string),
67
-
#("email", wisp.random_string(12) <> "@email.com"),
68
-
#("senha", dummy_password),
69
-
#("confirma_senha", dummy_password),
70
-
#("cargo", role.to_string_pt_br(dummy.random_role())),
71
-
])
63
+
|> simulate.json_body(
64
+
json.object([
65
+
#("nome", wisp.random_string(10) |> json.string),
66
+
#("matricula", int.random(111) |> int.to_string |> json.string),
67
+
#("telefone", int.random(9_999_999_999) |> int.to_string |> json.string),
68
+
#("email", { wisp.random_string(12) <> "@email.com" } |> json.string),
69
+
#("senha", dummy_password |> json.string),
70
+
#("confirma_senha", dummy_password |> json.string),
71
+
#("cargo", dummy.random_role() |> role.to_string_pt_br() |> json.string),
72
+
]),
73
+
)
72
74
73
75
let resp = http_router.handle_request(req, ctx)
74
76
assert resp.status == 401 as "Endpoint access should be restricted"
···
102
104
103
105
let req =
104
106
simulate.browser_request(http.Post, "/admin/signup")
105
-
|> simulate.form_body([
106
-
#("nome", wisp.random_string(10)),
107
-
#("matricula", taken_registration),
108
-
#("telefone", int.random(9_999_999_999) |> int.to_string),
109
-
#("email", wisp.random_string(5) <> "@email.com"),
110
-
#("senha", dummy_pswd),
111
-
#("confirma_senha", dummy_pswd),
112
-
#("cargo", role.to_string_pt_br(dummy.random_role())),
113
-
])
107
+
|> simulate.json_body(
108
+
json.object([
109
+
#("nome", wisp.random_string(10) |> json.string),
110
+
#("matricula", taken_registration |> json.string),
111
+
#("telefone", int.random(9_999_999_999) |> int.to_string |> json.string),
112
+
#("email", { wisp.random_string(12) <> "@email.com" } |> json.string),
113
+
#("senha", dummy_pswd |> json.string),
114
+
#("confirma_senha", dummy_pswd |> json.string),
115
+
#("cargo", dummy.random_role() |> role.to_string_pt_br() |> json.string),
116
+
]),
117
+
)
114
118
115
119
let with_auth = app_test.with_authorization(next: req)
116
120
let resp = http_router.handle_request(with_auth, ctx)
···
126
130
127
131
let req =
128
132
simulate.browser_request(http.Post, "/admin/signup")
129
-
|> simulate.form_body([
130
-
#("nome", wisp.random_string(10)),
131
-
#("matricula", int.random(111) |> int.to_string),
132
-
#("telefone", int.random(9_999_999_999) |> int.to_string),
133
-
#("email", taken_email),
134
-
#("senha", dummy_pswd),
135
-
#("confirma_senha", dummy_pswd),
136
-
#("cargo", role.to_string_pt_br(dummy.random_role())),
137
-
])
133
+
|> simulate.json_body(
134
+
json.object([
135
+
#("nome", wisp.random_string(10) |> json.string),
136
+
#("matricula", int.random(111) |> int.to_string |> json.string),
137
+
#("telefone", int.random(9_999_999_999) |> int.to_string |> json.string),
138
+
#("email", taken_email |> json.string),
139
+
#("senha", dummy_pswd |> json.string),
140
+
#("confirma_senha", dummy_pswd |> json.string),
141
+
#("cargo", dummy.random_role() |> role.to_string_pt_br() |> json.string),
142
+
]),
143
+
)
138
144
139
145
let with_auth = app_test.with_authorization(next: req)
140
146
let resp = http_router.handle_request(with_auth, ctx)
···
149
155
150
156
let req =
151
157
simulate.browser_request(http.Post, "/admin/signup")
152
-
|> simulate.form_body([
153
-
#("nome", wisp.random_string(10)),
154
-
#("matricula", int.random(111) |> int.to_string),
155
-
#("telefone", taken_phone),
156
-
#("email", wisp.random_string(5) <> "@email.com"),
157
-
#("senha", dummy_pswd),
158
-
#("confirma_senha", dummy_pswd),
159
-
#("cargo", role.to_string_pt_br(dummy.random_role())),
160
-
])
158
+
|> simulate.json_body(
159
+
json.object([
160
+
#("nome", wisp.random_string(10) |> json.string),
161
+
#("matricula", int.random(111) |> int.to_string |> json.string),
162
+
#("telefone", taken_phone |> json.string),
163
+
#("email", { wisp.random_string(12) <> "@email.com" } |> json.string),
164
+
#("senha", dummy_pswd |> json.string),
165
+
#("confirma_senha", dummy_pswd |> json.string),
166
+
#("cargo", dummy.random_role() |> role.to_string_pt_br() |> json.string),
167
+
]),
168
+
)
161
169
162
170
let with_auth = app_test.with_authorization(next: req)
163
171
let resp = http_router.handle_request(with_auth, ctx)
···
209
217
210
218
let new_user_req =
211
219
simulate.browser_request(http.Post, signup_path)
212
-
|> simulate.form_body([
213
-
#("nome", wisp.random_string(10)),
214
-
#("matricula", dummy_registration),
215
-
#("telefone", dummy_phone),
216
-
#("email", dummy_email),
217
-
#("senha", dummy_password),
218
-
#("confirma_senha", dummy_password),
219
-
#("cargo", role.to_string_pt_br(role.Firefighter)),
220
-
])
220
+
|> simulate.json_body(
221
+
json.object([
222
+
#("nome", wisp.random_string(10) |> json.string),
223
+
#("matricula", dummy_registration |> json.string),
224
+
#("telefone", dummy_phone |> json.string),
225
+
#("email", dummy_email |> json.string),
226
+
#("senha", dummy_password |> json.string),
227
+
#("confirma_senha", dummy_password |> json.string),
228
+
#("cargo", role.to_string_pt_br(role.Firefighter) |> json.string),
229
+
]),
230
+
)
221
231
222
232
let with_auth = app_test.with_authorization(new_user_req)
223
233
let new_user_resp = http_router.handle_request(with_auth, ctx)