KUMOS/Server/Includes/Auth.pbi
2026-05-02 15:49:06 +02:00

121 lines
3.9 KiB
Plaintext

Module Auth
EnableExplicit
;- Private helpers
Procedure.s GetFormField(PostData.s, Field.s)
; Parse a single field from application/x-www-form-urlencoded body
Protected Count = CountString(PostData, "&") + 1, i
Protected Pair.s, Key.s
For i = 1 To Count
Pair = StringField(PostData, i, "&")
Key = StringField(Pair, 1, "=")
If Key = Field
ProcedureReturn URLDecoder(StringField(Pair, 2, "="))
EndIf
Next
ProcedureReturn ""
EndProcedure
Procedure SetSessionCookie(*Request, Token.s)
FastCGI::WriteResponseHeader(*Request, "Set-Cookie",
#SESSION_COOKIE + "=" + Token +
"; Path=/; HttpOnly; SameSite=Strict; Max-Age=" + #SESSION_MAX_AGE)
EndProcedure
Procedure ClearSessionCookie(*Request)
FastCGI::WriteResponseHeader(*Request, "Set-Cookie",
#SESSION_COOKIE + "=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0")
EndProcedure
;- Public handlers
Procedure HandleLogin(*Request)
Protected PostData.s = FastCGI::GetPostData(*Request)
Protected Username.s = GetFormField(PostData, "username")
Protected Password.s = GetFormField(PostData, "password")
If Username = "" Or Password = ""
General::RespondJSON(*Request, ~"{\"success\":false,\"error\":\"Missing credentials\"}")
ProcedureReturn
EndIf
Protected ValidUser.s = Database::ValidateCredentials(Username, Password)
If ValidUser <> ""
Protected UserID.i = Database::FindUser(ValidUser)
Protected Token.s = Database::CreateSession(UserID, ValidUser)
SetSessionCookie(*Request, Token)
FastCGI::WriteResponseHeader(*Request, "Content-Type", "application/json; charset=utf-8")
FastCGI::WriteResponseHeader(*Request, "Cache-Control", "no-cache, no-store")
FastCGI::WriteResponseString(*Request, ~"{\"success\":true,\"username\":\"" + ValidUser + ~"\"}")
FastCGI::FinishResponse(*Request)
Else
; Uniform error - don't reveal which field was wrong
General::RespondJSON(*Request, ~"{\"success\":false,\"error\":\"Invalid username or password\"}")
EndIf
EndProcedure
Procedure HandleLogout(*Request)
Protected Token.s = FastCGI::GetCookie(*Request, #SESSION_COOKIE)
If Token <> ""
Database::DeleteSession(Token)
EndIf
ClearSessionCookie(*Request)
General::RespondJSON(*Request, ~"{\"success\":true}")
EndProcedure
Procedure HandleCheck(*Request)
Protected Token.s = FastCGI::GetCookie(*Request, #SESSION_COOKIE)
Protected Username.s = ""
If Token <> ""
Username = Database::ValidateSession(Token)
EndIf
If Username <> ""
General::RespondJSON(*Request, ~"{\"authenticated\":true,\"username\":\"" + Username + ~"\"}")
Else
General::RespondJSON(*Request, ~"{\"authenticated\":false}")
EndIf
EndProcedure
Procedure.s GetSessionUser(*Request)
Protected Token.s = FastCGI::GetCookie(*Request, #SESSION_COOKIE)
If Token <> ""
ProcedureReturn Database::ValidateSession(Token)
EndIf
ProcedureReturn ""
EndProcedure
Procedure HandleChangePassword(*Request)
Protected Username.s = GetSessionUser(*Request)
If Username = ""
General::RespondJSON(*Request, ~"{\"error\":\"Unauthorized\"}", "401 Unauthorized")
ProcedureReturn
EndIf
Protected CurrentPwd.s = General::GetPostField(*Request, "current_password")
Protected NewPwd.s = General::GetPostField(*Request, "new_password")
If CurrentPwd = "" Or NewPwd = ""
General::RespondJSON(*Request, ~"{\"error\":\"Missing fields\"}")
ProcedureReturn
EndIf
If Database::ValidateCredentials(Username, CurrentPwd) = ""
General::RespondJSON(*Request, ~"{\"error\":\"Current password is incorrect\"}")
ProcedureReturn
EndIf
Protected UserID.i = Database::FindUser(Username)
Database::ChangePassword(UserID, NewPwd)
General::RespondJSON(*Request, ~"{\"success\":true}")
EndProcedure
EndModule
; IDE Options = PureBasic 6.30 (Windows - x64)
; CursorPosition = 29
; Folding = B5
; EnableXP
; DPIAware