From 16471049e22dfee0625874806c31de819284921d Mon Sep 17 00:00:00 2001 From: hatkid Date: Sun, 29 Oct 2023 14:31:19 +0100 Subject: [PATCH] [ADD] Implement GET /_telodendria/admin/tokens (see #26) --- src/Routes.c | 1 + src/Routes/RouteAdminTokens.c | 149 ++++++++++++++++++++++++++++++++++ src/include/Routes.h | 2 + 3 files changed, 152 insertions(+) create mode 100644 src/Routes/RouteAdminTokens.c diff --git a/src/Routes.c b/src/Routes.c index d0d455b..d2a19e6 100644 --- a/src/Routes.c +++ b/src/Routes.c @@ -87,6 +87,7 @@ RouterBuild(void) R("/_telodendria/admin/v1/privileges", RoutePrivileges); R("/_telodendria/admin/v1/privileges/(.*)", RoutePrivileges); R("/_telodendria/admin/v1/deactivate/(.*)", RouteAdminDeactivate); + R("/_telodendria/admin/v1/tokens", RouteAdminTokens); #undef R diff --git a/src/Routes/RouteAdminTokens.c b/src/Routes/RouteAdminTokens.c new file mode 100644 index 0000000..6dd31f0 --- /dev/null +++ b/src/Routes/RouteAdminTokens.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2022-2023 Jordan Bancino <@jordan:bancino.net> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include + +#include +#include +#include + +#include +#include + +ROUTE_IMPL(RouteAdminTokens, path, argp) +{ + RouteArgs *args = argp; + HashMap *response = NULL; + + char *token; + + Db *db = args->matrixArgs->db; + + User *user = NULL; + + HttpRequestMethod method = HttpRequestMethodGet(args->context); + + (void) path; + + if ((method != HTTP_GET)) + { + char *msg = "Route only supports GET for now."; + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + return MatrixErrorCreate(M_UNRECOGNIZED, msg); + } + + + response = MatrixGetAccessToken(args->context, &token); + if (response) + { + goto finish; + } + + user = UserAuthenticate(db, token); + if (!user) + { + HttpResponseStatus(args->context, HTTP_BAD_REQUEST); + response = MatrixErrorCreate(M_UNKNOWN_TOKEN, NULL); + goto finish; + } + + if (!(UserGetPrivileges(user) & USER_ISSUE_TOKENS)) + { + char *msg = "User doesn't have the ISSUE_TOKENS privilege."; + HttpResponseStatus(args->context, HTTP_FORBIDDEN); + response = MatrixErrorCreate(M_FORBIDDEN, msg); + goto finish; + } + + if (method == HTTP_GET) + { + Array *tokensarray = ArrayCreate(); + + /* Get all registration tokens */ + Array *tokens = DbList(db, 2, "tokens", "registration"); + size_t i; + + response = HashMapCreate(); + + for (i = 0; i < ArraySize(tokens); i++) + { + /* NOTE: Sounds like a very unwise idea. */ + char *tokenname = ArrayGet(tokens, i); + char *creator; + UInt64 created; + UInt64 expires; + + Int64 used; + Int64 uses; + + Int64 remaining; + + RegTokenInfo *info = RegTokenGetInfo(db, tokenname); + HashMap *jsoninfo = HashMapCreate(); + + created = info->created; + expires = info->expires; + uses = info->uses; + used = info->used; + + remaining = Int64Sub(uses, used); + if (Int64Eq(uses, Int64Neg(Int64Create(0, 1)))) + { + /* If uses == -1(infinite uses), just set it too + * to -1 */ + remaining = uses; + } + if (!(creator = info->owner)) + { + /* The owner can be null if Telodendria created it. + * Since users can't contain a space, it is in this + * case set to "Telodendria Server". */ + creator = "Telodendria Server"; + } + + HashMapSet(jsoninfo, "name", JsonValueString(tokenname)); + HashMapSet(jsoninfo, "created_by", JsonValueString(creator)); + HashMapSet(jsoninfo, "created_on", JsonValueInteger(created)); + HashMapSet(jsoninfo, "expires_on", JsonValueInteger(expires)); + + HashMapSet(jsoninfo, "used", JsonValueInteger(used)); + + /* #26 says the following: + * "The number of uses *remaining* for the token [...]" + * You therefore can't easily set the uses value here. */ + HashMapSet(jsoninfo, "uses", JsonValueInteger(remaining)); + + RegTokenClose(info); + RegTokenFree(info); + ArrayAdd(tokensarray, JsonValueObject(jsoninfo)); + } + + JsonSet(response, JsonValueArray(tokensarray), 1, "tokens"); + + DbListFree(tokens); + } +finish: + /* TODO */ + UserUnlock(user); + return response; +} diff --git a/src/include/Routes.h b/src/include/Routes.h index 15eeffd..78e5b4b 100644 --- a/src/include/Routes.h +++ b/src/include/Routes.h @@ -105,6 +105,8 @@ ROUTE(RouteRoomAliases); ROUTE(RouteAdminDeactivate); +ROUTE(RouteAdminTokens); + #undef ROUTE #endif