2023-06-15 07:24:23 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
// Standard
|
|
|
|
"database/sql"
|
2023-06-16 07:11:27 +02:00
|
|
|
"errors"
|
2023-06-17 09:11:14 +02:00
|
|
|
"fmt"
|
|
|
|
"net/http"
|
2023-06-15 07:24:23 +02:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Session struct {
|
|
|
|
UUID string
|
|
|
|
UserID int
|
|
|
|
Created time.Time
|
|
|
|
}
|
|
|
|
|
2023-06-17 09:11:14 +02:00
|
|
|
func CreateSession() (session Session, err error) {// {{{
|
2023-06-15 07:24:23 +02:00
|
|
|
var rows *sql.Rows
|
|
|
|
if rows, err = db.Query(`
|
|
|
|
INSERT INTO public.session(uuid)
|
|
|
|
VALUES(gen_random_uuid())
|
|
|
|
RETURNING uuid, created`,
|
|
|
|
); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
if rows.Next() {
|
|
|
|
rows.Scan(&session.UUID, &session.Created)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
2023-06-17 09:11:14 +02:00
|
|
|
}// }}}
|
|
|
|
|
|
|
|
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")
|
|
|
|
}// }}}
|
|
|
|
func ValidateSession(r *http.Request, notFoundIsError bool) (session Session, found bool, err error) {// {{{
|
|
|
|
var uuid string
|
|
|
|
if uuid, err = sessionUUID(r); err != nil {
|
|
|
|
return
|
|
|
|
}
|
2023-06-16 07:11:27 +02:00
|
|
|
|
2023-06-17 09:11:14 +02:00
|
|
|
session.UUID = uuid
|
|
|
|
if found, err = session.Retrieve(); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if notFoundIsError && !found {
|
|
|
|
err = errors.New("Invalid session")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}// }}}
|
|
|
|
|
|
|
|
func (session *Session) Retrieve() (found bool, err error) {// {{{
|
2023-06-16 07:11:27 +02:00
|
|
|
var rows *sql.Rows
|
|
|
|
if rows, err = db.Query(`
|
|
|
|
SELECT
|
|
|
|
uuid, user_id, created
|
|
|
|
FROM public.session
|
|
|
|
WHERE
|
2023-06-17 09:11:14 +02:00
|
|
|
uuid = $1 AND
|
|
|
|
created + $2::interval >= NOW()
|
2023-06-16 07:11:27 +02:00
|
|
|
`,
|
|
|
|
session.UUID,
|
2023-06-17 09:11:14 +02:00
|
|
|
fmt.Sprintf("%d days", config.Session.DaysValid),
|
2023-06-16 07:11:27 +02:00
|
|
|
); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
|
2023-06-17 09:11:14 +02:00
|
|
|
found = false
|
2023-06-16 07:11:27 +02:00
|
|
|
if rows.Next() {
|
2023-06-17 09:11:14 +02:00
|
|
|
found = true
|
2023-06-16 07:11:27 +02:00
|
|
|
rows.Scan(&session.UUID, &session.UserID, &session.Created)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
2023-06-17 09:11:14 +02:00
|
|
|
}// }}}
|
|
|
|
func (session *Session) Authenticate(username, password string) (authenticated bool, err error) {// {{{
|
2023-06-16 07:11:27 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
2023-06-17 09:11:14 +02:00
|
|
|
}// }}}
|
|
|
|
|
|
|
|
|
|
|
|
// vim: foldmethod=marker
|