diff --git a/src/web_chat/iu9_ca_web_chat_lib/backend_logic/admin_control_procedure.cpp b/src/web_chat/iu9_ca_web_chat_lib/backend_logic/admin_control_procedure.cpp index 4d7a81d..d1325e3 100644 --- a/src/web_chat/iu9_ca_web_chat_lib/backend_logic/admin_control_procedure.cpp +++ b/src/web_chat/iu9_ca_web_chat_lib/backend_logic/admin_control_procedure.cpp @@ -1,30 +1,81 @@ #include "server_data_interact.h" #include -#include #include "../str_fields.h" +#include namespace iu9cawebchat { + /* nagative `forced_id` means id isn't forced */ + void add_user(SqliteConnection& conn, const std::string& nickname, const std::string& name, + const std::string& password, const std::string& bio, int64_t forced_id) { + if (!check_nickname(nickname)) + een9_THROW("Bad user nickname " + nickname + ". Can't reg"); + if (!check_name(name)) + een9_THROW("Bad user name " + name + ". Can't reg"); + if (!check_strong_password(password)) + een9_THROW("Bad user password. Can't reg"); + if (!is_orthodox_string(bio)) + een9_THROW("Bad user bio. Can't reg"); + if (is_nickname_taken(conn, nickname)) + een9_THROW("Nickname taken already. Can't reg"); + reserve_nickname(conn, nickname); + SqliteStatement req(conn, + "INSERT INTO `user` (`id`, `nickname`, `name`, `chatList_HistoryId`, `password`, `bio`) " + "VALUES (?1, ?2, ?3, 0, ?4, ?5)", {}, {{2, nickname}, {3, name}, {4, password}, {5, bio}}); + if (forced_id >= 0) + sqlite_stmt_bind_int64(req, 1, forced_id); + int must_be_done = sqlite_stmt_step(req, {}, {}); + if (must_be_done != SQLITE_DONE) + een9_THROW("sqlite error"); + } + std::string admin_control_procedure(SqliteConnection& conn, const std::string& req, bool& termination) { - if (req == "hello") { + size_t nid = 0; + auto read_thing = [&]() -> std::string { + while (nid < req.size() && isSPACE(req[nid])) + nid++; + std::string result; + bool esc = false; + while (nid < req.size() && (esc || !isSPACE(req[nid]))) { + if (esc) { + result += req[nid]; + esc = false; + } else if (req[nid] == '\\') { + esc = true; + } else { + result += req[nid]; + } + nid++; + } + return result; + }; + + std::string cmd = read_thing(); + if (cmd == "hello") { return ":0 omg! hiii!! Hewwou :3 !!!!\n"; } - if (req == "8") { + if (cmd == "8") { termination = true; return "Bye\n"; } - std::string updaterootpw_pref = "updaterootpw"; - if (een9::beginsWith(req, "updaterootpw")) { - size_t nid = updaterootpw_pref.size(); - if (nid >= req.size() || !isSPACE(req[nid])) - return "Bad command syntax. Missing whitespace\n"; - std::string new_password = req.substr(nid + 1); - if (!check_password(new_password)) - een9_THROW("Bad password"); + const char* adduser_pref = "adduser"; + if (cmd == "updaterootpw") { + + std::string new_password = read_thing(); + if (!check_strong_password(new_password)) + return "Bad password. Can't update"; sqlite_nooutput(conn, - "UPDATE `user` SET `password` = ?1 WHERE `id` = 0 ", - {}, {{1, new_password}}); + "UPDATE `user` SET `password` = ?1 WHERE `id` = 0", {}, {{1, new_password}}); return "Successul update\n"; } + /* adduser */ + if (cmd == "adduser") { + std::string nickname = read_thing(); + std::string name = read_thing(); + std::string password = read_thing(); + std::string bio = read_thing(); + add_user(conn, nickname, name, password, bio); + return "User " + nickname + " successfully registered"; + } return "Incorrect command\n"; } } diff --git a/src/web_chat/iu9_ca_web_chat_lib/backend_logic/server_data_interact.h b/src/web_chat/iu9_ca_web_chat_lib/backend_logic/server_data_interact.h index 2d04c09..6da7244 100644 --- a/src/web_chat/iu9_ca_web_chat_lib/backend_logic/server_data_interact.h +++ b/src/web_chat/iu9_ca_web_chat_lib/backend_logic/server_data_interact.h @@ -79,6 +79,8 @@ namespace iu9cawebchat { json::JSON internalapi_leaveChat(SqliteConnection& conn, int64_t uid, const json::JSON& Sent); /**/ + void add_user(SqliteConnection& conn, const std::string& nickname, const std::string& name, + const std::string& password, const std::string& bio, int64_t forced_id = -1); std::string admin_control_procedure(SqliteConnection& conn, const std::string& req, bool& termination); } diff --git a/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_chat.cpp b/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_chat.cpp index c0481ba..7063865 100644 --- a/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_chat.cpp +++ b/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_chat.cpp @@ -34,18 +34,22 @@ namespace iu9cawebchat { bool chat_members = (path_segs[0] == "chat-members"); - - // todo: do not throw id chat not found, catch exception and return 404 - json::JSON openedchat; - RowChat_Content chatInfo = lookup_chat_content_by_nickname(*wgd.db, chat_nickname); + RowChat_Content chatInfo; + try { + chatInfo = lookup_chat_content_by_nickname(*wgd.db, chat_nickname); + } catch (const std::exception& e) { + return page_E404(wgd); + } if (get_role_of_user_in_chat(*wgd.db, userinfo["id"].asInteger().get_int(), chatInfo.id) == user_chat_role_deleted) { return page_E404(wgd); } - openedchat["name"] = json::JSON(chatInfo.name); - openedchat["nickname"] = json::JSON(chatInfo.nickname); - openedchat["id"] = json::JSON(chatInfo.id); - openedchat["selectedMessageId"] = json::JSON(selected_message_id); // -1 means that nothing was selected + json::JSON openedchat; + openedchat["name"].asString() = chatInfo.name; + openedchat["nickname"].asString() = chatInfo.nickname; + openedchat["id"].asInteger() = json::Integer(chatInfo.id); + // -1 means that nothing was selected + openedchat["selectedMessageId"].asInteger() = json::Integer(selected_message_id); json::JSON initial_chatUpdResp = poll_update_chat_ONE_MSG_resp(*wgd.db, chatInfo.id, selected_message_id); if (chat_members) return http_R200("chat", wgd, {&config_presentation, &userinfo, &openedchat, &initial_chatUpdResp}); diff --git a/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_user.cpp b/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_user.cpp index d101165..96e54e0 100644 --- a/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_user.cpp +++ b/src/web_chat/iu9_ca_web_chat_lib/backend_logic/when_user.cpp @@ -50,8 +50,12 @@ namespace iu9cawebchat { return page_E404(wgd); } // todo: in libjsonincpp: fix '999999 problem' - int64_t myuid = userinfo["uid"].asInteger().get_int(); - bool can_edit = (alien.id == myuid); + bool can_edit = false; + int64_t myuid = -1; + if (userinfo.isDictionary()) { + myuid = userinfo["uid"].asInteger().get_int(); + can_edit = (alien.id == myuid && myuid >= 0); + } if (req.method == "POST") { std::vector> response_hlines; try { @@ -73,17 +77,23 @@ namespace iu9cawebchat { if (!bio.empty()) { if (!is_orthodox_string(bio) || bio.size() > 100000) een9_THROW("Incorrect `bio`"); - sqlite_nooutput(conn, "UPDATE `user` SET `bio` = ?1", {}, {{1, bio}}); + sqlite_nooutput(conn, + "UPDATE `user` SET `bio` = ?1 WHERE `id` = ?2", + {{2, alien.id}}, {{1, bio}}); } if (!name.empty()) { if (!check_name(name)) een9_THROW("Incorrect `name`"); - sqlite_nooutput(conn, "UPDATE `user` SET `name` = ?1", {}, {{1, name}}); + sqlite_nooutput(conn, + "UPDATE `user` SET `name` = ?1 WHERE `id` = ?2", + {{2, alien.id}}, {{1, name}}); } if (!password.empty()) { if (!check_strong_password(password)) een9_THROW("Incorrect `password`"); - sqlite_nooutput(conn, "UPDATE `user` SET `password` = ?1", {}, {{1, password}}); + sqlite_nooutput(conn, + "UPDATE `user` SET `password` = ?1 WHERE `id` = ?2", + {{2, alien.id}}, {{1, password}}); if (alien.id == myuid) { LoginCookie new_login_cookie = create_login_cookie(userinfo["nickname"].asString(), password); add_set_cookie_headers_to_login(login_cookies, response_hlines, new_login_cookie); diff --git a/src/web_chat/iu9_ca_web_chat_lib/initialize.cpp b/src/web_chat/iu9_ca_web_chat_lib/initialize.cpp index bbfb084..ed8a646 100644 --- a/src/web_chat/iu9_ca_web_chat_lib/initialize.cpp +++ b/src/web_chat/iu9_ca_web_chat_lib/initialize.cpp @@ -7,24 +7,27 @@ #include #include #include "sqlite3_wrapper.h" +#include "backend_logic/server_data_interact.h" namespace iu9cawebchat { void initialize_website(const json::JSON& config, const std::string& root_pw) { printf("Initialization...\n"); - een9_ASSERT(check_password(root_pw), "Bad root password"); + if (!check_strong_password(root_pw)) + een9_THROW("Bad root password"); std::string db_path; int ret; ret = find_db_sqlite_file_path(config, db_path); - een9_ASSERT(ret == 0, "Invalid settings[\"database\"] field"); + if (ret != 0) + een9_THROW("Invalid settings[\"database\"] field"); if (een9::isRegularFile(db_path)) { // todo: plaese, don't do this ret = unlink(db_path.c_str()); - een9_ASSERT_pl(ret == 0); + if (ret != 0) + een9_THROW("unlink"); } - een9_ASSERT(!een9::isRegularFile(db_path), "Database file exists prior to initialization. " - "Can't preceed withut harming existing data"); + if (een9::isRegularFile(db_path)) + een9_THROW("Database file exists prior to initialization. Can't preceed withut harming existing data"); SqliteConnection conn(db_path.c_str()); - assert(sqlite3_errcode(conn.hand) == SQLITE_OK); /* Role of memeber of chat: * 1 - admin * 2 - regular @@ -72,10 +75,7 @@ namespace iu9cawebchat { "`chat_IncHistoryId` INTEGER NOT NULL," "PRIMARY KEY (`chatId`, `id`)" ")"); - sqlite_nooutput(conn, "INSERT INTO `nickname` VALUES (?1)", {}, {{1, "root"}}); - sqlite_nooutput(conn, "INSERT INTO `user` (`id`, `nickname`, `name`, `chatList_HistoryId`, `password`, " - "`bio` ) VALUES (0, ?1, ?2, 0, ?3, ?4)", {}, - {{1, "root"}, {2, "Rootov Root Rootovich"}, {3, root_pw}, {4, "One admin to rule them all"}}); + add_user(conn, "root", "Rootov Root Rootovich", root_pw, "One admin to rule them all", 0); sqlite_nooutput(conn, "END"); } catch (const std::exception& e) { sqlite_nooutput(conn, "ROLLBACK", {}, {});