Compare commits

...

5 Commits

9 changed files with 85 additions and 30 deletions

2
.gitignore vendored
View File

@ -3,6 +3,8 @@
*.out
*.gch
*.user
*.swp
*.kate-swp
qswiki
wikiqs*
data/*

View File

@ -10,6 +10,7 @@ class SessionDao
virtual void save(const Session &session) = 0;
virtual std::optional<Session> find(std::string token) = 0;
virtual void deleteSession(std::string token) = 0;
virtual std::vector<Session> fetch() = 0;
virtual ~SessionDao()
{
}

63
database/sessiondaosqlite.cpp Normal file → Executable file
View File

@ -50,6 +50,29 @@ void SessionDaoSqlite::deleteSession(std::string token)
}
}
void SessionDaoSqlite::fillSession(int userid, Session &sess)
{
if(userid > -1)
{
UserDaoSqlite userDao{this->db};
auto u = userDao.find(userid);
if(u)
{
sess.user = *u;
}
else
{
Logger::error() << "Session for non existent user";
throw DatabaseQueryException("Session for non existent user");
}
}
else
{
sess.user = User::Anonymous();
}
sess.loggedIn = userid != -1;
}
std::optional<Session> SessionDaoSqlite::find(std::string token)
{
Session result;
@ -62,25 +85,7 @@ std::optional<Session> SessionDaoSqlite::find(std::string token)
int userid;
q >> std::tie(userid, result.token, result.csrf_token, result.creation_time);
if(userid > -1)
{
UserDaoSqlite userDao{this->db};
auto u = userDao.find(userid);
if(u)
{
result.user = *u;
}
else
{
Logger::error() << "Session for non existent user";
throw DatabaseQueryException("Session for non existent user");
}
}
else
{
result.user = User::Anonymous();
}
result.loggedIn = userid != -1;
fillSession(userid, result);
}
catch(const sqlite::exceptions::no_rows &e)
{
@ -92,3 +97,23 @@ std::optional<Session> SessionDaoSqlite::find(std::string token)
}
return result;
}
std::vector<Session> SessionDaoSqlite::fetch()
{
std::vector<Session> result;
*db << "SELECT userid, token, csrf_token, strftime('%s', creationtime) FROM session" >>
[this, &result](int userid, std::string token, std::string csrf_token, time_t creationtime)
{
Session tmp;
tmp.csrf_token = csrf_token;
tmp.token = token;
tmp.creation_time = creationtime;
fillSession(userid, tmp);
result.push_back(tmp);
};
return result;
}

View File

@ -6,11 +6,15 @@
class SessionDaoSqlite : public SessionDao, protected SqliteDao
{
private:
void fillSession(int userid, Session &sess);
public:
SessionDaoSqlite();
void save(const Session &session) override;
std::optional<Session> find(std::string token) override;
void deleteSession(std::string token) override;
std::vector<Session> fetch() override;
using SqliteDao::SqliteDao;
};

View File

@ -31,8 +31,8 @@ SOFTWARE.
#include "handlers/handlerfactory.h"
#include "database/databasefactory.h"
#include "config.h"
#include "template.h"
#include "session.h"
#include "template.h"
#include "logger.h"
#include "urlprovider.h"
#include "requestworker.h"
@ -74,6 +74,33 @@ std::unique_ptr<ICache> createCache(const ConfigVariableResolver &resolver)
return std::make_unique<FsCache>(path);
}
std::thread background_worker;
void start_background_worker(Database &database, Config &config)
{
background_worker = std::thread(
[&database, &config]()
{
while(true)
{
Logger::log() << "Executing background worker";
auto sessionDao = database.createSessionDao();
auto sessionList = sessionDao->fetch();
time_t now = time(NULL);
for(Session &sess : sessionList)
{
if(now - sess.creation_time > config.session_max_lifetime)
{
sessionDao->deleteSession(sess.token);
}
}
std::this_thread::sleep_for(std::chrono::hours(1));
}
});
}
int main(int argc, char **argv)
{
@ -136,6 +163,7 @@ int main(int argc, char **argv)
Logger::setStream(&logstream);
auto database = createDatabase(config);
std::string socketPath = config.configVarResolver.getConfig("socketpath");
CLIHandler cliHandler(config, *database);
@ -158,6 +186,8 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
start_background_worker(*database.get(), config);
CLIServer cliServer{cliHandler};
if(!cliServer.detachServer(socketPath))
{

View File

@ -42,6 +42,7 @@ std::string RevisionRenderer::renderContent(std::string content)
{
dynamicVarsMap["pagetitle"] = parser.extractCommand("pagetitle", content);
dynamicVarsMap["createdon"] = utils::toISODate(time(NULL));
dynamicVarsMap["modifydatetime"] = utils::toISODateTime(time(NULL));
std::string resolvedContent = parser.parseDynamics(content, std::bind(&RevisionRenderer::dynamicCallback, this, std::placeholders::_1, std::placeholders::_2));
@ -60,6 +61,7 @@ std::string RevisionRenderer::renderContent(const Revision &r, std::string_view
dynamicVarsMap["createdon"] = utils::toISODate(firstRevision.value().timestamp);
dynamicVarsMap["pagetitle"] = customTitle;
dynamicVarsMap["modifydatetime"] = utils::toISODateTime(r.timestamp);
std::string resolvedContent = parser.parseDynamics(r.content, std::bind(&RevisionRenderer::dynamicCallback, this, std::placeholders::_1, std::placeholders::_2));

View File

@ -4,8 +4,5 @@
<li style="font-size: 10pt">Powered by qswiki</li>
</ul>
</footer>
<script>
{qswiki:include:js_session_refresh}
</script>
</body>
</html>
</html>

View File

@ -1,5 +0,0 @@
function refreshSession()
{
fetch(new Request("{qswiki:config:refreshsessionurl}"));
}
setInterval(refreshSession, 60*2*1000);

View File

@ -7,7 +7,6 @@
</footer>
<script src="{qswiki:config:highlightjspath}"></script>
<script>
{qswiki:include:js_session_refresh}
hljs.highlightAll();
</script>
</body>