timekeeper

[Abandoned unfinished] CGI web application in C for time tracking. (My first, just a learning project)
Log | Files | Refs | README

commit e287822c97c5f3a3a7bcaf27a86d28f243d308b0
parent bc89555c9a6325dfafc171736b75ed1432ed20ec
Author: Jacob R. Edwards <jacob@jacobedwards.org>
Date:   Sun, 24 Mar 2024 20:41:58 -0700

Add button to revoke session tokens in account page

Also change revoketokens() return type from sqlbox_code to int
because in this case it only matters if it succeeds or fails, not
why it fails.

Diffstat:
Mpages/account.c | 46+++++++++++++++++++++++++++++++++++++++-------
Mstmt.c | 3+++
Mstmt.h | 1+
Muser.c | 10++++++++++
Muser.h | 1+
5 files changed, 54 insertions(+), 7 deletions(-)

diff --git a/pages/account.c b/pages/account.c @@ -1,8 +1,13 @@ +#define const + #include <string.h> #include "common.h" #include "pages.h" +#define DeleteAccountStr "account" +#define DeleteAuthTokensStr "logins" + enum kcgi_err pageaccount(struct pagedata *pd) { @@ -11,22 +16,49 @@ pageaccount(struct pagedata *pd) "Account", .css = css }; + char *k; enum kcgi_err status; if (!pd->user) return errorpage(pd, KHTTP_401); - if (pd->req.fieldmap[KeyDelete] && strcmp(pd->req.fieldmap[KeyDelete]->parsed.s, "yes") == 0) { - if (deleteuser(pd, pd->user->hash) == 0) - return redirect(pd, pd->pages[PageIndex], "Account deleted"); - else - return errorpage(pd, KHTTP_500); + if (pd->req.fieldmap[KeyDelete]) { + k = pd->req.fieldmap[KeyDelete]->parsed.s; + if (strcmp(k, DeleteAccountStr) == 0) { + if (deleteuser(pd, pd->user->hash) == 0) + return redirect(pd, pd->pages[PageIndex], "Account deleted"); + else + return errorpage(pd, KHTTP_500); + } else if (strcmp(k, DeleteAuthTokensStr) == 0) { + if (revoketokens(pd, pd->user->hash)) + return errorpage(pd, KHTTP_500); + else + return redirect(pd, pd->pages[PageIndex], "Session revoked"); + } } if ((status = tk_startpage(pd, &template, KHTTP_200)) != KCGI_OK || (status = htmlwithin(pd, KELEM_H1, "Account")) != KCGI_OK || - (status = htmlwithin(pd, KELEM_H2, "Delete account")) != KCGI_OK || + (status = htmlwithin(pd, KELEM_H2, "Manage Sessions")) != KCGI_OK || + /* Session Management */ + (status = khtml_elem(&pd->html, KELEM_FORM)) != KCGI_OK || + (status = khtml_elem(&pd->html, KELEM_LABEL)) != KCGI_OK || + (status = khtml_puts(&pd->html, "Revoke session keys: ")) != KCGI_OK || + (status = khtml_attr(&pd->html, KELEM_INPUT, + KATTR_TYPE, "hidden", + KATTR_NAME, pd->keys[KeyDelete].name, + KATTR_VALUE, DeleteAuthTokensStr, + KATTR__MAX)) != KCGI_OK || + (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK || + (status = khtml_putc(&pd->html, ' ')) != KCGI_OK || + (status = khtml_attr(&pd->html, KELEM_INPUT, + KATTR_TYPE, "submit", + KATTR_VALUE, "Revoke", + KATTR__MAX)) != KCGI_OK || + (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK || + /* Account Deletion */ + (status = htmlwithin(pd, KELEM_H2, "Delete Account")) != KCGI_OK || (status = htmlwithin(pd, KELEM_P, "Deleting an account is irreversible:" " no account data can be restored after deletion.")) != KCGI_OK || (status = khtml_elem(&pd->html, KELEM_FORM)) != KCGI_OK || @@ -35,7 +67,7 @@ pageaccount(struct pagedata *pd) (status = khtml_attr(&pd->html, KELEM_INPUT, KATTR_TYPE, "checkbox", KATTR_NAME, pd->keys[KeyDelete].name, - KATTR_VALUE, "yes", + KATTR_VALUE, DeleteAccountStr, KATTR_REQUIRED, "true", KATTR__MAX)) != KCGI_OK || (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK || diff --git a/stmt.c b/stmt.c @@ -72,6 +72,9 @@ struct sqlbox_pstmt pstmts[] = { [StmtAddAuthToken] = { .stmt = "INSERT into authtokens VALUES (?, ?, ?, unixepoch())" }, + [StmtRevokeAuthTokens] = { .stmt = + "DELETE FROM authtokens WHERE userid IS ?" + }, /* * Currently, the user can set the end time with a diff --git a/stmt.h b/stmt.h @@ -12,6 +12,7 @@ enum StmtID { StmtGetUserByToken, StmtDeleteUser, StmtAddAuthToken, + StmtRevokeAuthTokens, StmtStartTime, StmtStartBreakTime, StmtEndBreakTime, diff --git a/user.c b/user.c @@ -143,6 +143,16 @@ addtoken(struct pagedata *pd, char *hash, char *token, time_t expires) Len(params), params, 0); } +int +revoketokens(struct pagedata *pd, char *hash) +{ + struct sqlbox_parm param = + { .sparm = hash, .type = SQLBOX_PARM_STRING }; + + return sqlbox_exec(pd->db, pd->dbid, StmtRevokeAuthTokens, 1, &param, 0) != + SQLBOX_CODE_OK; +} + char * newtoken(struct pagedata *pd, char *hash) { diff --git a/user.h b/user.h @@ -29,3 +29,4 @@ enum user_error getuser(struct user **user, struct pagedata *pd, char *field, char *value); enum user_error loginuser(struct user **ruser, struct pagedata *pd, char *name, char *key); +int revoketokens(struct pagedata *pd, char *hash);