Begin implementing user privileges.

This commit is contained in:
Jordan Bancino 2023-04-16 17:51:03 +00:00
parent 768ecda41a
commit 4ee66ae3c7
6 changed files with 169 additions and 4 deletions

View file

@ -1,4 +1,4 @@
.Dd $Mdocdate: March 4 2023 $ .Dd $Mdocdate: April 16 2023 $
.Dt ADMIN 7 .Dt ADMIN 7
.Os Telodendria Project .Os Telodendria Project
.Sh NAME .Sh NAME
@ -49,6 +49,11 @@ endpoint.
.It Dv ISSUE_TOKENS .It Dv ISSUE_TOKENS
This allows users to create, modify and delete registration This allows users to create, modify and delete registration
tokens. tokens.
.It Dv CONFIG
Users with this privilege can modify Telodendria's configuration.
.It Dv GRANT_PRIVILEGES
Users with this privilege can modify their own privileges or
the privileges of others.
.It Dv ALL .It Dv ALL
Users with this privilege can use Users with this privilege can use
.Em any .Em any

View file

@ -30,6 +30,7 @@
#include <Json.h> #include <Json.h>
#include <Util.h> #include <Util.h>
#include <Str.h> #include <Str.h>
#include <User.h>
int int
RegTokenValid(RegTokenInfo * token) RegTokenValid(RegTokenInfo * token)
@ -139,6 +140,9 @@ RegTokenGetInfo(Db * db, char *token)
ret->used = ret->used =
JsonValueAsInteger(HashMapGet(tokenJson, "used")); JsonValueAsInteger(HashMapGet(tokenJson, "used"));
ret->grants =
UserDecodePrivileges(HashMapGet(tokenJson, "grants"));
return ret; return ret;
} }
@ -192,7 +196,7 @@ RegTokenVerify(char *token)
} }
RegTokenInfo * RegTokenInfo *
RegTokenCreate(Db * db, char *name, char *owner, unsigned long expires, int uses) RegTokenCreate(Db * db, char *name, char *owner, unsigned long expires, int uses, int privileges)
{ {
RegTokenInfo *ret; RegTokenInfo *ret;
HashMap *tokenJson; HashMap *tokenJson;
@ -233,6 +237,7 @@ RegTokenCreate(Db * db, char *name, char *owner, unsigned long expires, int uses
ret->uses = uses; ret->uses = uses;
ret->created = timestamp; ret->created = timestamp;
ret->expires = expires; ret->expires = expires;
ret->grants = privileges;
/* Write user info to database. */ /* Write user info to database. */
tokenJson = DbJson(ret->ref); tokenJson = DbJson(ret->ref);
@ -246,6 +251,7 @@ RegTokenCreate(Db * db, char *name, char *owner, unsigned long expires, int uses
JsonValueInteger(ret->used)); JsonValueInteger(ret->used));
HashMapSet(tokenJson, "uses", HashMapSet(tokenJson, "uses",
JsonValueInteger(ret->uses)); JsonValueInteger(ret->uses));
HashMapSet(tokenJson, "grants", UserEncodePrivileges(privileges));
return ret; return ret;
} }

View file

@ -127,7 +127,7 @@ ROUTE_IMPL(RouteUserProfile, path, argp)
strcmp(entry, "avatar_url") == 0) strcmp(entry, "avatar_url") == 0)
{ {
/* Check if user has privilege to do that action. */ /* Check if user has privilege to do that action. */
if (!strcmp(userId->localpart, UserGetName(user))) if (strcmp(userId->localpart, UserGetName(user)) == 0)
{ {
value = JsonValueAsString(HashMapGet(request, entry)); value = JsonValueAsString(HashMapGet(request, entry));
/* TODO: Make UserSetProfile notify other /* TODO: Make UserSetProfile notify other

View file

@ -688,6 +688,140 @@ UserDeleteTokens(User * user, char *exempt)
return 1; return 1;
} }
int
UserGetPrivileges(User *user)
{
if (!user)
{
return USER_NONE;
}
return UserDecodePrivileges(HashMapGet(DbJson(user->ref), "privileges"));
}
int
UserSetPrivileges(User *user, int privileges)
{
JsonValue *val;
if (!user)
{
return 0;
}
if (!privileges)
{
JsonValueFree(HashMapDelete(DbJson(user->ref), "privileges"));
return 1;
}
val = UserEncodePrivileges(privileges);
if (!val)
{
return 0;
}
JsonValueFree(HashMapSet(DbJson(user->ref), "privileges", val));
return 1;
}
int
UserDecodePrivileges(JsonValue *val)
{
int privileges = USER_NONE;
size_t i;
Array *arr;
if (!val)
{
goto finish;
}
if (JsonValueType(val) == JSON_ARRAY)
{
arr = JsonValueAsArray(val);
for (i = 0; i < ArraySize(arr); i++)
{
val = ArrayGet(arr, i);
if (!val || JsonValueType(val) != JSON_STRING)
{
continue;
}
privileges |= UserDecodePrivilege(JsonValueAsString(val));
}
}
finish:
return privileges;
}
int
UserDecodePrivilege(const char *p)
{
if (!p)
{
return USER_NONE;
}
else if (strcmp(p, "ALL") == 0)
{
return USER_ALL;
}
else if (strcmp(p, "DEACTIVATE") == 0)
{
return USER_DEACTIVATE;
}
else if (strcmp(p, "ISSUE_TOKENS") == 0)
{
return USER_ISSUE_TOKENS;
}
else if (strcmp(p, "CONFIG") == 0)
{
return USER_CONFIG;
}
else if (strcmp(p, "GRANT_PRIVILEGES") == 0)
{
return USER_GRANT_PRIVILEGES;
}
else
{
return USER_NONE;
}
}
JsonValue *
UserEncodePrivileges(int privileges)
{
Array *arr = ArrayCreate();
if (!arr)
{
return NULL;
}
if (privileges & USER_ALL)
{
ArrayAdd(arr, JsonValueString("ALL"));
goto finish;
}
#define A(priv, as) \
if (privileges & priv) \
{ \
ArrayAdd(arr, JsonValueString(as)); \
}
A(USER_DEACTIVATE, "DEACTIVATE");
A(USER_ISSUE_TOKENS, "ISSUE_TOKENS");
A(USER_CONFIG, "CONFIG");
A(USER_GRANT_PRIVILEGES, "GRANT_PRIVILEGES");
#undef A
finish:
return JsonValueArray(arr);
}
UserId * UserId *
UserIdParse(char *id, char *defaultServer) UserIdParse(char *id, char *defaultServer)
{ {

View file

@ -40,6 +40,8 @@ typedef struct RegTokenInfo
unsigned long created; unsigned long created;
unsigned long expires; unsigned long expires;
int grants; /* privileges */
} RegTokenInfo; } RegTokenInfo;
@ -56,7 +58,7 @@ extern RegTokenInfo *
RegTokenGetInfo(Db *, char *); RegTokenGetInfo(Db *, char *);
extern RegTokenInfo * extern RegTokenInfo *
RegTokenCreate(Db *, char *, char *, unsigned long, int); RegTokenCreate(Db *, char *, char *, unsigned long, int, int);
extern void extern void
RegTokenFree(RegTokenInfo *); RegTokenFree(RegTokenInfo *);

View file

@ -28,6 +28,14 @@
#include <Json.h> #include <Json.h>
#define USER_DEACTIVATE (1 << 0)
#define USER_ISSUE_TOKENS (1 << 1)
#define USER_CONFIG (1 << 2)
#define USER_GRANT_PRIVILEGES (1 << 3)
#define USER_NONE 0
#define USER_ALL ((1 << 4) - 1)
typedef struct User User; typedef struct User User;
typedef struct UserAccessToken typedef struct UserAccessToken
@ -113,6 +121,16 @@ extern void
extern int extern int
UserDeleteTokens(User *, char *); UserDeleteTokens(User *, char *);
extern int UserGetPrivileges(User *);
extern int UserSetPrivileges(User *, int);
extern int UserDecodePrivileges(JsonValue *);
extern JsonValue *UserEncodePrivileges(int);
extern int UserDecodePrivilege(const char *);
extern UserId * extern UserId *
UserIdParse(char *, char *); UserIdParse(char *, char *);