diff --git a/src/main/include/models.h b/src/main/include/models.h index be1030c..cb72680 100644 --- a/src/main/include/models.h +++ b/src/main/include/models.h @@ -19,6 +19,8 @@ klist_user *klist_user_get_by_id(klist *, u_int); klist_user *klist_user_get_by_local(klist *, u_int); klist_user *klist_user_get_by_discord(klist *, u_int); klist_user *klist_user_get_by_google(klist *, u_int); +void klist_user_save(klist *, klist_user *); +void klist_user_delete(klist *, klist_user *); void klist_user_deinit(klist_user *); diff --git a/src/main/include/sql.h b/src/main/include/sql.h index 9b9383e..c6a0fdd 100644 --- a/src/main/include/sql.h +++ b/src/main/include/sql.h @@ -13,6 +13,7 @@ enum KLIST_SQL { MOD_USER_LOCAL, MOD_USER_DISCORD, MOD_USER_GOOGLE, + DEL_USER, ADD_LIST, GET_LIST, GET_LISTS, @@ -32,4 +33,4 @@ enum KLIST_SQL { _KLIST_SQL_COUNT }; -char *klist_sql_get(const enum KLIST_SQL); \ No newline at end of file +const char *klist_sql_get(const enum KLIST_SQL); \ No newline at end of file diff --git a/src/main/include/util.h b/src/main/include/util.h index 9fa7fa1..60a1c20 100644 --- a/src/main/include/util.h +++ b/src/main/include/util.h @@ -28,10 +28,11 @@ void klist_deinit(klist *list); enum klist_user_command { USER_GET, + USER_CREATE, USER_DELETE }; struct klist_user_context { - enum klist_command cmd; + enum klist_user_command cmd; }; typedef struct klist_user_context klist_user_context; diff --git a/src/main/main.c b/src/main/main.c index 8465680..250d6f6 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -3,6 +3,7 @@ #include #include +#include "models.h" #include "util.h" void print_help(char **argv); @@ -18,16 +19,45 @@ int main(int argc, char **argv) { if (!ctx->error) { setup(ctx, argc, argv); + klist_user *user; switch (ctx->cmd) { case USER: switch (((klist_user_context *)ctx->cmd_ctx)->cmd) { case USER_GET: + user = klist_user_get_by_local(ctx, getuid()); + if (user) { + fprintf( + stderr, + "User: %p\nID: %lu\nDiscord: %lu\nGoogle: %lu\n,", + user->name, user->id, user->discord_id, user->google_id + ); + size_t lists_len, i = 0; + klist_list **lists = klist_list_get_all_by_user(ctx, user->id, &lists_len); + fprintf(stderr, "Lists: %lu\n", lists_len); + klist_user_deinit(user); + for (; i < lists_len; i++) klist_list_deinit(lists[i]); + } else fprintf(stderr, "No user for '%s' found.\n", getlogin()); + break; + case USER_CREATE: + fprintf( + stderr, + (klist_assure_user(ctx, getuid(), getlogin())) + ? "User created.\n" + : "User already exists.\n" + ); + break; case USER_DELETE: - default: ; + user = klist_user_get_by_local(ctx, getuid()); + if (user) { + klist_user_delete(ctx, user); + klist_user_deinit(user); + } + break; } case LIST: switch (((klist_list_context *)ctx->cmd_ctx)->cmd) { case LIST_ADD: + case LIST_EDIT: case LIST_GET: case LIST_DELETE: ; @@ -37,8 +67,7 @@ int main(int argc, char **argv) { case TASK_ADD: case TASK_EDIT: case TASK_GET: - case TASK_DELETE: - default: ; + case TASK_DELETE: ; } default: ; } @@ -66,18 +95,22 @@ void setup(klist *ctx, int argc, char **argv) { switch (ctx->cmd) { case USER: optind = 2; - while ((opt = getopt(argc, argv, "dg")) != -1) + klist_user_context *user_ctx = klist_user_context_init(ctx); + while ((opt = getopt(argc, argv, "cdg")) != -1) switch (opt) { + case 'c': + user_ctx->cmd = USER_CREATE; + break; case 'd': - fprintf(stderr, "Deleting user %u\n", getuid()); + user_ctx->cmd = USER_DELETE; break; case 'g': - fprintf(stderr, "Printing user lists\n"); + user_ctx->cmd = USER_GET; break; default: print_help(argv); } - + ctx->cmd_ctx = user_ctx; break; case LIST: if (argc < 3) { @@ -117,6 +150,7 @@ void setup(klist *ctx, int argc, char **argv) { klist_list_context *task_ctx = malloc(sizeof(struct klist_task_context)); optind = 3; + while ((opt = getopt(argc, argv, "aeds:")) != -1) switch (opt) { case 'a': diff --git a/src/main/models.c b/src/main/models.c index 55bb4c5..3c6f34f 100644 --- a/src/main/models.c +++ b/src/main/models.c @@ -1,5 +1,6 @@ #include "models.h" +#include #include #include @@ -49,6 +50,26 @@ klist_user *klist_user_get_by_local(klist *ctx, u_int local_id) { return NULL; } +void klist_user_save(klist *ctx, klist_user *user) { + sqlite3_stmt *stmt = ctx->stmts[ADD_USER]; + int result = 0; + sqlite3_bind_text(stmt, 1, (char*)user->name, -1, SQLITE_STATIC); + sqlite3_bind_int(stmt, 2, user->local_id); + sqlite3_bind_int(stmt, 3, user->discord_id > 0 ? user->discord_id : -1); + sqlite3_bind_int(stmt, 4, user->google_id > 0 ? user->google_id : -1); + if ((result = sqlite3_step(stmt)) == SQLITE_ROW) { + user->id = sqlite3_column_int(stmt, 1); + sqlite3_reset(stmt); + } else fprintf(stderr, "failed to save user: %s - %d\n", sqlite3_errmsg(ctx->db), result); +} + +void klist_user_delete(klist *ctx, klist_user *user) { + sqlite3_stmt *stmt = ctx->stmts[DEL_USER]; + sqlite3_bind_int(stmt, 1, (int)user->id); + if (sqlite3_step(stmt) == SQLITE_ROW) + sqlite3_reset(stmt); +} + void klist_user_deinit(klist_user *user) { free(user->name); free(user); diff --git a/src/main/sql.c b/src/main/sql.c index 6d7964c..baa2ec1 100644 --- a/src/main/sql.c +++ b/src/main/sql.c @@ -1,45 +1,45 @@ #include "include/sql.h" -char *klist_sql_get(const enum KLIST_SQL sql) { +const char *klist_sql_get(const enum KLIST_SQL sql) { switch (sql) { case INIT: return - "create table if not exists users (" - " id integer primary key," - " name text not null," - " local_id integer, -- if the thing is running locally" - " discord_id integer, -- if logging in via web via discord" - " google_id integer -- if logging in via web via google" - ");" - "create table if not exists user_lists (" - " id integer primary key," - " user_id integer not null," - " list_id integer not null" - ");" - "create table if not exists lists (" - " id integer primary key," - " name text not null," - " desc text" - ");" - "create table if not exists task_stages (" - " id integer primary key," - " name text not null," - " desc text," - " list_id integer not null," - " foreign key (list_id) references lists(id)" - ");" - "-- this currently enables moving tasks _between lists_ (calculated of course)" - "create table if not exists tasks (" - " id integer primary key," - " name text not null," - " desc text," - " stage integer not null," - " due date," - " due_stage integer, -- more like target stage" - " foreign key (stage) references task_stages(id)," - " foreign key (due_stage) references task_stages(id)" - ")"; - case ADD_USER: return "insert into users values (?1, ?2, ?3, ?4)"; + "create table if not exists users (\n" + " id integer primary key,\n" + " name text not null,\n" + " local_id integer, -- if the thing is running locally\n" + " discord_id integer, -- if logging in via web via discord\n" + " google_id integer -- if logging in via web via google\n" + ");\n" + "create table if not exists user_lists (\n" + " id integer primary key,\n" + " user_id integer not null,\n" + " list_id integer not null\n" + ");\n" + "create table if not exists lists (\n" + " id integer primary key,\n" + " name text not null,\n" + " desc text\n" + ");\n" + "create table if not exists task_stages (\n" + " id integer primary key,\n" + " name text not null,\n" + " desc text,\n" + " list_id integer not null,\n" + " foreign key (list_id) references lists(id)\n" + ");\n" + "-- this currently enables moving tasks _between lists_ (planned of course)\n" + "create table if not exists tasks (\n" + " id integer primary key,\n" + " name text not null,\n" + " desc text,\n" + " stage integer not null,\n" + " due date,\n" + " due_stage integer, -- more like target stage\n" + " foreign key (stage) references task_stages(id),\n" + " foreign key (due_stage) references task_stages(id)\n" + ")"; + case ADD_USER: return "insert into users (name, local_id, discord_id, google_id) values (?1, ?2, ?3, ?4) returning id"; case GET_USER: return "select * from users where id = ?1"; case GET_USER_BY_LOCAL: return "select * from users where local_id = ?1"; case GET_USER_BY_DISCORD: return "select * from users where discord_id = ?1"; @@ -49,23 +49,24 @@ char *klist_sql_get(const enum KLIST_SQL sql) { case MOD_USER_LOCAL: return "update users set local_id = ?1 where id = ?2";; case MOD_USER_DISCORD: return "update users set discord_id = ?1 where id = ?2"; case MOD_USER_GOOGLE: return "update users set google_id = ?1 where id = ?2"; - case ADD_LIST: return "insert into lists values (?1, ?2)"; + case DEL_USER: return "delete from users where id = ?1"; + case ADD_LIST: return "insert into lists (name, desc) values (?1, ?2)"; case GET_LIST: return "select * from lists where id = ?1"; case GET_LISTS: return "select * from lists"; case GET_LISTS_BY_USER: return "select * from lists where id = (select list_id from user_lists where user_id = ?1)"; case MOD_LIST_NAME: return "update lists set name = ?1 where id = ?2"; case DEL_LIST: return "delete from lists where id = ?1"; - case ADD_STAGE: return "insert into task_stages values (?1, ?2, ?3)"; + case ADD_STAGE: return "insert into task_stages (name, desc, list_id) values (?1, ?2, ?3)"; case GET_STAGE: return "select * from task_stages where id = ?1"; case GET_STAGES_FOR_LIST: return "select * from task_stages"; case DEL_STAGE: return "delete from task_stages where id = ?1"; - case ADD_TASK: return "insert into tasks values (?1, ?2, ?3, ?4, ?5, ?6);"; + case ADD_TASK: return "insert into tasks (name, desc, stage, due, due_stage) values (?1, ?2, ?3, ?4, ?5);"; case GET_TASK: return "select * from tasks where id = ?1"; case GET_TASKS: return "select * from tasks;"; case MOD_TASK_NAME: return "update tasks set name = ?1 where id = ?2"; - case MOD_TASK_DESCRIPTION: return "update tasks set description = ?1 where id = ?2"; + case MOD_TASK_DESCRIPTION: return "update tasks set desc = ?1 where id = ?2"; case DEL_TASK: return "delete from tasks where id = ?1"; - case _KLIST_SQL_COUNT: return ";"; + case _KLIST_SQL_COUNT: return ""; } return ""; } diff --git a/src/main/util.c b/src/main/util.c index e11d695..7549871 100644 --- a/src/main/util.c +++ b/src/main/util.c @@ -2,6 +2,10 @@ #include #include "util.h" + +#include + +#include "models.h" #include "sql.h" /* @@ -10,7 +14,7 @@ klist *klist_init(char *db) { klist *ctx = malloc(sizeof(klist)); - ctx->stmts = malloc(sizeof(sqlite3_stmt *) * _KLIST_SQL_COUNT); + ctx->stmts = malloc(_KLIST_SQL_COUNT * sizeof(sqlite3_stmt *)); ctx->cmd_ctx = NULL; ctx->error = 0; @@ -19,6 +23,9 @@ klist *klist_init(char *db) { return ctx; } void klist_deinit(klist *ctx) { + int i = 0; + for (; i < _KLIST_SQL_COUNT; i++) + sqlite3_finalize(ctx->stmts[i]); sqlite3_close(ctx->db); if (ctx->cmd_ctx) free(ctx->cmd_ctx); free(ctx->stmts); @@ -67,20 +74,39 @@ void klist_task_context_deinit(klist_task_context *ctx) { */ void klist_sql_prepare(klist *ctx, char *db) { - ctx->stmts = malloc(sizeof(sqlite3_stmt *) * _KLIST_SQL_COUNT); - sqlite3_open(db ? db : ":memory:", &ctx->db); - + if (sqlite3_open(db ? db : ":memory:", &ctx->db) != SQLITE_OK) { + fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(ctx->db)); + return; + } int i = 0; for (; i < _KLIST_SQL_COUNT; i++) - if (sqlite3_prepare(ctx->db, klist_sql_get(i), 0, &ctx->stmts[i], NULL) != SQLITE_OK) + if (sqlite3_prepare(ctx->db, klist_sql_get(i), -1, &ctx->stmts[i], NULL) != SQLITE_OK) fprintf(stderr, "sqlite3_prepare: %s\n", sqlite3_errmsg(ctx->db)); - + char *err; + sqlite3_exec(ctx->db, klist_sql_get(INIT), NULL, NULL, &err); + if (err) { + fprintf(stderr, "Failed to initialize, expect errors: %s\n", err); + sqlite3_free(err); + } } /* * assuring things */ -bool klist_assure_user(klist *, __uid_t, char *); +bool klist_assure_user(klist *ctx, __uid_t id, char *name) { + klist_user *user = klist_user_get_by_local(ctx, id); + bool created = false; + if (!user) { + user = klist_user_init(); + user->name = malloc((strlen(name) + 1) * sizeof(char)); + strcpy((char *)user->name, name); + user->local_id = id; + klist_user_save(ctx, user); + created = true; + } + klist_user_deinit(user); + return created; +} void klist_assure_list(klist *, char *); void klist_assure_task(klist *, char *); \ No newline at end of file