Session
This commit is contained in:
parent
b8a673fb0a
commit
a76c093d44
52
main.go
52
main.go
@ -51,6 +51,8 @@ func main() {// {{{
|
||||
static = http.FileServer(http.Dir("./static"))
|
||||
http.HandleFunc("/css_updated", cssUpdateHandler)
|
||||
http.HandleFunc("/session/create", sessionCreate)
|
||||
http.HandleFunc("/session/retrieve", sessionRetrieve)
|
||||
http.HandleFunc("/session/authenticate", sessionAuthenticate)
|
||||
http.HandleFunc("/ws", websocketHandler)
|
||||
http.HandleFunc("/", staticHandler)
|
||||
|
||||
@ -68,12 +70,62 @@ func sessionCreate(w http.ResponseWriter, r *http.Request) {// {{{
|
||||
session, err := NewSession()
|
||||
if err != nil {
|
||||
responseError(w, err)
|
||||
return
|
||||
}
|
||||
responseData(w, map[string]interface{}{
|
||||
"OK": true,
|
||||
"Session": session,
|
||||
})
|
||||
}// }}}
|
||||
func sessionRetrieve(w http.ResponseWriter, r *http.Request) {// {{{
|
||||
var err error
|
||||
var uuid string
|
||||
|
||||
if uuid, err = sessionUUID(r); err != nil {
|
||||
responseError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
session := Session{ UUID: uuid }
|
||||
if err = session.Retrieve(); err != nil {
|
||||
responseError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
responseData(w, map[string]interface{}{
|
||||
"OK": true,
|
||||
"Session": session,
|
||||
})
|
||||
}// }}}
|
||||
func sessionAuthenticate(w http.ResponseWriter, r *http.Request) {// {{{
|
||||
var err error
|
||||
var uuid string
|
||||
|
||||
if uuid, err = sessionUUID(r); err != nil {
|
||||
responseError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
session := Session{
|
||||
UUID: uuid,
|
||||
}
|
||||
|
||||
req := struct{ Username string; Password string }{}
|
||||
if err = request(r, &req); err != nil {
|
||||
responseError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = session.Authenticate(req.Username, req.Password); err != nil {
|
||||
responseError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
responseData(w, map[string]interface{}{
|
||||
"OK": true,
|
||||
"Session": session,
|
||||
})
|
||||
}// }}}
|
||||
func websocketHandler(w http.ResponseWriter, r *http.Request) {// {{{
|
||||
var err error
|
||||
|
||||
|
@ -3,6 +3,8 @@ package main
|
||||
import (
|
||||
// Standard
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@ -26,3 +28,18 @@ func responseData(w http.ResponseWriter, data interface{}) {
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
w.Write(resJSON)
|
||||
}
|
||||
|
||||
func request(r *http.Request, data interface{}) (err error) {
|
||||
body, _ := io.ReadAll(r.Body)
|
||||
defer r.Body.Close()
|
||||
err = json.Unmarshal(body, data)
|
||||
return
|
||||
}
|
||||
|
||||
func sessionUUID(r *http.Request) (string, error) {
|
||||
headers := r.Header["X-Session-Id"]
|
||||
if len(headers) > 0 {
|
||||
return headers[0], nil
|
||||
}
|
||||
return "", errors.New("Invalid session")
|
||||
}
|
||||
|
58
session.go
58
session.go
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
// Standard
|
||||
"database/sql"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -29,3 +30,60 @@ func NewSession() (session Session, err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (session *Session) Retrieve() (err error) {
|
||||
var rows *sql.Rows
|
||||
if rows, err = db.Query(`
|
||||
SELECT
|
||||
uuid, user_id, created
|
||||
FROM public.session
|
||||
WHERE
|
||||
uuid = $1
|
||||
`,
|
||||
session.UUID,
|
||||
); err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if rows.Next() {
|
||||
rows.Scan(&session.UUID, &session.UserID, &session.Created)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (session *Session) Authenticate(username, password string) (err error) {
|
||||
authenticated := false
|
||||
|
||||
var rows *sql.Rows
|
||||
if rows, err = db.Query(`
|
||||
SELECT id
|
||||
FROM public.user
|
||||
WHERE
|
||||
username=$1 AND
|
||||
password=$2
|
||||
`,
|
||||
username,
|
||||
password,
|
||||
); err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if rows.Next() {
|
||||
rows.Scan(&session.UserID)
|
||||
authenticated = session.UserID > 0
|
||||
}
|
||||
|
||||
if authenticated {
|
||||
_, err = db.Exec("UPDATE public.session SET user_id=$1 WHERE uuid=$2", session.UserID, session.UUID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
err = errors.New("Invalid authentication")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -16,8 +16,7 @@
|
||||
"preact/devtools": "/js/{{ .VERSION }}/lib/preact/devtools.mjs",
|
||||
"@preact/signals-core": "/js/{{ .VERSION }}/lib/signals/signals-core.mjs",
|
||||
"preact/signals": "/js/{{ .VERSION }}/lib/signals/signals.mjs",
|
||||
"htm": "/js/{{ .VERSION }}/lib/htm/htm.mjs"
|
||||
|
||||
"htm": "/js/{{ .VERSION }}/lib/htm/htm.mjs",
|
||||
"session": "/js/{{ .VERSION }}/session.mjs"
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import 'preact/devtools'
|
||||
//import { signal } from 'preact/signals'
|
||||
import { h, Component, render, createRef } from 'preact'
|
||||
import htm from 'htm'
|
||||
import Session from 'session'
|
||||
import { Session } from 'session'
|
||||
const html = htm.bind(h)
|
||||
|
||||
class App extends Component {
|
||||
@ -15,10 +15,16 @@ class App extends Component {
|
||||
this.wsConnect()
|
||||
this.wsLoop()
|
||||
|
||||
|
||||
this.session = new Session(this)
|
||||
this.session.initialize()
|
||||
}//}}}
|
||||
render() {//{{{
|
||||
if(this.sessionID === null) {
|
||||
if(!this.session.initialized) {
|
||||
return false;
|
||||
//return html`<div>Validating session</div>`
|
||||
}
|
||||
|
||||
if(!this.session.authenticated()) {
|
||||
return html`<${Login} />`
|
||||
}
|
||||
|
||||
@ -85,8 +91,9 @@ class App extends Component {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
|
||||
if(this.sessionID !== null)
|
||||
headers['X-SESSION-ID'] = this.sessionID
|
||||
console.log(this.session)
|
||||
if(this.session.UUID !== '')
|
||||
headers['X-Session-Id'] = this.session.UUID
|
||||
|
||||
fetch(url, {
|
||||
method: 'POST',
|
||||
@ -116,22 +123,6 @@ class App extends Component {
|
||||
break;
|
||||
}
|
||||
}//}}}
|
||||
login(username, password) {//{{{
|
||||
this.request('/session/create', {})
|
||||
.then(res=>{
|
||||
this.setSessionID(res.Session.UUID)
|
||||
})
|
||||
.catch(this.responseError)
|
||||
}//}}}
|
||||
|
||||
getSessionID() {
|
||||
return window.localStorage.getItem("sessionID")
|
||||
}
|
||||
setSessionID(uuid) {
|
||||
console.log('wut')
|
||||
this.sessionID = uuid
|
||||
window.localStorage.setItem('sessionID', uuid)
|
||||
}
|
||||
}
|
||||
|
||||
class Login extends Component {
|
||||
@ -152,7 +143,7 @@ class Login extends Component {
|
||||
login() {//{{{
|
||||
let username = document.getElementById('username').value
|
||||
let password = document.getElementById('password').value
|
||||
window._app.current.login(username, password)
|
||||
window._app.current.session.authenticate(username, password)
|
||||
}//}}}
|
||||
}
|
||||
|
||||
|
51
static/js/session.mjs
Normal file
51
static/js/session.mjs
Normal file
@ -0,0 +1,51 @@
|
||||
export class Session {
|
||||
constructor(app) {
|
||||
this.app = app
|
||||
this.UUID = ''
|
||||
this.initialized = false
|
||||
this.UserID = 0
|
||||
}
|
||||
|
||||
initialize() {//{{{
|
||||
// Retrieving the stored session UUID, if any.
|
||||
// If one found, validate with server.
|
||||
let uuid = window.localStorage.getItem("session.UUID")
|
||||
if(uuid === null) {
|
||||
this.create()
|
||||
} else {
|
||||
this.UUID = uuid
|
||||
this.app.request('/session/retrieve', {})
|
||||
.then(res=>{
|
||||
this.UserID = res.Session.UserID
|
||||
this.initialized = true
|
||||
this.app.forceUpdate()
|
||||
})
|
||||
.catch(this.app.responseError)
|
||||
}
|
||||
}//}}}
|
||||
create() {//{{{
|
||||
this.app.request('/session/create', {})
|
||||
.then(res=>{
|
||||
this.UUID = res.Session.UUID
|
||||
window.localStorage.setItem('session.UUID', this.UUID)
|
||||
this.app.forceUpdate()
|
||||
})
|
||||
.catch(this.responseError)
|
||||
}//}}}
|
||||
authenticate(username, password) {//{{{
|
||||
this.app.request('/session/authenticate', {
|
||||
username,
|
||||
password,
|
||||
})
|
||||
.then(res=>{
|
||||
this.UserID = res.Session.UserID
|
||||
this.app.forceUpdate()
|
||||
})
|
||||
.catch(this.app.responseError)
|
||||
}//}}}
|
||||
authenticated() {//{{{
|
||||
return this.UserID != 0
|
||||
}//}}}
|
||||
}
|
||||
|
||||
// vim: foldmethod=marker
|
@ -1,12 +0,0 @@
|
||||
export class Session {
|
||||
static createFromStorage() {
|
||||
let session = new Session()
|
||||
session.UUID
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.UUID = ''
|
||||
this.authenticated = false
|
||||
this.UserID = 0
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user