diff options
author | Michael McVady <femtonaut@gmail.com> | 2023-02-25 13:32:49 -0600 |
---|---|---|
committer | Michael McVady <femtonaut@gmail.com> | 2023-02-25 13:32:49 -0600 |
commit | 100bd1f5c9d1788e956660499e4cf96ef121c1c5 (patch) | |
tree | d7b361058a487329b40745b1b23346b117b9e4e7 | |
parent | 174907730bd2175bddc896cb6484918e2e5064f5 (diff) |
Hack in PATCH `/posts` endpoint
-rw-r--r-- | README.md | 13 | ||||
-rw-r--r-- | conf/clog.conf | 7 | ||||
-rw-r--r-- | src/clog.c | 115 | ||||
-rw-r--r-- | src/queries.h | 7 |
4 files changed, 126 insertions, 16 deletions
@@ -4,7 +4,7 @@ An attempt to reimplement flog, using the [kore.io](https://kore.io) framework. ## Running -``` +```sh make fetch-dependencies docker compose up ``` @@ -14,7 +14,7 @@ docker compose up To run locally modify `conf/clog.conf`, comment out `root /var/chroot/` and uncomment the `skip chroot` section: -``` +```conf privsep worker { runas clog @@ -26,7 +26,7 @@ privsep worker { Maybe disable `seccomp_tracing` in `conf/clog.conf` if running into problems: -``` +```conf seccomp_tracing no # seccomp_tracing yes ``` @@ -35,8 +35,9 @@ seccomp_tracing no `psql` and load `db/db.sql`, `db/data.sql` for `db/data.sql`. - ## TODO -* Have `tests.py` load and drop database. -* only do HTTP stuff at the edge. +1. Have `tests.py` load and drop database. +1. ~Only do HTTP stuff at the edge.~ +1. `PUT`/`PATCH`? posts. +1. pagination diff --git a/conf/clog.conf b/conf/clog.conf index 9000d65..f26429b 100644 --- a/conf/clog.conf +++ b/conf/clog.conf @@ -43,7 +43,12 @@ domain * { } route ^/posts/[a-z0-9\-]+$ { - handler delete_posts_resource + handler put_posts + methods put + } + + route ^/posts/[a-z0-9\-]+$ { + handler delete_posts methods delete } @@ -71,15 +71,13 @@ int redirect(struct http_request *req); int get_posts(struct http_request *req); int get_posts_resource(struct http_request *req); int post_posts(struct http_request *req); -int delete_posts_resource(struct http_request *req); +int put_posts(struct http_request *req); +int delete_posts(struct http_request *req); int sql_select_posts(struct post_query *pq); +int sql_update_posts(const char *id, const char *title, const char *body); int sql_delete_posts(const char *id); -int sql_insert_posts( - const char *id, - const char *title, - const char *body -); +int sql_insert_posts(const char *id, const char *title, const char *body); int sql_render_posts(struct kore_pgsql *sql, struct post_query *pq); static void process_md_output(const MD_CHAR *, MD_SIZE size, void *); @@ -92,7 +90,6 @@ void post_query_init(struct post_query *pq, enum content_type type, const char * pq->id = NULL; pq->type = type; - pq->status = QUERY_STATUS_OK; pq->result = kore_buf_alloc(0); } @@ -346,6 +343,75 @@ out: ; return KORE_RESULT_OK; } +int put_posts(struct http_request *req) { + int err = 0; + + int status = HTTP_STATUS_OK; + + enum content_type type = get_content_type(req); + + const char *id = NULL; + const char *title = NULL; + const char *body = NULL; + + struct kore_json_item *item = NULL; + struct kore_json json; + + kore_json_init(&json, req->http_body->data, req->http_body->length); + + id = req->path + strlen("/posts/"); + + // Check for valid resource UUID + kore_log(LOG_DEBUG, "Resource id /posts/%s.", id); + err = validate_uuid(id); + if (err == KORE_RESULT_ERROR) { + kore_log(LOG_ERR, "Invalid post id %s.", id); + http_err_resp(req, type, HTTP_STATUS_NOT_FOUND); + goto out; + } + + if (!kore_json_parse(&json)) { + status = HTTP_STATUS_BAD_REQUEST; + kore_log(LOG_ERR, "error parsing json: %s\n", kore_json_strerror()); + goto out; + } + + item = kore_json_find_string(json.root, "title"); + if (item != NULL) { + title = item->data.string; + kore_log(LOG_INFO, "title = '%s'\n", title); + } else { + status = HTTP_STATUS_BAD_REQUEST; + kore_log(LOG_ERR, "Error parsing title: %s\n", kore_json_strerror()); + goto out; + } + + item = kore_json_find_string(json.root, "body"); + if (item != NULL) { + body = item->data.string; + kore_log(LOG_INFO, "body = '%s'\n", body); + } else { + status = HTTP_STATUS_BAD_REQUEST; + kore_log(LOG_ERR, "Error parsing body: %s\n", kore_json_strerror()); + goto out; + } + + err = sql_update_posts(id, title, body); + + if (err == KORE_RESULT_ERROR) { + status = HTTP_STATUS_INTERNAL_ERROR; + goto out; + } + +out: ; + + http_err_resp(req, type, status); + + kore_json_cleanup(&json); + + return KORE_RESULT_OK; +} + int sql_select_posts(struct post_query *pq) { int err = KORE_RESULT_OK; @@ -408,7 +474,7 @@ out: ; return err; } -int delete_posts_resource(struct http_request *req) { +int delete_posts(struct http_request *req) { int err = 0; enum content_type type = get_content_type(req); @@ -545,6 +611,39 @@ out: ; return err; } +int sql_update_posts(const char *id, const char *title, const char *body) { + int err = KORE_RESULT_OK; + + struct kore_pgsql sql; + kore_pgsql_init(&sql); + + err = kore_pgsql_setup(&sql, database, KORE_PGSQL_SYNC); + if (err == KORE_RESULT_ERROR) { + kore_pgsql_logerror(&sql); + goto out; + } + + err = kore_pgsql_query_params( + &sql, + q_update_posts, + 0, + 3, + KORE_PGSQL_PARAM_TEXT(title), + KORE_PGSQL_PARAM_TEXT(body), + KORE_PGSQL_PARAM_TEXT(id) + ); + if (err == KORE_RESULT_ERROR) { + kore_pgsql_logerror(&sql); + goto out; + } + +out: ; + + kore_pgsql_cleanup(&sql); + + return err; +} + int sql_delete_posts(const char *id) { int err = KORE_RESULT_OK; diff --git a/src/queries.h b/src/queries.h index 809d259..6230f41 100644 --- a/src/queries.h +++ b/src/queries.h @@ -36,9 +36,14 @@ const char *q_insert_posts_with_id = \ "($1, $2, $3) " "RETURNING id;"; +const char *q_update_posts = \ +"UPDATE posts " +"SET title = $1, body = $2, updated_at = NOW() " +"WHERE id = $3 " +"RETURNING id;"; + const char *q_delete_posts = \ "DELETE " "FROM posts " "WHERE id = $1 " "RETURNING id;"; - |