forked from lda/telodendria
Begin implementing user privileges.
This commit is contained in:
parent
768ecda41a
commit
4ee66ae3c7
6 changed files with 169 additions and 4 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
134
src/User.c
134
src/User.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 *);
|
||||||
|
|
|
@ -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 *);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue