aqhome-cgi: more work

This commit is contained in:
Martin Preuss
2025-06-16 23:31:53 +02:00
parent b498a445b2
commit 06886e0094
8 changed files with 244 additions and 41 deletions

View File

@@ -16,6 +16,7 @@
#include "aqhome-cgi/service/module.h"
#include <gwenhywfar/debug.h>
#include <gwenhywfar/timestamp.h>
@@ -37,6 +38,8 @@
static AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sModuleName);
static int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem);
static int _handleRqLogin(AQH_MODULE *m, AQCGI_REQUEST *rq);
static int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq);
static AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq);
/* ------------------------------------------------------------------------------------------------
@@ -69,8 +72,16 @@ int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem)
if (strcasecmp(sLastPathElem, "login")==0)
return _handleRqLogin(m, rq);
else if (strcasecmp(sLastPathElem, "signup")==0) {
AQCGI_SendResponseWithStatus(rq, 501, "Not Implemented");
return GWEN_ERROR_NOT_IMPLEMENTED;
}
else if (strcasecmp(sLastPathElem, "confirm")==0) {
AQCGI_SendResponseWithStatus(rq, 501, "Not Implemented");
return GWEN_ERROR_NOT_IMPLEMENTED;
}
else {
AQCGI_SendResponseWithStatus(rq, 404, "Not Found");
return GWEN_ERROR_NOT_IMPLEMENTED;
}
}
@@ -78,25 +89,152 @@ int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *sLastPathElem)
int _handleRqLogin(AQH_MODULE *m, AQCGI_REQUEST *rq)
{
if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_GET) {
int rv;
int rv;
rv=AQH_ModService_RespondWithFile(m, rq, "login.html");
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
return 0;
if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_GET)
rv=AQH_ModService_RespondWithFile(m, rq, "en", "login.html");
else if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_POST)
rv=_handleRqLoginPost(m, rq);
else {
DBG_ERROR(NULL, "Invalid request method %d", AQCGI_Request_GetRequestMethod(rq));
AQCGI_SendResponseWithStatus(rq, 405, "Method No Allowed");
return GWEN_ERROR_INVALID;
}
else if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_POST) {
GWEN_DB_NODE *dbPost;
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
return 0;
}
dbPost=AQCGI_Request_GetDbPostBody(rq);
if (dbPost) {
int _handleRqLoginPost(AQH_MODULE *m, AQCGI_REQUEST *rq)
{
AQH_SERVICE *sv;
AQH_USER *user;
AQH_SESSION *session;
GWEN_BUFFER *dbuf;
GWEN_TIMESTAMP *ts;
int rv;
DBG_ERROR(NULL, "Handling request");
sv=AQH_ModService_GetService(m);
user=_getAndCheckUser(m, rq);
if (user==NULL) {
DBG_INFO(NULL, "here");
return GWEN_ERROR_GENERIC;
}
ts=GWEN_Timestamp_NowInLocalTime();
AQH_User_SetTimestampLastLogin(user, ts);
DBG_ERROR(NULL, "Saving user");
rv=AQH_Service_SaveUser(sv, user);
if (rv<0) {
DBG_ERROR(NULL, "Error saving user \"%s\"", AQH_User_GetAlias(user));
AQCGI_SendResponseWithStatus(rq, 500, "Internal Error");
AQH_User_free(user);
return rv;
}
/* generate session */
DBG_ERROR(NULL, "Generating session");
dbuf=GWEN_Buffer_new(0, 64, 0, 1);
AQCGI_GenerateSessionId(dbuf);
session=AQH_Session_new();
AQH_Session_SetTimestampCreation(session, ts);
AQH_Session_SetTimestampLastAccess(session, ts);
AQH_Session_SetUid(session, GWEN_Buffer_GetStart(dbuf));
GWEN_Buffer_free(dbuf);
AQH_Session_SetUserAlias(session, AQH_User_GetAlias(user));
rv=AQH_Service_AddSession(sv, session);
if (rv<0) {
DBG_ERROR(NULL, "Error adding session for user \"%s\"", AQH_User_GetAlias(user));
AQCGI_SendResponseWithStatus(rq, 500, "Internal Error");
AQH_Session_free(session);
AQH_User_free(user);
return GWEN_ERROR_INTERNAL;
}
/* add Set-Cookie header */
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
GWEN_Buffer_AppendArgs(dbuf, "Set-Cookie: session=%s; max-age=3600", AQH_Session_GetUid(session));
AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(dbuf));
/* finish */
AQCGI_SendResponseWithStatus(rq, 200, "Ok");
AQH_Session_free(session);
AQH_User_free(user);
return 0;
}
AQH_USER *_getAndCheckUser(AQH_MODULE *m, AQCGI_REQUEST *rq)
{
GWEN_DB_NODE *dbPost;
dbPost=AQCGI_Request_GetDbPostBody(rq);
if (dbPost) {
AQH_SERVICE *sv;
const char *sUserName;
const char *sPasswd;
AQH_USER *user;
const char *hashedPaswd;
GWEN_BUFFER *buf;
sv=AQH_ModService_GetService(m);
sUserName=GWEN_DB_GetCharValue(dbPost, "userid", 0, NULL);
sPasswd=GWEN_DB_GetCharValue(dbPost, "password", 0, NULL);
if (!(sUserName && *sUserName && sPasswd && *sPasswd)) {
DBG_ERROR(NULL, "Either user name or password missing");
AQCGI_SendResponseWithStatus(rq, 400, "Bad Request");
return NULL;
}
DBG_ERROR(NULL, "Loading user \"%s\" (%p)", sUserName, sv);
user=AQH_Service_LoadUser(sv, sUserName);
if (user==NULL) {
DBG_ERROR(NULL, "User \"%s\" not found", sUserName);
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
return NULL;
}
DBG_ERROR(NULL, "Loaded user \"%s\"", sUserName);
if (AQH_User_GetState(user)!=AQH_UserState_Active) {
DBG_ERROR(NULL, "User \"%s\" not active", sUserName);
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
AQH_User_free(user);
return NULL;
}
hashedPaswd=AQH_User_GetHashedPassword(user);
if (!(hashedPaswd && *hashedPaswd)) {
DBG_ERROR(NULL, "User \"%s\" has no hashed password", sUserName);
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
AQH_User_free(user);
return NULL;
}
buf=GWEN_Buffer_new(0, 256, 0, 1);
AQCGI_HashMd256ToBuffer(sPasswd, buf);
DBG_ERROR(NULL, "Hashed password: [%s]", GWEN_Buffer_GetStart(buf));
if (strcasecmp(GWEN_Buffer_GetStart(buf), hashedPaswd)!=0) {
DBG_ERROR(NULL, "Bad password for user \"%s\"", sUserName);
AQCGI_SendResponseWithStatus(rq, 403, "Forbidden");
GWEN_Buffer_free(buf);
AQH_User_free(user);
return NULL;
}
GWEN_Buffer_free(buf);
DBG_ERROR(NULL, "User \"%s\" accepted", sUserName);
return user;
}
else {
DBG_ERROR(NULL, "No POST data");
AQCGI_SendResponseWithStatus(rq, 400, "Bad Request");
return NULL;
}
}
@@ -106,4 +244,3 @@ int _handleRqLogin(AQH_MODULE *m, AQCGI_REQUEST *rq)