aqhome: more work on http service.
This commit is contained in:
982
aqhome/http/httpservice_conf.c
Normal file
982
aqhome/http/httpservice_conf.c
Normal file
@@ -0,0 +1,982 @@
|
||||
/****************************************************************************
|
||||
* This file is part of the project AqHome.
|
||||
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
||||
*
|
||||
* The license for this file can be found in the file COPYING which you
|
||||
* should have received along with this file.
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "aqhome/http/httpservice_conf.h"
|
||||
#include "aqhome/http/httpservice_p.h"
|
||||
|
||||
#include <gwenhywfar/db.h>
|
||||
#include <gwenhywfar/buffer.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
|
||||
#define AQH_HTTP_SERVICE_FILE_CONFIG "service.conf"
|
||||
#define AQH_HTTP_SERVICE_DIR_MODS "modules"
|
||||
#define AQH_HTTP_SERVICE_DIR_USERS "users"
|
||||
#define AQH_HTTP_SERVICE_DIR_SESSIONS "sessions"
|
||||
|
||||
|
||||
#ifdef GWEN_INHERIT_REF
|
||||
GWEN_INHERIT_REF(AQH_SERVICE, AQH_HTTP_SERVICE)
|
||||
#else
|
||||
extern uint32_t AQH_HTTP_SERVICE_ID;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* forward declarations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void _calculateUserPerms(AQH_SERVICE *sv, AQH_USER *user);
|
||||
static void _calculateModuleUserPerms(AQH_SERVICE *sv, AQH_MODULE_PERMS *p);
|
||||
static AQH_MODULE *_ensureModule(AQH_SERVICE *sv, const char *modName);
|
||||
static AQH_USER *_ensureUser(AQH_SERVICE *sv, const char *alias);
|
||||
static AQH_SESSION *_ensureSession(AQH_SERVICE *sv, const char *sessionUid);
|
||||
static GWEN_BUFFER *_getConfigFilePath(const AQH_SERVICE *sv, const char *fileName);
|
||||
static GWEN_BUFFER *_getModuleFilePath(const AQH_SERVICE *sv, const char *modName);
|
||||
static GWEN_BUFFER *_getUserFilePath(const AQH_SERVICE *sv, const char *userAlias);
|
||||
static GWEN_BUFFER *_getSessionFilePath(const AQH_SERVICE *sv, const char *sessionUid);
|
||||
static int _checkUser(const AQH_USER *user, int ignoreMissingId);
|
||||
static int _checkSession(const AQH_SESSION *session);
|
||||
static int _checkModule(const AQH_MODULE *m, int ignoreMissingId);
|
||||
static int _checkRoleList(const AQH_ROLE_LIST *roleList, int ignoreMissingId);
|
||||
static int _writeDbFile(const char *fname, GWEN_DB_NODE *db);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* implementations
|
||||
* ------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int AQH_HttpService_LoadConfig(AQH_SERVICE *sv)
|
||||
{
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
GWEN_BUFFER *nameBuf;
|
||||
int rv;
|
||||
GWEN_DB_NODE *db;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object");
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
db=GWEN_DB_Group_new("service");
|
||||
|
||||
nameBuf=_getConfigFilePath(sv, AQH_HTTP_SERVICE_FILE_CONFIG);
|
||||
rv=GWEN_DB_ReadFile(db, GWEN_Buffer_GetStart(nameBuf), GWEN_DB_FLAGS_DEFAULT | GWEN_DB_FLAGS_LOCKFILE);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
|
||||
xsv->lastModuleId=GWEN_DB_GetIntValue(db, "lastModuleId", 0, 0);
|
||||
xsv->lastUserId=GWEN_DB_GetIntValue(db, "lastUserId", 0, 0);
|
||||
xsv->maxSessionAgeInSecs=GWEN_DB_GetIntValue(db, "maxSessionAgeInSecs", 0, AQH_HTTP_SERVICE_DEFAULT_MAXSESSIONAGE);
|
||||
|
||||
GWEN_DB_Group_free(db);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_HttpService_SaveConfig(const AQH_SERVICE *sv)
|
||||
{
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
int rv;
|
||||
GWEN_BUFFER *nameBuf;
|
||||
GWEN_DB_NODE *db;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object");
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
db=GWEN_DB_Group_new("service");
|
||||
GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "lastModuleId", xsv->lastModuleId);
|
||||
GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "lastUserId", xsv->lastUserId);
|
||||
GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "maxSessionAgeInSecs", xsv->maxSessionAgeInSecs);
|
||||
|
||||
nameBuf=_getConfigFilePath(sv, AQH_HTTP_SERVICE_FILE_CONFIG);
|
||||
rv=_writeDbFile(GWEN_Buffer_GetStart(nameBuf), db);
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
GWEN_DB_Group_free(db);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *AQH_HttpService_GetModule(AQH_SERVICE *sv, const char *modName)
|
||||
{
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
AQH_MODULE *m;
|
||||
int rv;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rv=GWEN_Mutex_Lock(xsv->moduleMutex);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error obtaining lock on module mutex");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m=_ensureModule(sv, modName);
|
||||
|
||||
rv=GWEN_Mutex_Unlock(xsv->moduleMutex);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error releasing lock on module mutex");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (m==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_USER *AQH_HttpService_GetUser(AQH_SERVICE *sv, const char *alias)
|
||||
{
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
AQH_USER *user;
|
||||
int rv;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rv=GWEN_Mutex_Lock(xsv->userMutex);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error obtaining lock on user mutex");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
user=_ensureUser(sv, alias);
|
||||
|
||||
rv=GWEN_Mutex_Unlock(xsv->userMutex);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error releasing lock on user mutex");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (user==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_SESSION *AQH_HttpService_GetSession(AQH_SERVICE *sv, const char *sessionUid)
|
||||
{
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
AQH_SESSION *session;
|
||||
int rv;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rv=GWEN_Mutex_Lock(xsv->sessionMutex);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error obtaining lock on session mutex");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
session=_ensureSession(sv, sessionUid);
|
||||
|
||||
rv=GWEN_Mutex_Unlock(xsv->sessionMutex);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error releasing lock on session mutex");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (session==NULL) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *AQH_HttpService_LoadModule(const AQH_SERVICE *sv, const char *modName)
|
||||
{
|
||||
GWEN_BUFFER *nameBuf;
|
||||
int rv;
|
||||
GWEN_DB_NODE *db;
|
||||
AQH_MODULE *m;
|
||||
|
||||
db=GWEN_DB_Group_new("user");
|
||||
|
||||
nameBuf=_getModuleFilePath(sv, modName);
|
||||
rv=GWEN_DB_ReadFile(db, GWEN_Buffer_GetStart(nameBuf), GWEN_DB_FLAGS_DEFAULT | GWEN_DB_FLAGS_LOCKFILE);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
GWEN_DB_Group_free(db);
|
||||
return NULL;
|
||||
}
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
|
||||
m=AQH_Module_fromDb(db);
|
||||
if (m==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error loading module \"%s\" from config group", modName);
|
||||
GWEN_DB_Group_free(db);
|
||||
return NULL;
|
||||
}
|
||||
GWEN_DB_Group_free(db);
|
||||
|
||||
rv=_checkModule(m, 0);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Invalid data for module \"%s\"", modName);
|
||||
AQH_Module_free(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_HttpService_SaveModule(const AQH_SERVICE *sv, const AQH_MODULE *m)
|
||||
{
|
||||
int rv;
|
||||
const char *modName;
|
||||
GWEN_BUFFER *nameBuf;
|
||||
GWEN_DB_NODE *db;
|
||||
|
||||
rv=_checkModule(m, 0);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
db=GWEN_DB_Group_new("module");
|
||||
rv=AQH_Module_toDb(m, db);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
modName=AQH_Module_GetName(m);
|
||||
nameBuf=_getModuleFilePath(sv, modName);
|
||||
rv=_writeDbFile(GWEN_Buffer_GetStart(nameBuf), db);
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
GWEN_DB_Group_free(db);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_HttpService_AddModule(AQH_SERVICE *sv, AQH_MODULE *m)
|
||||
{
|
||||
int rv;
|
||||
uint32_t id;
|
||||
AQH_ROLE_LIST *roleList;
|
||||
AQH_ROLE *r;
|
||||
|
||||
rv=_checkModule(m, 1);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Not adding invalid module (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* assign module id */
|
||||
id=AQH_HttpService_GetNextModuleId(sv);
|
||||
AQH_Module_SetId(m, id);
|
||||
|
||||
/* assign role ids */
|
||||
roleList=AQH_Module_GetRoleList(m);
|
||||
id=1;
|
||||
r=AQH_Role_List_First(roleList);
|
||||
while(r) {
|
||||
AQH_Role_SetId(r, id++);
|
||||
r=AQH_Role_List_Next(r);
|
||||
}
|
||||
|
||||
rv=AQH_HttpService_SaveModule(sv, m);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error saving module module \"%s\" (%d)", AQH_Module_GetName(m), rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
AQH_Service_AddModule(sv, m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_USER *AQH_HttpService_LoadUser(const AQH_SERVICE *sv, const char *userAlias)
|
||||
{
|
||||
GWEN_BUFFER *nameBuf;
|
||||
int rv;
|
||||
GWEN_DB_NODE *db;
|
||||
AQH_USER *user;
|
||||
|
||||
db=GWEN_DB_Group_new("user");
|
||||
|
||||
nameBuf=_getUserFilePath(sv, userAlias);
|
||||
rv=GWEN_DB_ReadFile(db, GWEN_Buffer_GetStart(nameBuf), GWEN_DB_FLAGS_DEFAULT | GWEN_DB_FLAGS_LOCKFILE);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
GWEN_DB_Group_free(db);
|
||||
return NULL;
|
||||
}
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
|
||||
user=AQH_User_fromDb(db);
|
||||
if (user==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error loading user \"%s\" from config group", userAlias);
|
||||
GWEN_DB_Group_free(db);
|
||||
return NULL;
|
||||
}
|
||||
GWEN_DB_Group_free(db);
|
||||
|
||||
rv=_checkUser(user, 0);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Invalid data for user \"%s\"", userAlias);
|
||||
AQH_User_free(user);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_HttpService_SaveUser(const AQH_SERVICE *sv, const AQH_USER *user)
|
||||
{
|
||||
int rv;
|
||||
const char *sAlias;
|
||||
GWEN_BUFFER *nameBuf;
|
||||
GWEN_DB_NODE *db;
|
||||
|
||||
rv=_checkUser(user, 0);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
db=GWEN_DB_Group_new("user");
|
||||
rv=AQH_User_toDb(user, db);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
sAlias=AQH_User_GetAlias(user);
|
||||
nameBuf=_getUserFilePath(sv, sAlias);
|
||||
rv=_writeDbFile(GWEN_Buffer_GetStart(nameBuf), db);
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
GWEN_DB_Group_free(db);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_HttpService_AddUser(AQH_SERVICE *sv, AQH_USER *user)
|
||||
{
|
||||
int rv;
|
||||
uint32_t id;
|
||||
|
||||
rv=_checkUser(user, 0);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* assign user id */
|
||||
id=AQH_HttpService_GetNextUserId(sv);
|
||||
AQH_User_SetId(user, id);
|
||||
|
||||
rv=AQH_HttpService_SaveUser(sv, user);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
AQH_Service_AddUser(sv, user);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_HttpService_DelUser(AQH_SERVICE *sv, AQH_USER *user)
|
||||
{
|
||||
const char *sAlias;
|
||||
GWEN_BUFFER *nameBuf;
|
||||
uint32_t userId;
|
||||
|
||||
sAlias=AQH_User_GetAlias(user);
|
||||
userId=AQH_User_GetId(user);
|
||||
nameBuf=_getUserFilePath(sv, sAlias);
|
||||
unlink(GWEN_Buffer_GetStart(nameBuf));
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
AQH_Service_DelUser(sv, userId);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_SESSION *AQH_HttpService_LoadSession(const AQH_SERVICE *sv, const char *sessionUid)
|
||||
{
|
||||
GWEN_BUFFER *nameBuf;
|
||||
int rv;
|
||||
GWEN_DB_NODE *db;
|
||||
AQH_SESSION *session;
|
||||
|
||||
db=GWEN_DB_Group_new("user");
|
||||
|
||||
nameBuf=_getSessionFilePath(sv, sessionUid);
|
||||
rv=GWEN_DB_ReadFile(db, GWEN_Buffer_GetStart(nameBuf), GWEN_DB_FLAGS_DEFAULT | GWEN_DB_FLAGS_LOCKFILE);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
GWEN_DB_Group_free(db);
|
||||
return NULL;
|
||||
}
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
|
||||
session=AQH_Session_fromDb(db);
|
||||
if (session==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error loading session \"%s\" from config group", sessionUid);
|
||||
GWEN_DB_Group_free(db);
|
||||
return NULL;
|
||||
}
|
||||
GWEN_DB_Group_free(db);
|
||||
|
||||
rv=_checkSession(session);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Invalid data for session \"%s\"", sessionUid);
|
||||
AQH_Session_free(session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_HttpService_SaveSession(const AQH_SERVICE *sv, const AQH_SESSION *session)
|
||||
{
|
||||
int rv;
|
||||
const char *sUid;
|
||||
GWEN_BUFFER *nameBuf;
|
||||
GWEN_DB_NODE *db;
|
||||
|
||||
rv=_checkSession(session);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
db=GWEN_DB_Group_new("user");
|
||||
rv=AQH_Session_toDb(session, db);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
GWEN_DB_Group_free(db);
|
||||
return rv;
|
||||
}
|
||||
|
||||
sUid=AQH_Session_GetUid(session);
|
||||
nameBuf=_getSessionFilePath(sv, sUid);
|
||||
rv=_writeDbFile(GWEN_Buffer_GetStart(nameBuf), db);
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
GWEN_DB_Group_free(db);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_HttpService_AddSession(AQH_SERVICE *sv, AQH_SESSION *session)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv=_checkSession(session);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv=AQH_HttpService_SaveSession(sv, session);
|
||||
if (rv<0) {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
AQH_Service_AddSession(sv, session);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_HttpService_DelSession(AQH_SERVICE *sv, AQH_SESSION *session)
|
||||
{
|
||||
const char *uid;
|
||||
GWEN_BUFFER *nameBuf;
|
||||
|
||||
uid=AQH_Session_GetUid(session);
|
||||
nameBuf=_getSessionFilePath(sv, uid);
|
||||
unlink(GWEN_Buffer_GetStart(nameBuf));
|
||||
GWEN_Buffer_free(nameBuf);
|
||||
AQH_Service_DelSession(sv, uid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MODULE *_ensureModule(AQH_SERVICE *sv, const char *modName)
|
||||
{
|
||||
AQH_MODULE *module;
|
||||
|
||||
module=AQH_Service_GetModuleByName(sv, modName);
|
||||
if (module)
|
||||
return module;
|
||||
|
||||
module=AQH_HttpService_LoadModule(sv, modName);
|
||||
if (module==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Could not load module \"%s\"", modName);
|
||||
return NULL;
|
||||
}
|
||||
AQH_Service_AddModule(sv, module);
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_USER *_ensureUser(AQH_SERVICE *sv, const char *alias)
|
||||
{
|
||||
AQH_USER *user;
|
||||
|
||||
user=AQH_Service_GetUserByAlias(sv, alias);
|
||||
if (user)
|
||||
return user;
|
||||
|
||||
user=AQH_HttpService_LoadUser(sv, alias);
|
||||
if (user==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Could not load user \"%s\"", alias);
|
||||
return NULL;
|
||||
}
|
||||
_calculateUserPerms(sv, user);
|
||||
|
||||
AQH_Service_AddUser(sv, user);
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_SESSION *_ensureSession(AQH_SERVICE *sv, const char *sessionUid)
|
||||
{
|
||||
AQH_SESSION *session;
|
||||
|
||||
session=AQH_Service_GetSessionByUid(sv, sessionUid);
|
||||
if (session)
|
||||
return session;
|
||||
|
||||
session=AQH_HttpService_LoadSession(sv, sessionUid);
|
||||
if (session) {
|
||||
AQH_USER *user;
|
||||
|
||||
user=AQH_HttpService_GetUser(sv, AQH_Session_GetUserAlias(session));
|
||||
if (user==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "User \"%s\" for session \"%s\" not available", AQH_Session_GetUserAlias(session), sessionUid);
|
||||
AQH_Session_free(session);
|
||||
return NULL;
|
||||
}
|
||||
AQH_User_Attach(user);
|
||||
AQH_Session_SetUser(session, user);
|
||||
AQH_Service_AddSession(sv, session);
|
||||
}
|
||||
|
||||
if (session==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Could not load session \"%s\"", sessionUid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_BUFFER *_getConfigFilePath(const AQH_SERVICE *sv, const char *fileName)
|
||||
{
|
||||
const char *configFolder;
|
||||
|
||||
configFolder=AQH_HttpService_GetConfigFolder(sv);
|
||||
if (!(configFolder && *configFolder)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "No config folder given");
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
GWEN_BUFFER *nameBuf;
|
||||
|
||||
nameBuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendString(nameBuf, configFolder);
|
||||
GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S AQH_HTTP_SERVICE_DIR_SESSIONS GWEN_DIR_SEPARATOR_S);
|
||||
GWEN_Text_EscapeToBuffer(fileName, nameBuf);
|
||||
return nameBuf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
GWEN_BUFFER *_getModuleFilePath(const AQH_SERVICE *sv, const char *modName)
|
||||
{
|
||||
const char *configFolder;
|
||||
|
||||
configFolder=AQH_HttpService_GetConfigFolder(sv);
|
||||
if (!(configFolder && *configFolder)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "No config folder given");
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
GWEN_BUFFER *nameBuf;
|
||||
|
||||
nameBuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendString(nameBuf, configFolder);
|
||||
GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S AQH_HTTP_SERVICE_DIR_MODS GWEN_DIR_SEPARATOR_S);
|
||||
GWEN_Text_EscapeToBuffer(modName, nameBuf);
|
||||
GWEN_Buffer_AppendString(nameBuf, ".conf");
|
||||
return nameBuf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
GWEN_BUFFER *_getUserFilePath(const AQH_SERVICE *sv, const char *userAlias)
|
||||
{
|
||||
const char *configFolder;
|
||||
|
||||
configFolder=AQH_HttpService_GetConfigFolder(sv);
|
||||
if (!(configFolder && *configFolder)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "No config folder given");
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
GWEN_BUFFER *nameBuf;
|
||||
|
||||
nameBuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendString(nameBuf, configFolder);
|
||||
GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S AQH_HTTP_SERVICE_DIR_USERS GWEN_DIR_SEPARATOR_S);
|
||||
GWEN_Text_EscapeToBuffer(userAlias, nameBuf);
|
||||
GWEN_Buffer_AppendString(nameBuf, ".conf");
|
||||
return nameBuf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
GWEN_BUFFER *_getSessionFilePath(const AQH_SERVICE *sv, const char *sessionUid)
|
||||
{
|
||||
const char *configFolder;
|
||||
|
||||
configFolder=AQH_HttpService_GetConfigFolder(sv);
|
||||
if (!(configFolder && *configFolder)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "No config folder given");
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
GWEN_BUFFER *nameBuf;
|
||||
|
||||
nameBuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendString(nameBuf, configFolder);
|
||||
GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S AQH_HTTP_SERVICE_DIR_SESSIONS GWEN_DIR_SEPARATOR_S);
|
||||
GWEN_Text_EscapeToBuffer(sessionUid, nameBuf);
|
||||
GWEN_Buffer_AppendString(nameBuf, ".conf");
|
||||
return nameBuf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _checkUser(const AQH_USER *user, int ignoreMissingId)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
if (!ignoreMissingId) {
|
||||
uint32_t id;
|
||||
|
||||
id=AQH_User_GetId(user);
|
||||
if (id==0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid user: no id");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
s=AQH_User_GetAlias(user);
|
||||
if (!(s && *s)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid user: no alias");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
s=AQH_User_GetHashedPassword(user);
|
||||
if (!(s && *s)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid user: no password");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
s=AQH_User_GetEmail(user);
|
||||
if (!(s && *s)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid user: no email");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _checkSession(const AQH_SESSION *session)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
s=AQH_Session_GetUid(session);
|
||||
if (!(s && *s)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid session: no uid");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
s=AQH_Session_GetUserAlias(session);
|
||||
if (!(s && *s)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid session: no user alias");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
if (AQH_Session_GetTimestampCreation(session)==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid session: no creation time");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _checkModule(const AQH_MODULE *m, int ignoreMissingId)
|
||||
{
|
||||
const char *s;
|
||||
const AQH_ROLE_LIST *roleList;
|
||||
int rv;
|
||||
|
||||
if (!ignoreMissingId) {
|
||||
if (AQH_Module_GetId(m)==0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid module: missing id");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
s=AQH_Module_GetName(m);
|
||||
if (!(s && *s)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid module: missing name");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
roleList=AQH_Module_GetRoleList(m);
|
||||
if (roleList==NULL || AQH_Role_List_GetCount(roleList)<1) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid module: empty or missing role list");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
rv=_checkRoleList(roleList, ignoreMissingId);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid module %s: invalid role definition", AQH_Module_GetName(m));
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _checkRoleList(const AQH_ROLE_LIST *roleList, int ignoreMissingId)
|
||||
{
|
||||
const AQH_ROLE *r;
|
||||
|
||||
r=AQH_Role_List_First(roleList);
|
||||
while(r) {
|
||||
const char *s;
|
||||
|
||||
if (!ignoreMissingId) {
|
||||
if (AQH_Role_GetId(r)==0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid role: missing id");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
s=AQH_Role_GetName(r);
|
||||
if (!(s && *s)) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Invalid role: missing name");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
r=AQH_Role_List_Next(r);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _calculateUserPerms(AQH_SERVICE *sv, AQH_USER *user)
|
||||
{
|
||||
AQH_MODULE_PERMS_LIST *permList;
|
||||
|
||||
permList=AQH_User_GetModulePermList(user);
|
||||
if (permList) {
|
||||
AQH_MODULE_PERMS *p;
|
||||
|
||||
p=AQH_ModulePerms_List_First(permList);
|
||||
while(p) {
|
||||
_calculateModuleUserPerms(sv, p);
|
||||
p=AQH_ModulePerms_List_Next(p);
|
||||
}
|
||||
}
|
||||
AQH_User_AddRuntimeFlags(user, AQH_USER_RTFLAGS_PERMSCALC);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _calculateModuleUserPerms(AQH_SERVICE *sv, AQH_MODULE_PERMS *p)
|
||||
{
|
||||
uint32_t perms=0;
|
||||
uint32_t addPerms=0;
|
||||
uint32_t delPerms=0;
|
||||
const AQH_MODULE *m;
|
||||
|
||||
m=AQH_Service_GetModuleById(sv, AQH_ModulePerms_GetModuleId(p));
|
||||
if (m==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Module \"%d\" not found, ignoring", AQH_ModulePerms_GetModuleId(p));
|
||||
}
|
||||
else {
|
||||
const AQH_ROLE_LIST *roleList;
|
||||
|
||||
roleList=AQH_Module_GetRoleList(m);
|
||||
if (roleList) {
|
||||
int i, j;
|
||||
|
||||
j=AQH_ModulePerms_GetRoleArrayArraySize();
|
||||
for(i=0; i<j; i++) {
|
||||
uint8_t roleId;
|
||||
|
||||
roleId=AQH_ModulePerms_GetRoleArrayAt(p, i);
|
||||
if (roleId>0) {
|
||||
AQH_ROLE *r;
|
||||
|
||||
r=AQH_Role_List_GetById(roleList, roleId);
|
||||
if (r==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Role %d not found in module \"%s\", ignoring", roleId, AQH_Module_GetName(m));
|
||||
}
|
||||
else {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Module \"%s\": adding perms for role \"%s\"", AQH_Module_GetName(m), AQH_Role_GetName(r));
|
||||
perms|=AQH_Role_GetPerms(r);
|
||||
addPerms|=AQH_Role_GetExplAddPerms(r);
|
||||
delPerms|=AQH_Role_GetExplDelPerms(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
perms|=addPerms;
|
||||
perms&=~delPerms;
|
||||
AQH_ModulePerms_SetPerms(p, perms);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _writeDbFile(const char *fname, GWEN_DB_NODE *db)
|
||||
{
|
||||
GWEN_BUFFER *tmpFilenameBuf;
|
||||
int rv;
|
||||
|
||||
tmpFilenameBuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
GWEN_Buffer_AppendString(tmpFilenameBuf, fname);
|
||||
GWEN_Buffer_AppendString(tmpFilenameBuf, ".tmp");
|
||||
unlink(GWEN_Buffer_GetStart(tmpFilenameBuf));
|
||||
rv=GWEN_DB_WriteFile(db, GWEN_Buffer_GetStart(tmpFilenameBuf), GWEN_DB_FLAGS_DEFAULT | GWEN_DB_FLAGS_LOCKFILE);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error writing db file \"%s\": %d", GWEN_Buffer_GetStart(tmpFilenameBuf), rv);
|
||||
GWEN_Buffer_free(tmpFilenameBuf);
|
||||
return rv;
|
||||
}
|
||||
if (rename(GWEN_Buffer_GetStart(tmpFilenameBuf), fname)<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error renaming tmp file to \"%s\": %d (%s)", fname, errno, strerror(errno));
|
||||
GWEN_Buffer_free(tmpFilenameBuf);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
unlink(GWEN_Buffer_GetStart(tmpFilenameBuf));
|
||||
GWEN_Buffer_free(tmpFilenameBuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user