timekeeper

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

commit 9d4d0b357b18093737927460423b06ff785242b7
parent 334c3728d0e769f0a79a65c32eb03e3590335f24
Author: Jacob R. Edwards <jacob@jacobedwards.org>
Date:   Tue,  5 Mar 2024 23:58:39 -0800

Take login process out of pages

Now loadpagerequest() is called to setup the pagedata struct, and
it contains a pointer to a struct for the logged in user (or NULL).

This really takes a load off of every page making things a lot more
simple.

Diffstat:
Mpage.c | 31++++++++++++++++++++++++++++++-
Mpage.h | 5+++++
Mpages/account.c | 11+++--------
Mpages/index.c | 11++++-------
Mpages/login.c | 13++++++-------
Mpages/logout.c | 13+++++--------
Mpages/main.c | 11++++-------
Mpages/util.c | 10----------
Mpages/util.h | 1-
Mtimekeeper.c | 3++-
Muser.h | 2++
11 files changed, 61 insertions(+), 50 deletions(-)

diff --git a/page.c b/page.c @@ -1,3 +1,5 @@ +#define const + #include <sys/types.h> #include <stdarg.h> #include <stddef.h> @@ -5,7 +7,35 @@ #include <kcgi.h> #include <kcgihtml.h> +#include "user.h" #include "page.h" +#include "key.h" + +enum kcgi_err +loadpagerequest(struct kfcgi *fcgi, struct pagedata *pd) +{ + enum kcgi_err status; + + status = khttp_fcgi_parse(fcgi, &pd->req); + if (status != KCGI_OK) + return status; + + pd->user = NULL; + if (!pd->req.cookiemap[KeyHash]) + return KCGI_OK; + + pd->user = getuser(pd, "hash", pd->req.cookiemap[KeyHash]->parsed.s); + /* propagate errors from getuser to here and handle them */ + + return KCGI_OK; +} + +void +freepagerequest(struct pagedata *pd) +{ + freeuser(pd->user); + khttp_free(&pd->req); +} enum kcgi_err showpage(struct pagedata *pd, char **names, @@ -23,7 +53,6 @@ showpage(struct pagedata *pd, char **names, names[(pd->req.page == len ? (len - 1) : pd->req.page)], status); } - khttp_free(&pd->req); return status; } diff --git a/page.h b/page.h @@ -1,3 +1,5 @@ +struct user; + struct pagedata { struct kreq req; struct khtmlreq html; @@ -5,7 +7,10 @@ struct pagedata { size_t dbid; struct kvalid *keys; char **pages; /* page names */ + struct user *user; }; +enum kcgi_err loadpagerequest(struct kfcgi *fcgi, struct pagedata *pd); +void freepagerequest(struct pagedata *pd); enum kcgi_err showpage(struct pagedata *pd, char **names, enum kcgi_err (*functions[])(struct pagedata *), size_t len); diff --git a/pages/account.c b/pages/account.c @@ -7,14 +7,12 @@ enum kcgi_err pageaccount(struct pagedata *pd) { enum kcgi_err status; - struct user *user; - user = sitegetlogin(pd); - if (!user) + 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, user->hash) == 0) + if (deleteuser(pd, pd->user->hash) == 0) return redirect(pd, pd->pages[PageIndex], "Account deleted"); else return errorpage(pd, KHTTP_500); @@ -40,11 +38,8 @@ pageaccount(struct pagedata *pd) KATTR_TYPE, "submit", KATTR_VALUE, "Delete", KATTR__MAX)) != KCGI_OK || - (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK) { - freeuser(user); + (status = khtml_closeelem(&pd->html, 1)) != KCGI_OK) return status; - } - freeuser(user); return khtml_close(&pd->html); } diff --git a/pages/index.c b/pages/index.c @@ -6,22 +6,19 @@ enum kcgi_err pageindex(struct pagedata *pd) { enum kcgi_err status; - struct user *user; - - user = sitegetlogin(pd); if ((status = starthtmldoc(pd, KHTTP_200)) != KCGI_OK) return status; khtml_elem(&pd->html, KELEM_H1); - khtml_printf(&pd->html, "Welcome %s!", user ? user->name : "friend"); + khtml_printf(&pd->html, "Welcome %s!", pd->user ? pd->user->name : "friend"); khtml_closeelem(&pd->html, 1); - if ((status = htmllink(pd, user ? "/logout" : "/login", - user ? "Logout" : "Login")) != KCGI_OK) + if ((status = htmllink(pd, pd->user ? "/logout" : "/login", + pd->user ? "Logout" : "Login")) != KCGI_OK) return status; - if (user) { + if (pd->user) { if ((status = khtml_puts(&pd->html, " | ")) != KCGI_OK || (status = htmllink(pd, pd->pages[PageAccount], "Manage account"))) return status; diff --git a/pages/login.c b/pages/login.c @@ -33,12 +33,14 @@ enum kcgi_err pagelogin(struct pagedata *pd) { enum kcgi_err status; - struct user *user; + struct user *user = NULL; char *fuser, *fpass; enum LoginStatus ls; char *msg; - user = NULL; + if (pd->user) + return redirect(pd, pd->pages[PageIndex], "Logged in"); + ls = LoginUntried; if (pd->req.fieldmap[KeyUsername] && pd->req.fieldmap[KeyPassword]) { fuser = pd->req.fieldmap[KeyUsername]->parsed.s; @@ -54,17 +56,14 @@ pagelogin(struct pagedata *pd) if (ls == LoginValid) { status = khttp_head(&pd->req, kresps[KRESP_SET_COOKIE], "%s=%s; Path=/", pd->keys[KeyHash].name, user->hash); + freeuser(user); if (status != KCGI_OK) return status; + return redirect(pd, pd->pages[PageIndex], "Logged in"); } } - } else { - user = sitegetlogin(pd); } - if (user) - return redirect(pd, pd->pages[PageIndex], "Logged in"); - if ((status = starthtmldoc(pd, KHTTP_200)) != KCGI_OK) return status; diff --git a/pages/logout.c b/pages/logout.c @@ -1,19 +1,16 @@ #include "common.h" - #include "pages.h" enum kcgi_err pagelogout(struct pagedata *pd) { enum kcgi_err status; - struct user *user; - if ((user = sitegetlogin(pd))) { - freeuser(user); - if ((status = khttp_head(&pd->req, kresps[KRESP_SET_COOKIE], - "%s=; Path=/", pd->keys[KeyHash].name)) != KCGI_OK) - return status; - } + if (!pd->user) + return errorpage(pd, KHTTP_500); + if ((status = khttp_head(&pd->req, kresps[KRESP_SET_COOKIE], + "%s=; Path=/", pd->keys[KeyHash].name)) != KCGI_OK) + return status; return redirect(pd, pd->pages[PageIndex], "You are being logged out"); } diff --git a/pages/main.c b/pages/main.c @@ -246,22 +246,20 @@ enum kcgi_err pagemain(struct pagedata *pd) { enum kcgi_err status; - struct user *user; enum time_field tf; time_t *times; size_t ntimes; - user = sitegetlogin(pd); - if (!user) + if (!pd->user) return errorpage(pd, KHTTP_401); if (pd->req.fieldmap[KeyTime]) { tf = gettf(pd->req.fieldmap[KeyTime]->parsed.s); if (tf < 0) err(1, "Invalid time field"); - if (tf == StartTime && newrow(pd, user->hash) != SQLBOX_CODE_OK) + if (tf == StartTime && newrow(pd, pd->user->hash) != SQLBOX_CODE_OK) err(1, "New time"); - if (settime(pd, user->hash, tf, time(NULL))) + if (settime(pd, pd->user->hash, tf, time(NULL))) return KCGI_SYSTEM; } @@ -269,7 +267,7 @@ pagemain(struct pagedata *pd) if (status != KCGI_OK) return status; - times = gettimes(pd, user->hash, &ntimes); + times = gettimes(pd, pd->user->hash, &ntimes); if (!times) err(1, "gettimes"); @@ -280,6 +278,5 @@ pagemain(struct pagedata *pd) } free(times); - freeuser(user); return khtml_close(&pd->html); } diff --git a/pages/util.c b/pages/util.c @@ -8,7 +8,6 @@ #include <kcgihtml.h> #include "../page.h" -#include "../user.h" #include "../key.h" enum kcgi_err @@ -69,12 +68,3 @@ redirect(struct pagedata *pd, char *to, char *msg) return status; return khtml_close(&pd->html); } - -/* getlogin is taken */ -struct user * -sitegetlogin(struct pagedata *pd) -{ - if (!pd->req.cookiemap[KeyHash]) - return NULL; - return getuser(pd, "hash", pd->req.cookiemap[KeyHash]->parsed.s); -} diff --git a/pages/util.h b/pages/util.h @@ -1,4 +1,3 @@ enum kcgi_err errorpage(struct pagedata *pd, enum khttp code); enum kcgi_err starthtmldoc(struct pagedata *pd, enum khttp code); enum kcgi_err redirect(struct pagedata *pd, char *to, char *msg); -struct user *sitegetlogin(struct pagedata *pd); diff --git a/timekeeper.c b/timekeeper.c @@ -92,9 +92,10 @@ main(void) err(1, "Unable to setup database"); status = KCGI_OK; - while ((status = khttp_fcgi_parse(fcgi, &pd.req)) == KCGI_OK) { + while (loadpagerequest(fcgi, &pd) == KCGI_OK) { /* Ignore return value */ showpage(&pd, pages, pagefunctions, Len(pages)); + freepagerequest(&pd); } sqlbox_free(pd.db); diff --git a/user.h b/user.h @@ -15,6 +15,8 @@ struct user { char *hash; }; +struct pagedata; + int adduser(struct pagedata *pd, char *name, char *key); void freeuser(struct user *user); struct user *getuser(struct pagedata *pd, char *field, char *value);