This commit is contained in:
parent
85b93fbbe3
commit
059d6d3879
@ -1,14 +1,23 @@
|
||||
find_package(Wt REQUIRED Dbo)
|
||||
|
||||
add_library(Database
|
||||
Database.h Database.cpp
|
||||
Task.h Task.cpp
|
||||
HomeBox.h HomeBox.cpp
|
||||
Session.h Session.cpp
|
||||
Task.h
|
||||
User.h
|
||||
HomeBox.h
|
||||
)
|
||||
|
||||
get_filename_component(PARENT_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
|
||||
|
||||
target_include_directories(Database
|
||||
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
INTERFACE ${PARENT_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(Database
|
||||
PUBLIC sqlite3
|
||||
PUBLIC Universal
|
||||
PUBLIC Wt::Wt
|
||||
PUBLIC Wt::Dbo
|
||||
PRIVATE Wt::DboSqlite3
|
||||
)
|
@ -1,9 +1,29 @@
|
||||
#include "Database.h"
|
||||
#include "BoostLog.h"
|
||||
#include "Session.h"
|
||||
#include <Wt/Dbo/FixedSqlConnectionPool.h>
|
||||
#include <Wt/Dbo/SqlConnectionPool.h>
|
||||
#include <Wt/Dbo/backend/Sqlite3.h>
|
||||
#include <sqlite3.h>
|
||||
#include <sstream>
|
||||
|
||||
std::unique_ptr<Session> Database::session() {
|
||||
if (!m_sqlConnectionPool) return {};
|
||||
return std::make_unique<Session>(*m_sqlConnectionPool);
|
||||
}
|
||||
|
||||
bool Database::open(const std::string &path) {
|
||||
try {
|
||||
auto connection = std::make_unique<Wt::Dbo::backend::Sqlite3>(path);
|
||||
connection->setProperty("show-queries", "true");
|
||||
connection->setDateTimeStorage(Wt::Dbo::SqlDateTimeType::DateTime,
|
||||
Wt::Dbo::backend::DateTimeStorage::PseudoISO8601AsText);
|
||||
m_sqlConnectionPool = std::make_unique<Wt::Dbo::FixedSqlConnectionPool>(std::move(connection), 10);
|
||||
session()->createTables();
|
||||
} catch (const Wt::Dbo::Exception &e) {
|
||||
LOG(error) << e.code() << ": " << e.what();
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
int result = sqlite3_open(path.c_str(), &m_sqlite3);
|
||||
if (result != SQLITE_OK) {
|
||||
@ -14,97 +34,6 @@ bool Database::open(const std::string &path) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int selectTaskCallback(void *data, int argc, char **argv, char **columnName) {
|
||||
auto tasks = reinterpret_cast<Tasks *>(data);
|
||||
Task task;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (argv[i] == nullptr) continue;
|
||||
if (strcmp(columnName[i], "id") == 0) {
|
||||
task.id = std::atol(argv[i]);
|
||||
} else if (strcmp(columnName[i], "create_time") == 0) {
|
||||
task.createTime = std::atol(argv[i]);
|
||||
} else if (strcmp(columnName[i], "content") == 0) {
|
||||
task.content = argv[i];
|
||||
} else if (strcmp(columnName[i], "comment") == 0) {
|
||||
task.comment = argv[i];
|
||||
} else if (strcmp(columnName[i], "finished") == 0) {
|
||||
task.finished = std::atol(argv[i]);
|
||||
} else if (strcmp(columnName[i], "parent_id") == 0) {
|
||||
task.parentId = std::atol(argv[i]);
|
||||
}
|
||||
}
|
||||
tasks->push_back(task);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Tasks Database::tasks() {
|
||||
Tasks ret;
|
||||
char *error = nullptr;
|
||||
if (sqlite3_exec(m_sqlite3, "select * from tasks", selectTaskCallback, &ret, &error) != SQLITE_OK) {
|
||||
LOG(error) << "sqlite3_exec() failed: " << error << std::endl;
|
||||
sqlite3_free(error);
|
||||
}
|
||||
std::unordered_map<int, Task *> tasks;
|
||||
for (auto iterator = ret.begin(); iterator != ret.end();) {
|
||||
if (iterator->parentId >= 0) {
|
||||
if (tasks.count(iterator->parentId) > 0) {
|
||||
auto parentTask = tasks.at(iterator->parentId);
|
||||
parentTask->children.push_back(*iterator);
|
||||
tasks.insert({iterator->id, &parentTask->children.back()});
|
||||
} else {
|
||||
LOG(warning) << "task`s parent id " << iterator->parentId << " not existed.";
|
||||
}
|
||||
iterator = ret.erase(iterator);
|
||||
} else {
|
||||
tasks.insert({iterator->id, &(*iterator)});
|
||||
++iterator;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Database::addTask(uint64_t createTime, const std::string &content, const std::string &comment, int parentId,
|
||||
bool finished) {
|
||||
bool ret = true;
|
||||
std::ostringstream oss;
|
||||
oss << "INSERT INTO tasks (create_time,content,comment,parent_id,finished) VALUES (" << createTime << ",\""
|
||||
<< content << "\",\"" << comment << "\"," << parentId << "," << finished << ");";
|
||||
auto sql = oss.str();
|
||||
char *error = nullptr;
|
||||
int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, &error);
|
||||
if (result != SQLITE_OK) {
|
||||
LOG(error) << "add task failed: " << error << ", sql: " << sql;
|
||||
sqlite3_free(error);
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Database::removeTask(int id) {
|
||||
bool ret = true;
|
||||
std::ostringstream oss;
|
||||
oss << "DELETE FROM tasks WHERE id = " << id << ";";
|
||||
auto sql = oss.str();
|
||||
char *error = nullptr;
|
||||
int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, &error);
|
||||
if (result != SQLITE_OK) {
|
||||
LOG(error) << "add task failed: " << error << ", sql: " << sql;
|
||||
sqlite3_free(error);
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Database::setTaskFinished(int id, bool finished, uint64_t finishedTime) {
|
||||
std::ostringstream oss;
|
||||
oss << "UPDATE tasks SET finished = " << finished << ", finished_time = " << finishedTime << " WHERE id = " << id;
|
||||
auto sql = oss.str();
|
||||
int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, NULL);
|
||||
if (result != SQLITE_OK) {
|
||||
LOG(error) << "add task failed: " << sqlite3_errmsg(m_sqlite3) << ", sql: " << sql;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Database::updateVisitCount(const std::string &url, const std::string &visitorUuid, const std::string &userAgent,
|
||||
int64_t time) {
|
||||
@ -278,72 +207,9 @@ VisitAnalysis Database::visitAnalysisData(const std::string &url) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Database::addHomeBoxItem(const std::string &name, const std::string &location, int cost) {
|
||||
bool ret = true;
|
||||
std::ostringstream oss;
|
||||
oss << "INSERT INTO homebox (name,location,cost) VALUES (\"" << name << "\",\"" << location << "\"," << cost
|
||||
<< ");";
|
||||
auto sql = oss.str();
|
||||
char *error = nullptr;
|
||||
int result = sqlite3_exec(m_sqlite3, sql.c_str(), NULL, NULL, &error);
|
||||
if (result != SQLITE_OK) {
|
||||
LOG(error) << "add task failed: " << error << ", sql: " << sql;
|
||||
sqlite3_free(error);
|
||||
ret = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int selectHomeBoxItemCallback(void *data, int argc, char **argv, char **columnName) {
|
||||
auto items = reinterpret_cast<HomeBox::Items *>(data);
|
||||
HomeBox::Item item;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (argv[i] == nullptr) continue;
|
||||
if (strcmp(columnName[i], "id") == 0) {
|
||||
item.id = std::atol(argv[i]);
|
||||
} else if (strcmp(columnName[i], "name") == 0) {
|
||||
item.name = argv[i];
|
||||
} else if (strcmp(columnName[i], "location") == 0) {
|
||||
item.location = argv[i];
|
||||
} else if (strcmp(columnName[i], "cost") == 0) {
|
||||
item.cost = std::atol(argv[i]);
|
||||
}
|
||||
}
|
||||
items->push_back(item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HomeBox::Items Database::homeBoxItems() {
|
||||
HomeBox::Items ret;
|
||||
char *error = nullptr;
|
||||
if (sqlite3_exec(m_sqlite3, "select * from homebox", selectHomeBoxItemCallback, &ret, &error) != SQLITE_OK) {
|
||||
LOG(error) << "sqlite3_exec() failed: " << error << std::endl;
|
||||
sqlite3_free(error);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Database::initialize() {
|
||||
const char *sql =
|
||||
"CREATE TABLE IF NOT EXISTS tasks (id INTEGER PRIMARY KEY AUTOINCREMENT, create_time INTEGER NOT NULL, "
|
||||
"parent_id INTEGER, content VARCHAR(512) NOT NULL, comment VARCHAR(512) NOT NULL, finished BOLL, finished_time "
|
||||
"INTEGER);";
|
||||
int result = sqlite3_exec(m_sqlite3, sql, NULL, NULL, NULL);
|
||||
if (result != SQLITE_OK) {
|
||||
LOG(error) << "Failed to create table: " << sqlite3_errmsg(m_sqlite3);
|
||||
return;
|
||||
}
|
||||
|
||||
const char *homeBoxSql = "CREATE TABLE IF NOT EXISTS homebox (id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"name VARCHAR(512) NOT NULL, location VARCHAR(512) NOT NULL, cost INTEGER);";
|
||||
result = sqlite3_exec(m_sqlite3, homeBoxSql, NULL, NULL, NULL);
|
||||
if (result != SQLITE_OK) {
|
||||
LOG(error) << "Failed to create table: " << sqlite3_errmsg(m_sqlite3);
|
||||
return;
|
||||
}
|
||||
|
||||
char *message = nullptr;
|
||||
sql = R"(
|
||||
auto sql = R"(
|
||||
CREATE TABLE IF NOT EXISTS visit_analysis (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
url TEXT NOT NULL,
|
||||
@ -353,7 +219,7 @@ void Database::initialize() {
|
||||
page_view_count INTEGER NOT NULL
|
||||
);
|
||||
)";
|
||||
result = sqlite3_exec(m_sqlite3, sql, 0, 0, &message);
|
||||
int result = sqlite3_exec(m_sqlite3, sql, 0, 0, &message);
|
||||
if (result != SQLITE_OK) {
|
||||
LOG(error) << "Failed to create table: " << message << std::endl;
|
||||
sqlite3_free(message);
|
||||
|
@ -6,6 +6,12 @@
|
||||
#include "Task.h"
|
||||
#include <string>
|
||||
|
||||
namespace Wt {
|
||||
namespace Dbo {
|
||||
class SqlConnectionPool;
|
||||
}
|
||||
} // namespace Wt
|
||||
|
||||
class VisitAnalysis {
|
||||
public:
|
||||
std::string url;
|
||||
@ -15,34 +21,28 @@ public:
|
||||
};
|
||||
|
||||
struct sqlite3;
|
||||
class Session;
|
||||
|
||||
class Database {
|
||||
friend class Amass::Singleton<Database>;
|
||||
|
||||
public:
|
||||
~Database();
|
||||
std::unique_ptr<Session> session();
|
||||
bool open(const std::string &path);
|
||||
Tasks tasks();
|
||||
bool addTask(uint64_t createTime, const std::string &content, const std::string &comment = "", int parentId = -1,
|
||||
bool finished = false);
|
||||
bool removeTask(int id);
|
||||
void setTaskFinished(int id, bool finished, uint64_t finishedTime);
|
||||
|
||||
void updateVisitCount(const std::string &url, const std::string &visitorUuid, const std::string &userAgent,
|
||||
int64_t time);
|
||||
void updateVisitCount(const std::string &url, const std::string &visitorUuid, const std::string &userAgent, int64_t time);
|
||||
void clearVisitRecord();
|
||||
VisitAnalysis visitAnalysisData(const std::string &url);
|
||||
VisitAnalysis siteVisitAnalysisData();
|
||||
std::list<VisitAnalysis> mostViewedUrls(int size);
|
||||
std::list<VisitAnalysis> latestViewedUrls(int size);
|
||||
|
||||
HomeBox::Items homeBoxItems();
|
||||
bool addHomeBoxItem(const std::string &name, const std::string &location, int cost);
|
||||
|
||||
protected:
|
||||
void initialize();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Wt::Dbo::SqlConnectionPool> m_sqlConnectionPool;
|
||||
sqlite3 *m_sqlite3 = nullptr;
|
||||
};
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
#include "HomeBox.h"
|
@ -1,20 +1,23 @@
|
||||
#ifndef __HOMEBOX_H__
|
||||
#define __HOMEBOX_H__
|
||||
|
||||
#include <list>
|
||||
#include <Wt/Dbo/Dbo.h>
|
||||
#include <string>
|
||||
|
||||
class HomeBox {
|
||||
public:
|
||||
namespace HomeBox {
|
||||
class Item {
|
||||
public:
|
||||
int id = -1;
|
||||
std::string name;
|
||||
std::string location;
|
||||
int cost;
|
||||
};
|
||||
|
||||
using Items = std::list<Item>;
|
||||
template <class Action>
|
||||
void persist(Action &a) {
|
||||
Wt::Dbo::field(a, name, "name");
|
||||
Wt::Dbo::field(a, location, "location");
|
||||
Wt::Dbo::field(a, cost, "cost");
|
||||
}
|
||||
};
|
||||
} // namespace HomeBox
|
||||
|
||||
#endif // __HOMEBOX_H__
|
@ -1,30 +1,17 @@
|
||||
#include "Session.h"
|
||||
#include "BoostLog.h"
|
||||
#include <Wt/Auth/Dbo/AuthInfo.h>
|
||||
#include <Wt/Auth/Dbo/UserDatabase.h>
|
||||
#include <Wt/Auth/FacebookService.h>
|
||||
#include <Wt/Auth/GoogleService.h>
|
||||
#include <Wt/Auth/HashFunction.h>
|
||||
#include <Wt/Auth/PasswordService.h>
|
||||
#include <Wt/Auth/PasswordStrengthValidator.h>
|
||||
#include <Wt/Auth/PasswordVerifier.h>
|
||||
#include <Wt/Dbo/backend/Sqlite3.h>
|
||||
|
||||
Session::Session(Wt::Dbo::SqlConnectionPool &connectionPool) : m_connectionPool(connectionPool) {
|
||||
setConnectionPool(m_connectionPool);
|
||||
Session::Session(Wt::Dbo::SqlConnectionPool &connectionPool) {
|
||||
setConnectionPool(connectionPool);
|
||||
|
||||
mapClass<Task>("task");
|
||||
mapClass<HomeBox::Item>("homebox_item");
|
||||
|
||||
mapClass<User>("user");
|
||||
mapClass<AuthInfo>("auth_info");
|
||||
mapClass<AuthInfo::AuthIdentityType>("auth_identity");
|
||||
mapClass<AuthInfo::AuthTokenType>("auth_token");
|
||||
|
||||
try {
|
||||
createTables();
|
||||
LOG(info) << "Created database.";
|
||||
} catch (Wt::Dbo::Exception &e) {
|
||||
LOG(error) << e.what() << ", using existing database";
|
||||
}
|
||||
|
||||
m_users = std::make_unique<UserDatabase>(*this);
|
||||
}
|
||||
|
||||
@ -46,3 +33,7 @@ Wt::Auth::AbstractUserDatabase &Session::users() {
|
||||
Wt::Auth::Login &Session::login() {
|
||||
return m_login;
|
||||
}
|
||||
|
||||
DBO_INSTANTIATE_TEMPLATES(User)
|
||||
DBO_INSTANTIATE_TEMPLATES(Task)
|
||||
DBO_INSTANTIATE_TEMPLATES(HomeBox::Item)
|
@ -1,6 +1,8 @@
|
||||
#ifndef __SESSION_H__
|
||||
#define __SESSION_H__
|
||||
|
||||
#include "HomeBox.h"
|
||||
#include "Task.h"
|
||||
#include "User.h"
|
||||
#include <Wt/Auth/Login.h>
|
||||
#include <Wt/Dbo/Session.h>
|
||||
@ -16,7 +18,6 @@ public:
|
||||
Wt::Auth::Login &login();
|
||||
|
||||
private:
|
||||
Wt::Dbo::SqlConnectionPool &m_connectionPool;
|
||||
std::unique_ptr<UserDatabase> m_users;
|
||||
Wt::Auth::Login m_login;
|
||||
};
|
@ -1,34 +0,0 @@
|
||||
#include "Task.h"
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/serialize.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace json {
|
||||
|
||||
static boost::json::object serialize(const Task &task) {
|
||||
boost::json::object ret;
|
||||
ret["id"] = task.id;
|
||||
ret["parentId"] = task.parentId;
|
||||
ret["finished"] = task.finished;
|
||||
ret["createTime"] = task.createTime;
|
||||
ret["content"] = task.content;
|
||||
ret["comment"] = task.comment;
|
||||
|
||||
boost::json::array children;
|
||||
for (auto &child : task.children) {
|
||||
children.push_back(serialize(child));
|
||||
}
|
||||
ret["children"] = std::move(children);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string serialize(const Tasks &tasks) {
|
||||
boost::json::array ret;
|
||||
for (auto &task : tasks) {
|
||||
ret.push_back(serialize(task));
|
||||
}
|
||||
return boost::json::serialize(ret);
|
||||
}
|
||||
} // namespace json
|
||||
} // namespace boost
|
@ -1,31 +1,33 @@
|
||||
#ifndef __TASK_H__
|
||||
#define __TASK_H__
|
||||
|
||||
#include <list>
|
||||
#include <Wt/Dbo/Dbo.h>
|
||||
#include <string>
|
||||
|
||||
class Task;
|
||||
using Tasks = std::list<Task>;
|
||||
using Tasks = Wt::Dbo::collection<Wt::Dbo::ptr<Task>>;
|
||||
|
||||
class Task {
|
||||
public:
|
||||
int id = -1;
|
||||
int parentId = -1;
|
||||
bool finished = false;
|
||||
int32_t createTime = 0;
|
||||
std::string content;
|
||||
std::string comment;
|
||||
|
||||
Wt::Dbo::ptr<Task> parent;
|
||||
Tasks children;
|
||||
|
||||
template <class Action>
|
||||
void persist(Action &a) {
|
||||
Wt::Dbo::field(a, content, "content");
|
||||
Wt::Dbo::field(a, comment, "comment");
|
||||
Wt::Dbo::field(a, finished, "finished");
|
||||
Wt::Dbo::field(a, createTime, "create_time");
|
||||
|
||||
Wt::Dbo::belongsTo(a, parent, "parent");
|
||||
Wt::Dbo::hasMany(a, children, Wt::Dbo::ManyToOne, "parent");
|
||||
}
|
||||
};
|
||||
|
||||
namespace boost {
|
||||
namespace json {
|
||||
std::string serialize(const Tasks &tasks);
|
||||
}
|
||||
} // namespace boost
|
||||
|
||||
#endif // __TASK_H__
|
@ -1,5 +1,6 @@
|
||||
#include "Application.h"
|
||||
#include "Database.h"
|
||||
#include "Database/Database.h"
|
||||
#include "Database/Session.h"
|
||||
#include "DateTime.h"
|
||||
#include "HttpSession.h"
|
||||
#include "IoContext.h"
|
||||
@ -8,6 +9,7 @@
|
||||
#include "ServiceManager.h"
|
||||
#include "SystemUsage.h"
|
||||
#include "WeChatContext/CorporationContext.h"
|
||||
#include <Wt/Dbo/Json.h>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/serialize.hpp>
|
||||
#include <boost/stacktrace.hpp>
|
||||
@ -60,22 +62,23 @@ Application::Application(const std::string &path)
|
||||
|
||||
m_router->insert("/api/v1/tasklist", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||
using namespace boost::beast;
|
||||
auto database = Amass::Singleton<Database>::instance();
|
||||
auto tasks = database->tasks();
|
||||
auto database = Amass::Singleton<Database>::instance()->session();
|
||||
Tasks tasks = database->find<Task>();
|
||||
std::ostringstream oss;
|
||||
Wt::Dbo::jsonSerialize(tasks, oss);
|
||||
|
||||
http::response<boost::beast::http::string_body> s{boost::beast::http::status::ok, request.version()};
|
||||
s.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
s.set(http::field::content_type, "application/json;charset=UTF-8");
|
||||
s.keep_alive(request.keep_alive());
|
||||
s.body() = boost::json::serialize(tasks);
|
||||
s.body() = oss.str();
|
||||
s.prepare_payload();
|
||||
session.reply(std::move(s));
|
||||
});
|
||||
|
||||
m_router->insert("/api/v1/task/add", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||
m_router->insert("/api/v1/task/add", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) mutable {
|
||||
using namespace boost::beast;
|
||||
LOG(info) << "add task: " << request.body();
|
||||
auto database = Amass::Singleton<Database>::instance();
|
||||
auto rootJson = boost::json::parse(request.body());
|
||||
auto &root = rootJson.as_object();
|
||||
|
||||
@ -83,10 +86,18 @@ Application::Application(const std::string &path)
|
||||
if (root.contains("content")) {
|
||||
content = root.at("content").as_string();
|
||||
}
|
||||
bool ret = database->addTask(root.at("createTime").as_int64(), content,
|
||||
std::string(root.at("comment").as_string()), root.at("parentId").as_int64());
|
||||
auto database = Amass::Singleton<Database>::instance()->session();
|
||||
auto task = std::make_unique<Task>();
|
||||
task->createTime = root.at("createTime").as_int64();
|
||||
task->content = content;
|
||||
task->comment = std::string(root.at("comment").as_string());
|
||||
auto t = database->add(std::move(task));
|
||||
Wt::Dbo::ptr<Task> parent = database->find<Task>("where id=?").bind(root.at("parentId").as_int64());
|
||||
if (parent) {
|
||||
parent.modify()->children.insert(t);
|
||||
}
|
||||
boost::json::object reply;
|
||||
reply["status"] = ret ? 0 : -1;
|
||||
reply["status"] = 0;
|
||||
http::response<boost::beast::http::string_body> s{boost::beast::http::status::ok, request.version()};
|
||||
s.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
s.set(http::field::content_type, "application/json;charset=UTF-8");
|
||||
@ -99,11 +110,15 @@ Application::Application(const std::string &path)
|
||||
m_router->insert("/api/v1/task/delete/{id}", [this](HttpSession &session, const Request &request,const boost::urls::matches &matches) {
|
||||
using namespace boost::beast;
|
||||
LOG(info) << "delete task: " << matches.at("id");
|
||||
auto database = Amass::Singleton<Database>::instance();
|
||||
auto status = database->removeTask(std::stoi(matches.at("id")));
|
||||
|
||||
auto database = Amass::Singleton<Database>::instance()->session();
|
||||
Wt::Dbo::ptr<Task> joe = database->find<Task>().where("id = ?").bind(std::stoi(matches.at("id")));
|
||||
int status = -1;
|
||||
if (joe) {
|
||||
joe.remove();
|
||||
status = 0;
|
||||
}
|
||||
boost::json::object reply;
|
||||
reply["status"] = status ? 0 : -1;
|
||||
reply["status"] = status;
|
||||
http::response<boost::beast::http::string_body> s{boost::beast::http::status::ok, request.version()};
|
||||
s.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
s.set(http::field::content_type, "application/json;charset=UTF-8");
|
||||
@ -125,8 +140,7 @@ Application::Application(const std::string &path)
|
||||
ServiceLogic::make_200<boost::beast::http::string_body>(request, "notify successed.\n", "text/html"));
|
||||
});
|
||||
// clang-format on
|
||||
m_router->insert("/api/v1/visit_analysis", [this](HttpSession &session, const Request &request,
|
||||
const boost::urls::matches &matches) {
|
||||
m_router->insert("/api/v1/visit_analysis", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||
using namespace boost::beast;
|
||||
auto rootJson = boost::json::parse(request.body());
|
||||
auto &root = rootJson.as_object();
|
||||
@ -166,8 +180,7 @@ Application::Application(const std::string &path)
|
||||
session.reply(std::move(s));
|
||||
});
|
||||
|
||||
m_router->insert("/api/v1/most_viewed_urls", [this](HttpSession &session, const Request &request,
|
||||
const boost::urls::matches &matches) {
|
||||
m_router->insert("/api/v1/most_viewed_urls", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||
using namespace boost::beast;
|
||||
int size = 5;
|
||||
std::error_code error;
|
||||
@ -200,8 +213,7 @@ Application::Application(const std::string &path)
|
||||
session.reply(std::move(s));
|
||||
});
|
||||
|
||||
m_router->insert("/api/v1/latest_viewed_urls", [this](HttpSession &session, const Request &request,
|
||||
const boost::urls::matches &matches) {
|
||||
m_router->insert("/api/v1/latest_viewed_urls", [this](HttpSession &session, const Request &request, const boost::urls::matches &matches) {
|
||||
using namespace boost::beast;
|
||||
int size = 5;
|
||||
std::error_code error;
|
||||
@ -290,21 +302,21 @@ void Application::alarmTask() {
|
||||
LOG(error) << error.message();
|
||||
return;
|
||||
}
|
||||
auto database = Amass::Singleton<Database>::instance();
|
||||
auto tasks = database->tasks();
|
||||
auto session = Amass::Singleton<Database>::instance()->session();
|
||||
Tasks tasks = session->find<Task>();
|
||||
bool founded = false;
|
||||
std::string content;
|
||||
for (auto &task : tasks) {
|
||||
if (founded) break;
|
||||
for (auto &child : task.children) {
|
||||
if (!child.finished) {
|
||||
content = child.content;
|
||||
for (auto child : task->children) {
|
||||
if (!child->finished) {
|
||||
content = child->content;
|
||||
founded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!founded && !task.finished) {
|
||||
content = task.content;
|
||||
if (!founded && !task->finished) {
|
||||
content = task->content;
|
||||
founded = true;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "Application.h"
|
||||
#include "BoostLog.h"
|
||||
#include "Database.h"
|
||||
#include "Database/Database.h"
|
||||
#include "IoContext.h"
|
||||
#include "Listener.h"
|
||||
#include "Live2dBackend.h"
|
||||
@ -11,6 +11,7 @@
|
||||
#include "WeChatContext/CorporationContext.h"
|
||||
#include "WeChatContext/WeChatContext.h"
|
||||
#include "WebApplication.h"
|
||||
#include <Wt/Dbo/SqlConnectionPool.h>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "Database.h"
|
||||
#include "Database/Database.h"
|
||||
#include "BoostLog.h"
|
||||
#include "Database/Session.h"
|
||||
#include <Wt/Dbo/SqlConnectionPool.h>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <filesystem>
|
||||
|
||||
@ -11,19 +13,66 @@ BOOST_AUTO_TEST_CASE(DatabaseTest) {
|
||||
std::filesystem::remove(path);
|
||||
}
|
||||
Database database;
|
||||
BOOST_TEST(database.open(path));
|
||||
database.open(path);
|
||||
// BOOST_TEST(database.open(path));
|
||||
|
||||
database.addTask(1234, "Hello");
|
||||
auto session = database.session();
|
||||
|
||||
database.addTask(1234, "这是一个测试", "", true);
|
||||
Wt::Dbo ::Transaction transaction(*session);
|
||||
|
||||
database.addHomeBoxItem("手机", "抽屉", 1499);
|
||||
auto items = database.homeBoxItems();
|
||||
BOOST_CHECK_EQUAL(items.size(), 1);
|
||||
auto task = std::make_unique<Task>();
|
||||
task->comment = "my_comment";
|
||||
task->content = "my_content";
|
||||
|
||||
auto p = session->add(std::move(task));
|
||||
|
||||
{
|
||||
task = std::make_unique<Task>();
|
||||
task->comment = "my_comment1";
|
||||
task->content = "my_content1";
|
||||
auto c = session->add(std::move(task));
|
||||
p.modify()->children.insert(c);
|
||||
}
|
||||
|
||||
{
|
||||
task = std::make_unique<Task>();
|
||||
task->comment = "my_comment2";
|
||||
task->content = "my_content2";
|
||||
auto c = session->add(std::move(task));
|
||||
p.modify()->children.insert(c);
|
||||
|
||||
{
|
||||
task = std::make_unique<Task>();
|
||||
task->comment = "my_comment3";
|
||||
task->content = "my_content3";
|
||||
auto d = session->add(std::move(task));
|
||||
c.modify()->children.insert(d);
|
||||
}
|
||||
|
||||
{
|
||||
task = std::make_unique<Task>();
|
||||
task->comment = "my_comment4";
|
||||
task->content = "my_content4";
|
||||
auto d = session->add(std::move(task));
|
||||
c.modify()->children.insert(d);
|
||||
}
|
||||
}
|
||||
|
||||
Wt::Dbo::ptr<Task> tt = session->find<Task>("where id = 3");
|
||||
LOG(info) << tt->parent->content;
|
||||
LOG(info) << tt->children.size();
|
||||
|
||||
{
|
||||
auto item = std::make_unique<HomeBox::Item>();
|
||||
item->cost = 1499;
|
||||
item->location = "抽屉";
|
||||
item->name = "手机";
|
||||
|
||||
auto d = session->add(std::move(item));
|
||||
}
|
||||
|
||||
auto now = std::chrono::system_clock::now();
|
||||
std::time_t now_time = std::chrono::system_clock::to_time_t(now);
|
||||
database.setTaskFinished(1, true, now_time);
|
||||
|
||||
database.updateVisitCount("/note", "uuid_123", "chrome", now_time);
|
||||
database.updateVisitCount("/note/1", "uuid_1232", "chrome", now_time);
|
||||
|
@ -3,11 +3,9 @@ find_package(Wt REQUIRED Wt)
|
||||
add_library(WebApplication
|
||||
WebApplication.h WebApplication.cpp
|
||||
LoginWidget.h LoginWidget.cpp
|
||||
User.h User.cpp
|
||||
Hello.h Hello.cpp
|
||||
Restful.h Restful.cpp
|
||||
Dialog.h Dialog.cpp
|
||||
Session.h Session.cpp
|
||||
)
|
||||
|
||||
target_include_directories(WebApplication
|
||||
@ -16,8 +14,6 @@ target_include_directories(WebApplication
|
||||
|
||||
target_link_libraries(WebApplication
|
||||
PUBLIC Universal
|
||||
PRIVATE Wt::Wt
|
||||
PRIVATE Wt::Dbo
|
||||
PRIVATE Wt::HTTP
|
||||
PRIVATE Wt::DboSqlite3
|
||||
PRIVATE Database
|
||||
)
|
@ -1,8 +1,9 @@
|
||||
#include "Hello.h"
|
||||
#include "BoostLog.h"
|
||||
#include "Database/Database.h"
|
||||
#include "Database/Session.h"
|
||||
#include "Dialog.h"
|
||||
#include "LoginWidget.h"
|
||||
#include "Session.h"
|
||||
#include "WebApplication.h"
|
||||
#include <Wt/Auth/Identity.h>
|
||||
#include <Wt/WBootstrap2Theme.h>
|
||||
@ -12,14 +13,13 @@
|
||||
#include <Wt/WPushButton.h>
|
||||
#include <Wt/WText.h>
|
||||
|
||||
Hello::Hello(const Wt::WEnvironment &env, Wt::Dbo::SqlConnectionPool &connectionPool, bool embedded)
|
||||
: Wt::WApplication(env) {
|
||||
Hello::Hello(const Wt::WEnvironment &env, bool embedded) : Wt::WApplication(env) {
|
||||
messageResourceBundle().use(appRoot() + "wt");
|
||||
messageResourceBundle().use(appRoot() + "auth_strings");
|
||||
messageResourceBundle().use(appRoot() + "auth_css_theme");
|
||||
useStyleSheet("/resources/app.css");
|
||||
LOG(info) << "app root: " << appRoot();
|
||||
m_session = std::make_unique<Session>(connectionPool);
|
||||
m_session = Amass::Singleton<Database>::instance()->session();
|
||||
m_session->login().changed().connect(this, &Hello::authEvent);
|
||||
setTitle("Hello world");
|
||||
if (!embedded) {
|
||||
@ -35,7 +35,6 @@ Hello::Hello(const Wt::WEnvironment &env, Wt::Dbo::SqlConnectionPool &connection
|
||||
} else {
|
||||
LOG(error) << "Missing: parameter: 'div'";
|
||||
}
|
||||
internalPathChanged().connect(this, &Hello::handlePathChange);
|
||||
auto externalPath = env.getParameter("path");
|
||||
if (externalPath != nullptr) {
|
||||
m_externalPath = *externalPath;
|
||||
@ -55,6 +54,7 @@ Hello::Hello(const Wt::WEnvironment &env, Wt::Dbo::SqlConnectionPool &connection
|
||||
root()->addWidget(std::make_unique<Wt::WText>("<p><emph>Note: you can also run this application "
|
||||
"from within <a href=\"hello.html\">a web page</a>.</emph></p>"));
|
||||
}
|
||||
LOG(info) << "internal path: " << internalPath();
|
||||
|
||||
m_root->addWidget(std::make_unique<Wt::WText>("Your name, please ? "));
|
||||
m_nameEdit = m_root->addWidget(std::make_unique<Wt::WLineEdit>());
|
||||
@ -73,10 +73,8 @@ Hello::Hello(const Wt::WEnvironment &env, Wt::Dbo::SqlConnectionPool &connection
|
||||
auto app = Amass::Singleton<WebApplication>::instance();
|
||||
|
||||
m_root->addWidget(std::make_unique<Dialog>());
|
||||
|
||||
if (!m_externalPath.empty()) {
|
||||
handlePathChange(m_externalPath);
|
||||
}
|
||||
internalPathChanged().connect(this, &Hello::handlePathChange);
|
||||
handlePathChange(m_externalPath.empty() ? internalPath() : m_externalPath);
|
||||
}
|
||||
|
||||
Hello::~Hello() {
|
||||
|
@ -7,7 +7,7 @@ class Session;
|
||||
|
||||
class Hello : public Wt::WApplication {
|
||||
public:
|
||||
Hello(const Wt::WEnvironment &env, Wt::Dbo::SqlConnectionPool &connectionPool, bool embedded);
|
||||
Hello(const Wt::WEnvironment &env, bool embedded);
|
||||
~Hello();
|
||||
|
||||
protected:
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "Restful.h"
|
||||
#include "Session.h"
|
||||
#include "Database/Database.h"
|
||||
#include "Database/Session.h"
|
||||
#include <Wt/Dbo/Impl.h>
|
||||
#include <Wt/Dbo/Json.h>
|
||||
#include <Wt/Dbo/backend/Sqlite3.h>
|
||||
@ -10,7 +11,7 @@ DBO_INSTANTIATE_TEMPLATES(MyMessage)
|
||||
DbStruct *m_dbStruct;
|
||||
|
||||
void AuthenticationResource::handleRequest(const Wt::Http::Request &request, Wt::Http::Response &response) {
|
||||
Session session(m_connectionPool);
|
||||
auto session = Amass::Singleton<Database>::instance()->session();
|
||||
response.setMimeType("application/json");
|
||||
response.addHeader("Server", "Wt");
|
||||
|
||||
@ -48,8 +49,7 @@ int DbStruct::rand() {
|
||||
return distribution(rng);
|
||||
}
|
||||
|
||||
AuthenticationResource::AuthenticationResource(Wt::Dbo::SqlConnectionPool &connectionPool)
|
||||
: m_connectionPool(connectionPool) {
|
||||
AuthenticationResource::AuthenticationResource() {
|
||||
}
|
||||
|
||||
DbStruct::DbStruct(const std::string &db) : rng(clock()), distribution(1, 10000) {
|
||||
|
@ -46,11 +46,8 @@ struct DbStruct {
|
||||
|
||||
class AuthenticationResource : public Wt::WResource {
|
||||
public:
|
||||
AuthenticationResource(Wt::Dbo::SqlConnectionPool &connectionPool);
|
||||
AuthenticationResource();
|
||||
void handleRequest(const Wt::Http::Request &request, Wt::Http::Response &response) final;
|
||||
|
||||
private:
|
||||
Wt::Dbo::SqlConnectionPool &m_connectionPool;
|
||||
};
|
||||
|
||||
class PlaintextResource : public Wt::WResource {
|
||||
|
@ -1,5 +0,0 @@
|
||||
#include "User.h"
|
||||
#include <Wt/Dbo/Impl.h>
|
||||
#include <Wt/Auth/Dbo/AuthInfo.h>
|
||||
|
||||
DBO_INSTANTIATE_TEMPLATES(User)
|
@ -1,8 +1,8 @@
|
||||
#include "WebApplication.h"
|
||||
#include "BoostLog.h"
|
||||
#include "Database/Session.h"
|
||||
#include "Hello.h"
|
||||
#include "Restful.h"
|
||||
#include "Session.h"
|
||||
#include <Wt/Auth/AuthService.h>
|
||||
#include <Wt/Auth/HashFunction.h>
|
||||
#include <Wt/Auth/PasswordService.h>
|
||||
@ -23,13 +23,12 @@ WebApplication::WebApplication(uint16_t port, const std::string &documentRoot) {
|
||||
initializeAuthenticationService();
|
||||
|
||||
m_server = std::make_unique<Wt::WServer>(std::format("{}/resources", documentRoot), args);
|
||||
m_sqlConnectionPool = createConnectionPool(std::format("{}/database.sqlite", documentRoot));
|
||||
|
||||
m_server->addEntryPoint(Wt::EntryPointType::Application,
|
||||
std::bind(&WebApplication::createApplication, this, std::placeholders::_1, false));
|
||||
m_server->addEntryPoint(Wt::EntryPointType::WidgetSet,
|
||||
std::bind(&WebApplication::createApplication, this, std::placeholders::_1, true), "/wt/app.js");
|
||||
m_server->addResource(std::make_shared<AuthenticationResource>(*m_sqlConnectionPool), "/auth");
|
||||
m_server->addResource(std::make_shared<AuthenticationResource>(), "/auth");
|
||||
m_server->addResource(std::make_shared<PlaintextResource>(), "/plaintext");
|
||||
m_server->addResource(std::make_shared<DbResource>(std::format("{}/database.sqlite", documentRoot)), "/db");
|
||||
|
||||
@ -39,15 +38,8 @@ WebApplication::WebApplication(uint16_t port, const std::string &documentRoot) {
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Wt::Dbo::SqlConnectionPool> WebApplication::createConnectionPool(const std::string &sqlite3) {
|
||||
auto connection = std::make_unique<Wt::Dbo::backend::Sqlite3>(sqlite3);
|
||||
connection->setProperty("show-queries", "true");
|
||||
connection->setDateTimeStorage(Wt::Dbo::SqlDateTimeType::DateTime, Wt::Dbo::backend::DateTimeStorage::PseudoISO8601AsText);
|
||||
return std::make_unique<Wt::Dbo::FixedSqlConnectionPool>(std::move(connection), 10);
|
||||
}
|
||||
|
||||
std::unique_ptr<Wt::WApplication> WebApplication::createApplication(const Wt::WEnvironment &env, bool embedded) {
|
||||
return std::make_unique<Hello>(env, *m_sqlConnectionPool, embedded);
|
||||
return std::make_unique<Hello>(env, embedded);
|
||||
}
|
||||
|
||||
WebApplication::~WebApplication() {
|
||||
|
@ -9,10 +9,6 @@ class WServer;
|
||||
class WApplication;
|
||||
class WEnvironment;
|
||||
|
||||
namespace Dbo {
|
||||
class SqlConnectionPool;
|
||||
}
|
||||
|
||||
namespace Auth {
|
||||
class AuthService;
|
||||
class PasswordService;
|
||||
@ -32,12 +28,10 @@ public:
|
||||
|
||||
protected:
|
||||
WebApplication(uint16_t port, const std::string &documentRoot);
|
||||
static std::unique_ptr<Wt::Dbo::SqlConnectionPool> createConnectionPool(const std::string &sqlite3);
|
||||
std::unique_ptr<Wt::WApplication> createApplication(const Wt::WEnvironment &env, bool embedded);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Wt::WServer> m_server;
|
||||
std::unique_ptr<Wt::Dbo::SqlConnectionPool> m_sqlConnectionPool;
|
||||
|
||||
std::unique_ptr<Wt::Auth::AuthService> m_authService;
|
||||
std::unique_ptr<Wt::Auth::PasswordService> m_passwordService;
|
||||
|
Loading…
Reference in New Issue
Block a user