snuffler-web/inc/database.php

196 lines
5.4 KiB
PHP
Executable file

<?php
if(count(get_included_files()) ==1) {
http_response_code(403);
die("403: Forbidden");
}
class DataBase extends SQLite3 {
function __construct() {
$this->open('database.db');
$this->exec('PRAGMA foreign_keys=ON;');
$this->exec('PRAGMA full_column_names=ON;');
$this->exec('PRAGMA short_column_names=OFF;');
$sql = "
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY UNIQUE,
pass TEXT,
email TEXT UNIQUE,
handle TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
about TEXT
);
CREATE TABLE IF NOT EXISTS personas (
id INTEGER PRIMARY KEY UNIQUE,
userid INTEGER NOT NULL,
handle TEXT NOT NULL,
name TEXT NOT NULL,
about TEXT,
colour INTEGER,
FOREIGN KEY (userid) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE,
UNIQUE (userid, handle)
);
CREATE TABLE IF NOT EXISTS posts (
id INTEGER PRIMARY KEY UNIQUE,
time INTEGER NOT NULL,
userid INTEGER NOT NULL,
personaid INTEGER NOT NULL,
text TEXT NOT NULL,
FOREIGN KEY (userid) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (personaid) REFERENCES personas(id) ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS comments (
id INTEGER PRIMARY KEY UNIQUE,
time INTEGER NOT NULL,
userid INTEGER NOT NULL,
personaid INTEGER,
postid INTEGER NOT NULL,
text TEXT NOT NULL,
FOREIGN KEY (postid) REFERENCES posts(id),
FOREIGN KEY (userid) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (personaid) REFERENCES personas(id) ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS tokens (
id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
userid INTEGER NOT NULL,
token TEXT NOT NULL UNIQUE,
lastuse TEXT NOT NULL,
expires TEXT NOT NULL,
FOREIGN KEY (userid) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE
);
INSERT OR IGNORE INTO users (id, handle, name, about) VALUES ('0', 'SYSTEM', 'SYSTEM', 'SYSTEM');
";
$ret = $this->exec($sql);
}
function addUser($handle, $name, $about=NULL) {
$id = hexdec(uniqid());
$sql = "INSERT INTO users (id, handle, name, about) VALUES ('$id', '$handle', '$name', '$about')";
$ret = $this->exec($sql);
if(!$ret) {
die($this->lastErrorMsg());
}
}
function getUserByHandle($handle) {
$handle = $this->escapeString($handle);
$sql = "SELECT * FROM users AS user WHERE handle='$handle';";
$ret = $this->query($sql)->fetchArray(SQLITE3_ASSOC);
if(!$ret) {
return false;
}
return $ret;
}
function addPost($text, $userid=NULL, $personaid=NULL) {
$id = hexdec(uniqid());
$time = time();
$sql = $this->prepare("INSERT INTO posts (id, time, userid, personaid, text) values ('$id', '$time', '$userid', :personaid, '$text')");
$sql->bindParam(':personaid', $personaid, SQLITE3_INTEGER);
$ret = $sql->execute();
if(!$ret) {
die($this->lastErrorMsg());
}
}
function addPersona($userid, $handle, $name, $about=NULL, $colour=NULL) {
$id = hexdec(uniqid());
$sql = "INSERT INTO personas (id, userid, handle, name, colour) VALUES ('$id', '$userid', '$handle', '$about', '$colour');";
$ret = $this->exec($sql);
if(!$ret) {
die($this->lastErrorMsg());
}
}
function passwordSet($userid, $password=NULL) {
$hash = empty($password) ? NULL : password_hash($password, PASSWORD_DEFAULT);
$sql = "UPDATE USERS SET pass='$hash' WHERE id='$userid';";
$ret = $this->exec($sql);
if(!$ret) {
die($this->lastErrorMsg());
}
}
function passwordVerify($userid, $password) {
$sql = "SELECT pass FROM users WHERE id='$userid';";
$ret = $this->query($sql)->fetchArray(SQLITE3_NUM);
if(!$ret) {
return false;
}
$dbhash = $ret[0];
return password_verify($password, $dbhash);
}
function tokenGen() {
return random_bytes(32);
}
function tokenAdd($userid) {
$token = $this->tokenGen();
$hashed = hash('sha256', $token);
$time = time();
$expires = $time + 2592000; // 30 days
$sql = "INSERT INTO tokens (userid, token, lastuse, expires) VALUES ('$userid', '$hashed', '$time', '$expires');";
$ret = $this->exec($sql);
if(!$ret) {
die($this->lastErrorMsg());
}
return $token;
}
function tokenRefresh($tokenid) {
$time = time();
$expires = $time + 2592000; // 30 days
$sql = "UPDATE tokens SET lastuse='$time', expires='$expires' WHERE id='$tokenid';";
$ret = $this->exec($sql);
if(!$ret) {
die($this->lastErrorMsg());
}
}
function tokenRemove($token) {
$hashed = hash('sha256', $token);
$sql = "DELETE FROM tokens WHERE token='$hashed';";
$ret = $this->exec($sql);
if(!$ret) {
die($this->lastErrorMsg());
}
}
function getAuthedUserId($token=NULL) {
if (empty($token)) {
if (empty($_COOKIE['token'])) {
return false;
}
$token = base64_decode($_COOKIE['token']);
}
$hashed = hash('sha256', $token);
$sql = "SELECT id AS id, userid AS userid, expires AS expires FROM tokens WHERE token='$hashed';";
$ret = $this->query($sql)->fetchArray(SQLITE3_ASSOC);
if(!$ret) {
return false;
}
if ($ret['expires'] < time()) {
$this->tokenRemove($token);
return false;
}
$this->tokenRefresh($ret['id']);
return $ret['userid'];
}
function getPosts($userid=NULL, $personaid = NULL) {
$sql = "SELECT * FROM posts AS post LEFT JOIN users AS user ON post.userid=user.id LEFT JOIN personas AS persona ON post.personaid=persona.id;";
$ret = $this->query($sql);
$array = array();
while ($row = $ret->fetchArray(SQLITE3_ASSOC)) {
array_push($array, $row);
}
return $array;
}
}
?>