comparison scid/page-api-projects.c @ 18:600204c31bf0

misc: refactor
author David Demelier <markand@malikania.fr>
date Tue, 12 Jul 2022 20:20:51 +0200
parents page-api-projects.c@3051ef92173a
children f98ea578b1ef
comparison
equal deleted inserted replaced
17:40fe70256fb0 18:600204c31bf0
1 /*
2 * page-api-projects.c -- /api/v?/projects route
3 *
4 * Copyright (c) 2021 David Demelier <markand@malikania.fr>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <assert.h>
20
21 #include "config.h"
22 #include "db.h"
23 #include "log.h"
24 #include "page-api-projects.h"
25 #include "page.h"
26 #include "types.h"
27 #include "util.h"
28
29 static void
30 list(struct kreq *r, const struct project *projects, size_t projectsz)
31 {
32 struct json_t *doc;
33 char *dump;
34
35 doc = project_to(projects, projectsz);
36 dump = json_dumps(doc, JSON_COMPACT);
37
38 khttp_puts(r, dump);
39 free(dump);
40 json_decref(doc);
41 }
42
43 static int
44 save(const char *json)
45 {
46 struct project res = {0};
47 int ret = -1;
48
49 json_t *doc;
50 json_error_t err;
51
52 if (!(doc = json_loads(json, 0, &err)))
53 log_warn("api/post: invalid JSON input: %s", err.text);
54 else if (project_from(&res, 1, doc) < 0)
55 log_warn("api/post: failed to decode parameters");
56 else if (db_project_add(&res) < 0)
57 log_warn("api/post: database save error");
58 else
59 ret = 0;
60
61 json_decref(doc);
62
63 return ret;
64 }
65
66 static void
67 push(struct kreq *r, const struct project *p)
68 {
69 struct json_t *json;
70 char *dump;
71
72 json = project_to(p, 1);
73 dump = json_dumps(json, JSON_COMPACT);
74
75 khttp_head(r, kresps[KRESP_CONTENT_TYPE], "%s", kmimetypes[KMIME_APP_JSON]);
76 khttp_head(r, kresps[KRESP_STATUS], "%s", khttps[KHTTP_200]);
77 khttp_body(r);
78 khttp_puts(r, dump);
79 khttp_free(r);
80
81 free(dump);
82 json_decref(json);
83 }
84
85 static void
86 get_one(struct kreq *r, const char *name)
87 {
88 struct db_ctx ctx;
89 struct project project = {
90 .name = name
91 };
92
93 if (db_project_find(&ctx, &project) < 0)
94 page(r, NULL, KHTTP_500, KMIME_APP_JSON, NULL);
95 else {
96 push(r, &project);
97 db_ctx_finish(&ctx);
98 }
99 }
100
101 static void
102 get_one_id(struct kreq *r, int id)
103 {
104 struct db_ctx ctx;
105 struct project project = {
106 .id = id
107 };
108
109 if (db_project_find_id(&ctx, &project) < 0)
110 page(r, NULL, KHTTP_500, KMIME_APP_JSON, NULL);
111 else {
112 push(r, &project);
113 db_ctx_finish(&ctx);
114 }
115 }
116
117 static void
118 get_all(struct kreq *r)
119 {
120 struct db_ctx ctx;
121 struct project projects[SCI_PROJECT_MAX];
122 ssize_t projectsz;
123
124 if ((projectsz = db_project_list(&ctx, projects, UTIL_SIZE(projects))) < 0)
125 page(r, NULL, KHTTP_500, KMIME_APP_JSON, NULL);
126 else {
127 khttp_head(r, kresps[KRESP_CONTENT_TYPE], "%s", kmimetypes[KMIME_APP_JSON]);
128 khttp_head(r, kresps[KRESP_STATUS], "%s", khttps[KHTTP_200]);
129 khttp_body(r);
130 list(r, projects, projectsz);
131 db_ctx_finish(&ctx);
132 khttp_free(r);
133 }
134 }
135
136 static void
137 get(struct kreq *r)
138 {
139 char name[128];
140 int id;
141
142 if (sscanf(r->path, "v1/projects/%d", &id) == 1)
143 get_one_id(r, id);
144 else if (sscanf(r->path, "v1/projects/%127s", name) == 1)
145 get_one(r, name);
146 else
147 get_all(r);
148 }
149
150 static void
151 post(struct kreq *r)
152 {
153 if (r->fieldsz < 1)
154 page(r, NULL, KHTTP_400, KMIME_APP_JSON, NULL);
155 else if (save(r->fields[0].val) < 0)
156 page(r, NULL, KHTTP_500, KMIME_APP_JSON, NULL);
157 else {
158 khttp_head(r, kresps[KRESP_CONTENT_TYPE], "%s", kmimetypes[KMIME_APP_JSON]);
159 khttp_head(r, kresps[KRESP_STATUS], "%s", khttps[KHTTP_200]);
160 khttp_body(r);
161 khttp_free(r);
162 }
163 }
164
165 void
166 page_api_v1_projects(struct kreq *r)
167 {
168 assert(r);
169
170 switch (r->method) {
171 case KMETHOD_GET:
172 get(r);
173 break;
174 case KMETHOD_POST:
175 post(r);
176 break;
177 default:
178 page(r, NULL, KHTTP_400, KMIME_APP_JSON, NULL);
179 break;
180 }
181
182 }