Forget-Me-Not/post_handlers/login_post_handler.nim

94 lines
4.7 KiB
Nim

#[Copyright 2025 ITwrx.
This file is part of Forget-Me-Not.
Forget-Me-Not is released under the GNU Affero General Public License 3.0.
See COPYING or <https://www.gnu.org/licenses/> for details.]#
import guildenstern/httpserver
import nimword, jsony
import std/[base64, sysrand]
import "../helpers/form", "../helpers/validation", "../helpers/auth", "../helpers/global", "../models/user", "../models/session"
proc loginPostHandler*() =
try:
var cookieHeader1, cookieHeader2: string
let email = formInput("email")
let password = formInput("password")
#validate form inputs
vInput("email", @["required", "string", "email", "max:75"])
vInput("password", @["required", "string", "min_complexity", "max:100"])
var csrfTokenInput = formInput("csrf_token")
#create formResult and redirect on validation errors.
if formErrors.len > 0:
addFormOldInput("email", formInput("email"))
#discard assignErrorFR(formErrors, formOldInputs, csrfTokenInput)
discard assignErrorFR(formErrors, formOldInputs)
let frJson = formResult.toJson()
if APP_MODE == "dev":
cookieHeader1 = "Set-Cookie: form_result=" & frJson & ";" & "HttpOnly;" & "path=/;" & "SameSite=Lax;"
else:
cookieHeader1 = "Set-Cookie: form_result=" & frJson & ";" & "HttpOnly;" & "Secure=true;" & "path=/;" & "SameSite=Lax;"
reply(Http303, [locationBack(), cookieHeader1])
else:
#inputs pass validation rules. let's see if the creds supplied are valid.
let registeredUser = getUserByEmail(email)
if registeredUser.email.len > 0:
if password.isValidPassword(registeredUser.password):
#create sessionId
var sessionId = $urandom(32)
sessionId = base64.encode(sessionId)
#create session
var userSession: Session
userSession.sessionId = sessionId
userSession.userId = registeredUser.id
userSession.csrfToken = newCsrfToken()
createUserSession(userSession)
discard assignLoginSuccessFR()
let frJson = formResult.toJson()
#redirect, and set session cookie.
if APP_MODE == "dev":
cookieHeader1 = "Set-Cookie: " & APP_NAME & "_session=" & sessionId & ";" & "HttpOnly;" & "SameSite=Lax;"
cookieHeader2 = "Set-Cookie: form_result=" & frJson & ";" & "HttpOnly;" & "path=/;" & "SameSite=Lax;"
else:
cookieHeader1 = "Set-Cookie: " & APP_NAME & "_session=" & sessionId & ";" & "HttpOnly;" & "Secure=true;" & "SameSite=Lax;"
cookieHeader2 = "Set-Cookie: form_result=" & frJson & ";" & "HttpOnly;" & "Secure=true;" & "path=/;" & "SameSite=Lax;"
#headers are just an openarray of strings.
reply(Http303, [location("/"), cookieHeader1, cookieHeader2])
else:
#password supplied did not match password in DB for supplied email address. redirect back to login with creds error.
#create a formError.
formError.fieldName = "password"
formError.fieldMessage = "Entered password is not valid."
#add it to formErrors seq.
formErrors.add(formError)
formResult.message = "Authentication error."
formResult.messageClass = "text-red-500"
formResult.errors = toJson(formErrors)
formResult.oldInputs = getOldInputJson()
let frJson = formResult.toJson()
if APP_MODE == "dev":
cookieHeader1 = "Set-Cookie: form_result=" & frJson & ";" & "HttpOnly;" & "path=/;" & "SameSite=Lax;"
else:
cookieHeader1 = "Set-Cookie: form_result=" & frJson & ";" & "HttpOnly;" & "Secure=true;" & "path=/;" & "SameSite=Lax;"
reply(Http303, [locationBack(), cookieHeader1])
else:
formError.fieldName = "email"
formError.fieldMessage = "No user found with supplied email address."
#add it to formErrors seq.
formErrors.add(formError)
formResult.message = "Authentication error."
formResult.messageClass = "text-red-500"
formResult.errors = toJson(formErrors)
formResult.oldInputs = getOldInputJson()
let frJson = formResult.toJson()
if APP_MODE == "dev":
cookieHeader1 = "Set-Cookie: form_result=" & frJson & ";" & "HttpOnly;" & "path=/;" & "SameSite=Lax;"
else:
cookieHeader1 = "Set-Cookie: form_result=" & frJson & ";" & "HttpOnly;" & "Secure=true;" & "path=/;" & "SameSite=Lax;"
reply(Http303, [locationBack(), cookieHeader1])
except Exception as e:
echo e.msg
discard assignGeneralErrorFR(e.msg)
setFR()
reply(Http303, [location("/500")])