aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Armstrong <jeff@approximatrix.com>2022-04-28 12:51:26 -0400
committerJeffrey Armstrong <jeff@approximatrix.com>2022-04-28 12:51:26 -0400
commitb558fd94527e6a3f359c3ca766eeabaf0c7a8a57 (patch)
treedc8c84749e309f5fb8ff014839c76c8fc44095e5
parente7aaa0256420e8d30dee54e603af60d54434c38e (diff)
downloadlevitating-b558fd94527e6a3f359c3ca766eeabaf0c7a8a57.tar.gz
levitating-b558fd94527e6a3f359c3ca766eeabaf0c7a8a57.zip
Sessions are now created and stored at login.
-rw-r--r--captain/db.f90122
-rw-r--r--captain/sql/create.sql7
-rw-r--r--captain/web.f9068
3 files changed, 177 insertions, 20 deletions
diff --git a/captain/db.f90 b/captain/db.f90
index 7a8052d..7500b8a 100644
--- a/captain/db.f90
+++ b/captain/db.f90
@@ -1502,6 +1502,27 @@ contains
end function validate_user_db
+ function get_user_id_db(username)
+ implicit none
+
+ character(len=*), intent(in)::username
+ integer::get_user_id_db
+
+ type(sqlite3_stmt)::stmt
+
+ get_user_id_db = -1
+
+ if(stmt%prepare(db, "SELECT id FROM users WHERE username=? LIMIT 1") == SQLITE_OK) then
+ if(stmt%bind_text(1, username) == SQLITE_OK) then
+ if(stmt%step() == SQLITE_ROW) then
+ get_user_id_db = stmt%column_int(0)
+ end if
+ end if
+ call stmt%finalize()
+ end if
+
+ end function get_user_id_db
+
function get_user_auth_db(username)
implicit none
@@ -1564,5 +1585,106 @@ contains
end if
end subroutine get_session_username_db
+
+ function create_user_session_db(username) result(session)
+ use m_uuid
+ implicit none
+
+ character(len=*), intent(in)::username
+ character(len=UUID_LENGTH)::session, internal_session
+
+ integer::userid, res
+ type(sqlite3_stmt)::stmt
+
+ internal_session = generate_uuid4()
+ userid = get_user_id_db(username)
+ session = ' '
+
+ if(stmt%prepare(db, "INSERT INTO sessions(user, session, accessed) VALUES(?, ?, datetime('now'))") == SQLITE_OK) then
+ if(stmt%bind_int(1, userid) == SQLITE_OK .AND. &
+ stmt%bind_text(2, internal_session) == SQLITE_OK) then
+
+ if(any(stmt%step() == (/SQLITE_OK, SQLITE_DONE, SQLITE_ROW/))) then
+ session = internal_session
+ end if
+
+ end if
+
+ call stmt%finalize()
+ end if
+
+ end function create_user_session_db
+
+ subroutine destroy_session_db(session)
+ implicit none
+
+ character(len=*), intent(in)::session
+ type(sqlite3_stmt)::stmt
+
+ if(stmt%prepare(db, "DELETE FROM sessions WHERE session=?") == SQLITE_OK) then
+ if(stmt%bind_text(1, session) == SQLITE_OK) then
+ call stmt%step_now()
+ end if
+ call stmt%finalize()
+ end if
+
+ end subroutine destroy_session_db
+
+ subroutine destroy_old_sessions_db()
+ implicit none
+
+ type(sqlite3_stmt)::stmt
+
+ if(stmt%prepare(db, "DELETE FROM sessions WHERE accessed < datetime('now', '-30 minutes')") == SQLITE_OK) then
+ call stmt%step_now()
+ call stmt%finalize()
+ end if
+
+ end subroutine destroy_old_sessions_db
+
+ subroutine update_session_db(session)
+ implicit none
+
+ character(len=*), intent(in)::session
+ type(sqlite3_stmt)::stmt
+
+ if(stmt%prepare(db, "UPDATE sessions SET accessed=datetime('now') WHERE session=?") == SQLITE_OK) then
+ if(stmt%bind_text(1, session) == SQLITE_OK) then
+ call stmt%step_now()
+ end if
+ call stmt%finalize()
+ end if
+
+ end subroutine update_session_db
+
+ function session_expired_db(session)
+ implicit none
+
+ character(len=*), intent(in)::session
+ logical::session_expired_db
+
+ type(sqlite3_stmt)::stmt
+
+ session_expired_db = .true.
+
+ if(stmt%prepare(db, "SELECT COUNT(*) FROM sessions WHERE accessed < datetime('now', '-30 minutes') AND session=?") &
+ == SQLITE_OK) &
+ then
+ if(stmt%bind_text(1, session) == SQLITE_OK) then
+
+ if(stmt%step() == SQLITE_ROW) then
+ session_expired_db = .not. (stmt%column_int(0) > 0)
+ end if
+
+ end if
+
+ call stmt%finalize()
+ end if
+
+ if(session_expired_db) then
+ call destroy_session_db(session)
+ end if
+
+ end function session_expired_db
end module captain_db
diff --git a/captain/sql/create.sql b/captain/sql/create.sql
index 7517e07..40cbc0c 100644
--- a/captain/sql/create.sql
+++ b/captain/sql/create.sql
@@ -15,10 +15,13 @@ CREATE TABLE group_instructions(group_id INTEGER, instruction INTEGER, player IN
CREATE TABLE checkin(player INTEGER PRIMARY KEY, year INTEGER, month INTEGER, day INTEGER, hour INTEGER, minute INTEGER, second INTEGER, os TEXT DEFAULT NULL, FOREIGN KEY(player) REFERENCES players(id) ON DELETE CASCADE);
-CREATE TABLE schedule(instruction INTEGER NOT NULL, player INTEGER NOT NULL, day INTEGER DEFAULT 0, hour INTEGER DEFAULT 0, FOREIGN KEY(instruction) REFERENCES instructions(id) ON DELETE CASCADE, FOREIGN KEY(player) REFERENCES players(id) ON DELETE CASCADE );
+CREATE TABLE schedule(id INTEGER PRIMARY KEY, instruction INTEGER NOT NULL, player INTEGER NOT NULL, day INTEGER DEFAULT 0, hour INTEGER DEFAULT 0, FOREIGN KEY(instruction) REFERENCES instructions(id) ON DELETE CASCADE, FOREIGN KEY(player) REFERENCES players(id) ON DELETE CASCADE );
+
+CREATE TABLE scheduled_jobs(schedule INTEGER UNIQUE NOT NULL, job INTEGER UNIQUE NOT NULL, FOREIGN KEY(schedule) REFERENCES schedules(id) ON DELETE CASCADE, FOREIGN KEY(job) REFERENCES jobs(id));
CREATE TABLE users(id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, email TEXT NOT NULL, password TEXT NOT NULL, level INTEGER DEFAULT 1);
-CREATE TABLE sessions(user INTEGER, session TEXT NOT NULL, expiration TEXT NOT NULL, FOREIGN KEY(user) REFERENCES users(id) ON DELETE CASCADE);
+CREATE TABLE sessions(user INTEGER, session TEXT NOT NULL, accessed TEXT NOT NULL, FOREIGN KEY(user) REFERENCES users(id) ON DELETE CASCADE);
CREATE VIEW session_auth AS SELECT sessions.session, users.username, users.level FROM sessions INNER JOIN users ON sessions.user = users.id;
+
diff --git a/captain/web.f90 b/captain/web.f90
index 09d687b..c3841c0 100644
--- a/captain/web.f90
+++ b/captain/web.f90
@@ -52,8 +52,45 @@ contains
end function method
+ subroutine handle_basic_template_components(req, page)
+ use server_response
+ use page_template
+ use captain_db
+ use config
+ implicit none
+
+ type(request), intent(in)::req
+ type(template), intent(inout)::page
+ character(len=128)::username
+
+ call page%assign('project', project)
+ call page%assign('base_url', req%server)
+
+ if(associated(req%token)) then
+ if(get_session_auth_db(req%token) > 0) then
+
+ call page%assign('user_link_page', "profile")
+ call get_session_username_db(req%token, username)
+ call page%assign('user_link_text', trim(username))
+
+ else
+
+ call page%assign('user_link_page', "login")
+ call page%assign('user_link_text', "Login")
+
+ end if
+ else
+
+ call page%assign('user_link_page', "login")
+ call page%assign('user_link_text', "Login")
+
+ end if
+
+ end subroutine handle_basic_template_components
+
subroutine build_request_object(req)
use server_response, only:request
+ implicit none
type(request), intent(out)::req
character(len=:), allocatable::url, script_name
@@ -1026,22 +1063,7 @@ contains
end if
- call page%assign('project', project)
- call page%assign('base_url', req%server)
-
- if(associated(req%token)) then
- if(get_session_auth_db(req%token) > 0) then
- call page%assign('user_link_page', "profile")
- call get_session_username_db(req%token, username)
- call page%assign('user_link_text', trim(username))
- else
- call page%assign('user_link_page', "login")
- call page%assign('user_link_text', "Login")
- end if
- else
- call page%assign('user_link_page', "login")
- call page%assign('user_link_text', "Login")
- end if
+ call handle_basic_template_components(req, page)
call write_log("Rendering page for "//req%location)
call page%render()
@@ -1054,7 +1076,8 @@ contains
end function request_templated
function handle_post(req) result(resp)
- use captain_db, only: add_player_db, add_group_db, update_player_token_db
+ use captain_db, only: add_player_db, add_group_db, update_player_token_db, create_user_session_db, &
+ validate_user_db
use page_template
use config, only: template_filepath
use logging
@@ -1111,11 +1134,20 @@ contains
call page%assign('destination', 'groups.html')
end if
+
+ else if(trim(category) == "login.html") then
+
+ ! Determine if logged in
+ if(validate_user_db(posted%get_value("username"), posted%get_value("password"))) then
+ call page%assign('destination', "home.html?token="//create_user_session_db(posted%get_value("username")))
+ else
+ call page%assign('destination', "login.html?failed=1")
+ end if
end if
! Handle the template
- call page%assign('base_url', req%server)
+ call handle_basic_template_components(req, page)
call page%render()
call write_log("Finalizing response", LOG_INFO)