mirror of
https://codeberg.org/grunfink/snac2.git
synced 2024-11-09 19:50:26 +03:00
More mastoapi work.
This commit is contained in:
parent
4ced03bac1
commit
ccce01d285
179
mastoapi.c
179
mastoapi.c
@ -71,6 +71,56 @@ xs_dict *app_get(const char *id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int token_add(const char *id, const xs_dict *token)
|
||||||
|
/* stores a token */
|
||||||
|
{
|
||||||
|
int status = 201;
|
||||||
|
xs *fn = xs_fmt("%s/token/", srv_basedir);
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
mkdirx(fn);
|
||||||
|
fn = xs_str_cat(fn, id);
|
||||||
|
fn = xs_str_cat(fn, ".json");
|
||||||
|
|
||||||
|
if ((f = fopen(fn, "w")) != NULL) {
|
||||||
|
xs *j = xs_json_dumps_pp(token, 4);
|
||||||
|
fwrite(j, strlen(j), 1, f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
status = 500;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xs_dict *token_get(const char *id)
|
||||||
|
/* gets a token */
|
||||||
|
{
|
||||||
|
xs *fn = xs_fmt("%s/token/%s.json", srv_basedir, id);
|
||||||
|
xs_dict *token = NULL;
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
if ((f = fopen(fn, "r")) != NULL) {
|
||||||
|
xs *j = xs_readall(f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
token = xs_json_loads(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int token_del(const char *id)
|
||||||
|
/* deletes a token */
|
||||||
|
{
|
||||||
|
xs *fn = xs_fmt("%s/token/%s.json", srv_basedir, id);
|
||||||
|
|
||||||
|
return unlink(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *login_page = ""
|
const char *login_page = ""
|
||||||
"<!DOCTYPE html>\n"
|
"<!DOCTYPE html>\n"
|
||||||
"<body><h1>%s OAuth identify</h1>\n"
|
"<body><h1>%s OAuth identify</h1>\n"
|
||||||
@ -176,7 +226,18 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
|
|||||||
*body = xs_fmt("%s?code=%s", redir, code);
|
*body = xs_fmt("%s?code=%s", redir, code);
|
||||||
status = 303;
|
status = 303;
|
||||||
|
|
||||||
srv_debug(0, xs_fmt("oauth x-snac-login: redirect to %s", *body));
|
srv_debug(0, xs_fmt("oauth x-snac-login: success, redirect to %s", *body));
|
||||||
|
|
||||||
|
/* assign the login to the app */
|
||||||
|
xs *app = app_get(cid);
|
||||||
|
|
||||||
|
if (app != NULL) {
|
||||||
|
app = xs_dict_set(app, "uid", login);
|
||||||
|
app = xs_dict_set(app, "code", code);
|
||||||
|
app_add(cid, app);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
srv_log(xs_fmt("oauth x-snac-login: error getting app %s", cid));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
srv_debug(0, xs_fmt("oauth x-snac-login: login '%s' incorrect", login));
|
srv_debug(0, xs_fmt("oauth x-snac-login: login '%s' incorrect", login));
|
||||||
@ -198,19 +259,44 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
|
|||||||
const char *ruri = xs_dict_get(msg, "redirect_uri");
|
const char *ruri = xs_dict_get(msg, "redirect_uri");
|
||||||
|
|
||||||
if (gtype && code && cid && csec && ruri) {
|
if (gtype && code && cid && csec && ruri) {
|
||||||
xs *rsp = xs_dict_new();
|
xs *app = app_get(cid);
|
||||||
xs *cat = xs_number_new(time(NULL));
|
|
||||||
xs *token = random_str();
|
|
||||||
|
|
||||||
rsp = xs_dict_append(rsp, "access_token", token);
|
if (app == NULL) {
|
||||||
rsp = xs_dict_append(rsp, "token_type", "Bearer");
|
status = 401;
|
||||||
rsp = xs_dict_append(rsp, "created_at", cat);
|
srv_log(xs_fmt("oauth token: invalid app %s", cid));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (strcmp(csec, xs_dict_get(app, "client_secret")) != 0) {
|
||||||
|
status = 401;
|
||||||
|
srv_log(xs_fmt("oauth token: invalid client_secret for app %s", cid));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
xs *rsp = xs_dict_new();
|
||||||
|
xs *cat = xs_number_new(time(NULL));
|
||||||
|
xs *tokid = random_str();
|
||||||
|
|
||||||
*body = xs_json_dumps_pp(rsp, 4);
|
rsp = xs_dict_append(rsp, "access_token", tokid);
|
||||||
*ctype = "application/json";
|
rsp = xs_dict_append(rsp, "token_type", "Bearer");
|
||||||
status = 200;
|
rsp = xs_dict_append(rsp, "created_at", cat);
|
||||||
|
|
||||||
srv_debug(0, xs_fmt("oauth token: successful login, token %s", token));
|
*body = xs_json_dumps_pp(rsp, 4);
|
||||||
|
*ctype = "application/json";
|
||||||
|
status = 200;
|
||||||
|
|
||||||
|
const char *uid = xs_dict_get(app, "uid");
|
||||||
|
|
||||||
|
srv_debug(0, xs_fmt("oauth token: "
|
||||||
|
"successful login for %s, new token %s", uid, tokid));
|
||||||
|
|
||||||
|
xs *token = xs_dict_new();
|
||||||
|
token = xs_dict_append(token, "token", tokid);
|
||||||
|
token = xs_dict_append(token, "client_id", cid);
|
||||||
|
token = xs_dict_append(token, "client_secret", csec);
|
||||||
|
token = xs_dict_append(token, "uid", uid);
|
||||||
|
token = xs_dict_append(token, "code", code);
|
||||||
|
|
||||||
|
token_add(tokid, token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
srv_debug(0, xs_fmt("oauth token: invalid or unset arguments"));
|
srv_debug(0, xs_fmt("oauth token: invalid or unset arguments"));
|
||||||
@ -221,15 +307,28 @@ int oauth_post_handler(const xs_dict *req, const char *q_path,
|
|||||||
if (strcmp(cmd, "/revoke") == 0) {
|
if (strcmp(cmd, "/revoke") == 0) {
|
||||||
const char *cid = xs_dict_get(msg, "client_id");
|
const char *cid = xs_dict_get(msg, "client_id");
|
||||||
const char *csec = xs_dict_get(msg, "client_secret");
|
const char *csec = xs_dict_get(msg, "client_secret");
|
||||||
const char *token = xs_dict_get(msg, "token");
|
const char *tokid = xs_dict_get(msg, "token");
|
||||||
|
|
||||||
|
if (cid && csec && tokid) {
|
||||||
|
xs *token = token_get(tokid);
|
||||||
|
|
||||||
if (cid && csec && token) {
|
|
||||||
*body = xs_str_new("{}");
|
*body = xs_str_new("{}");
|
||||||
*ctype = "application/json";
|
*ctype = "application/json";
|
||||||
status = 200;
|
|
||||||
|
if (token == NULL || strcmp(csec, xs_dict_get(token, "client_secret")) != 0) {
|
||||||
|
srv_debug(0, xs_fmt("oauth revoke: bad secret for token %s", tokid));
|
||||||
|
status = 403;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
token_del(tokid);
|
||||||
|
srv_debug(0, xs_fmt("oauth revoke: revoked token %s", tokid));
|
||||||
|
status = 200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
srv_debug(0, xs_fmt("oauth revoke: invalid or unset arguments"));
|
||||||
|
status = 403;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
status = 400;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -242,6 +341,8 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
|
|||||||
if (!xs_startswith(q_path, "/api/v1/"))
|
if (!xs_startswith(q_path, "/api/v1/"))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
srv_debug(0, xs_fmt("mastoapi_get_handler %s", q_path));
|
||||||
|
|
||||||
{
|
{
|
||||||
xs *j = xs_json_dumps_pp(req, 4);
|
xs *j = xs_json_dumps_pp(req, 4);
|
||||||
printf("mastoapi get:\n%s\n", j);
|
printf("mastoapi get:\n%s\n", j);
|
||||||
@ -250,12 +351,56 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path,
|
|||||||
int status = 404;
|
int status = 404;
|
||||||
xs_dict *msg = xs_dict_get(req, "q_vars");
|
xs_dict *msg = xs_dict_get(req, "q_vars");
|
||||||
xs *cmd = xs_replace(q_path, "/api/v1", "");
|
xs *cmd = xs_replace(q_path, "/api/v1", "");
|
||||||
|
char *v;
|
||||||
|
|
||||||
srv_debug(0, xs_fmt("mastoapi_get_handler %s", q_path));
|
snac snac = {0};
|
||||||
|
int logged_in = 0;
|
||||||
|
|
||||||
|
/* if there is an authorization field, try to validate it */
|
||||||
|
if (!xs_is_null(v = xs_dict_get(req, "authorization")) && xs_startswith(v, "Bearer ")) {
|
||||||
|
xs *tokid = xs_replace(v, "Bearer ", "");
|
||||||
|
xs *token = token_get(tokid);
|
||||||
|
|
||||||
|
if (token != NULL) {
|
||||||
|
const char *uid = xs_dict_get(token, "uid");
|
||||||
|
|
||||||
|
if (!xs_is_null(uid) && user_open(&snac, uid)) {
|
||||||
|
logged_in = 1;
|
||||||
|
srv_debug(0, xs_fmt("mastoapi auth: valid token for user %s", uid));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
srv_log(xs_fmt("mastoapi auth: corrupted token %s", tokid));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
srv_log(xs_fmt("mastoapi auth: invalid token %s", tokid));
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(cmd, "/accounts/verify_credentials") == 0) {
|
if (strcmp(cmd, "/accounts/verify_credentials") == 0) {
|
||||||
|
if (logged_in) {
|
||||||
|
xs_dict *acct = xs_dict_new();
|
||||||
|
|
||||||
|
acct = xs_dict_append(acct, "id", xs_dict_get(snac.config, "uid"));
|
||||||
|
acct = xs_dict_append(acct, "username", xs_dict_get(snac.config, "uid"));
|
||||||
|
acct = xs_dict_append(acct, "acct", xs_dict_get(snac.config, "uid"));
|
||||||
|
acct = xs_dict_append(acct, "display_name", xs_dict_get(snac.config, "name"));
|
||||||
|
acct = xs_dict_append(acct, "created_at", xs_dict_get(snac.config, "published"));
|
||||||
|
acct = xs_dict_append(acct, "note", xs_dict_get(snac.config, "bio"));
|
||||||
|
acct = xs_dict_append(acct, "url", snac.actor);
|
||||||
|
acct = xs_dict_append(acct, "avatar", xs_dict_get(snac.config, "avatar"));
|
||||||
|
|
||||||
|
*body = xs_json_dumps_pp(acct, 4);
|
||||||
|
*ctype = "application/json";
|
||||||
|
status = 200;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
status = 422; // "Unprocessable entity" (no login)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* user cleanup */
|
||||||
|
if (logged_in)
|
||||||
|
user_free(&snac);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user