gaming
This commit is contained in:
parent
f61a739095
commit
d0709646d1
|
@ -252,9 +252,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.19"
|
||||
version = "0.7.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
|
||||
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -280,6 +280,17 @@ version = "1.0.66"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
|
||||
|
||||
[[package]]
|
||||
name = "argon2"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db4ce4441f99dbd377ca8a8f57b698c44d0d6e712d8329b5040da5a64aa1ce73"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"blake2",
|
||||
"password-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "askama"
|
||||
version = "0.11.1"
|
||||
|
@ -341,9 +352,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.58"
|
||||
version = "0.1.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c"
|
||||
checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -362,12 +373,27 @@ version = "0.13.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "blake2"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b12e5fd123190ce1c2e559308a94c9bacad77907d4c6005d9e58fe1a0689e55e"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.3"
|
||||
|
@ -547,9 +573,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
|||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.24"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
|
||||
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
|
@ -869,9 +895,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
|||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.5.4"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
|
||||
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
@ -957,9 +983,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.4"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
|
||||
checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
|
@ -968,6 +994,17 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "password-hash"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.9"
|
||||
|
@ -1176,18 +1213,18 @@ checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.147"
|
||||
version = "1.0.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
|
||||
checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.147"
|
||||
version = "1.0.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
|
||||
checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1196,9 +1233,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.88"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e8b3801309262e8184d9687fb697586833e939767aea0dda89f5a8e650e8bd7"
|
||||
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -1290,9 +1327,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.103"
|
||||
version = "1.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
|
||||
checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1544,6 +1581,7 @@ dependencies = [
|
|||
"actix-session",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"argon2",
|
||||
"askama",
|
||||
"askama_actix",
|
||||
"hex",
|
||||
|
@ -1684,9 +1722,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "2.0.1+zstd.1.5.2"
|
||||
version = "2.0.4+zstd.1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b"
|
||||
checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
|
|
|
@ -15,6 +15,7 @@ actix-session = { version = "0.7", features = ["cookie-session"] }
|
|||
askama = { version = "0.11", features = ["with-actix-web"] }
|
||||
askama_actix = "0.13"
|
||||
anyhow = "1.0"
|
||||
argon2 = "0.4"
|
||||
rusqlite = "0.28"
|
||||
rust-embed = "6.4"
|
||||
mime_guess = "2.0"
|
||||
|
|
|
@ -66,7 +66,7 @@ async fn main() -> anyhow::Result<()> {
|
|||
let (storage_service, storage) = StorageService::create(&config.database, nsdcpath)?;
|
||||
let storage_thread = thread::spawn(|| storage_service.run());
|
||||
|
||||
let web_backend = WebBackend::new(config).run()?;
|
||||
let web_backend = WebBackend::new(config, storage).run()?;
|
||||
let web_task = tokio::spawn(async move {
|
||||
if let Err(e) = web_backend.await {
|
||||
let _err = etx.send(e);
|
||||
|
@ -87,7 +87,6 @@ async fn main() -> anyhow::Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
drop(storage);
|
||||
let _ = ctx.send(());
|
||||
web_task.await.unwrap();
|
||||
storage_thread.join().unwrap();
|
||||
|
|
|
@ -21,7 +21,12 @@ use std::{
|
|||
str::FromStr,
|
||||
};
|
||||
|
||||
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
|
||||
use anyhow::{anyhow, Result};
|
||||
use rusqlite::{ErrorCode, OptionalExtension};
|
||||
use tokio::sync::{
|
||||
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
|
||||
oneshot,
|
||||
};
|
||||
use tokio::time::Instant;
|
||||
|
||||
mod nsdcontrol;
|
||||
|
@ -54,7 +59,7 @@ impl StorageService {
|
|||
let (tx, rx) = unbounded_channel();
|
||||
let db = rusqlite::Connection::open(dbpath)?;
|
||||
db.execute("pragma foreign_keys = on", [])?;
|
||||
db.execute(include_str!("schema.sql"), [])?;
|
||||
db.execute_batch(include_str!("schema.sql"))?;
|
||||
tracing::debug!("Database loaded ({})", dbpath);
|
||||
Ok((
|
||||
Self {
|
||||
|
@ -70,12 +75,52 @@ impl StorageService {
|
|||
while let Some(task) = self.rx.blocking_recv() {
|
||||
let before = Instant::now();
|
||||
tracing::debug!("got task {:?}", task);
|
||||
match task {
|
||||
Task::RegisterAccount(tx, u, h) => tx.send(self.register_account(u, h)).unwrap(),
|
||||
Task::GetAccountByUsername(tx, u) => {
|
||||
tx.send(self.get_account_by_username(u)).unwrap()
|
||||
}
|
||||
}
|
||||
tracing::debug!(
|
||||
"task took {}ms",
|
||||
Instant::now().duration_since(before).as_secs_f64() / 1000.0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn register_account(&self, username: String, hash: String) -> Result<Option<i64>> {
|
||||
let result = self.db.query_row(
|
||||
"insert into accounts(username,hash) values (?, ?) returning id",
|
||||
[username, hash],
|
||||
|v| v.get(0),
|
||||
);
|
||||
match result {
|
||||
Ok(o) => Ok(Some(o)),
|
||||
Err(err) => {
|
||||
if let rusqlite::Error::SqliteFailure(serr, _) = err && serr.code == ErrorCode::ConstraintViolation {
|
||||
Ok(None)
|
||||
} else {
|
||||
Err(anyhow!(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_account_by_username(&self, username: String) -> Result<Option<AccountCredentials>> {
|
||||
Ok(self
|
||||
.db
|
||||
.query_row(
|
||||
"select id,hash from accounts where username=?",
|
||||
[username],
|
||||
|v| {
|
||||
Ok(AccountCredentials {
|
||||
id: v.get::<_, i64>(0)?,
|
||||
hash: v.get::<_, String>(1)?,
|
||||
})
|
||||
},
|
||||
)
|
||||
.optional()?)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StorageConnection {
|
||||
|
@ -91,14 +136,31 @@ impl Clone for StorageConnection {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Task {}
|
||||
pub struct AccountCredentials {
|
||||
id: i64,
|
||||
hash: String,
|
||||
}
|
||||
|
||||
type ResultSender<T> = oneshot::Sender<Result<T>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Task {
|
||||
RegisterAccount(ResultSender<Option<i64>>, String, String),
|
||||
GetAccountByUsername(ResultSender<Option<AccountCredentials>>, String),
|
||||
}
|
||||
|
||||
impl StorageConnection {
|
||||
// WARNING: these methods are NOT cancel-safe
|
||||
// executor_wrapper!(
|
||||
// add_quote,
|
||||
// Task::AddQuote,
|
||||
// rusqlite::Result<()>,
|
||||
// quote: Quote
|
||||
// );
|
||||
executor_wrapper!(
|
||||
register_account,
|
||||
Task::RegisterAccount,
|
||||
Result<Option<i64>>,
|
||||
username: String,
|
||||
hash: String
|
||||
);
|
||||
executor_wrapper!(
|
||||
get_account,
|
||||
Task::GetAccountByUsername,
|
||||
Result<Option<AccountCredentials>>,
|
||||
username: String
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
create table if not exists accounts(
|
||||
id integer primary key,
|
||||
username text not null,
|
||||
password text not null
|
||||
hash text not null
|
||||
);
|
||||
|
||||
create table if not exists requests(
|
||||
|
@ -30,3 +30,4 @@ create table if not exists records(
|
|||
);
|
||||
|
||||
create unique index if not exists name_index on domains (name);
|
||||
create unique index if not exists username_index on accounts (username);
|
||||
|
|
|
@ -16,12 +16,15 @@
|
|||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use crate::storage::StorageConnection;
|
||||
use crate::Config;
|
||||
use actix_session::storage::CookieSessionStore;
|
||||
use actix_session::{SessionMiddleware, Session};
|
||||
use actix_session::{Session, SessionMiddleware};
|
||||
use actix_web::cookie::Key;
|
||||
use actix_web::dev::Server;
|
||||
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
|
||||
use actix_web::web::Data;
|
||||
use actix_web::{web, App, HttpRequest, HttpResponse, HttpServer, Responder};
|
||||
use argon2::Argon2;
|
||||
use rust_embed::RustEmbed;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -29,6 +32,7 @@ mod templates;
|
|||
|
||||
pub struct WebBackend {
|
||||
config: Arc<Config>,
|
||||
db: StorageConnection,
|
||||
}
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
|
@ -49,18 +53,38 @@ async fn static_files(path: web::Path<String>) -> impl Responder {
|
|||
}
|
||||
|
||||
#[actix_web::get("/")]
|
||||
async fn login(session: Session) -> actix_web::Result<impl Responder> {
|
||||
Ok(templates::LoginTemplate {flash: None})
|
||||
async fn login(session: Session, req: HttpRequest) -> actix_web::Result<impl Responder> {
|
||||
if let Some(_) = session.get::<i64>("uid")? {
|
||||
Ok(HttpResponse::TemporaryRedirect().finish())
|
||||
} else {
|
||||
Ok(templates::LoginTemplate { flash: None }.respond_to(&req))
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_web::get("/register")]
|
||||
async fn register(session: Session, req: HttpRequest) -> actix_web::Result<impl Responder> {
|
||||
if let Some(_) = session.get::<i64>("uid")? {
|
||||
Ok(HttpResponse::TemporaryRedirect().finish())
|
||||
} else {
|
||||
Ok(templates::RegisterTemplate { flash: None }.respond_to(&req))
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_web::post("/")]
|
||||
async fn login_post(session: Session) -> actix_web::Result<impl Responder> {
|
||||
Ok(templates::LoginTemplate {flash: Some("wtfjusthappened".into())})
|
||||
Ok(templates::LoginTemplate {
|
||||
flash: Some("wtfjusthappened".into()),
|
||||
})
|
||||
}
|
||||
|
||||
#[actix_web::post("/register")]
|
||||
async fn register_post(session: Session) -> actix_web::Result<impl Responder> {
|
||||
Ok("")
|
||||
}
|
||||
|
||||
impl WebBackend {
|
||||
pub fn new(config: Arc<Config>) -> Self {
|
||||
Self { config }
|
||||
pub fn new(config: Arc<Config>, db: StorageConnection) -> Self {
|
||||
Self { config, db }
|
||||
}
|
||||
|
||||
pub fn run(self) -> anyhow::Result<Server> {
|
||||
|
@ -72,8 +96,12 @@ impl WebBackend {
|
|||
CookieSessionStore::default(),
|
||||
key.clone(),
|
||||
))
|
||||
.app_data(Data::new(Argon2::default()))
|
||||
.app_data(Data::new(self.db.clone()))
|
||||
.service(login)
|
||||
.service(login_post)
|
||||
.service(register)
|
||||
.service(register_post)
|
||||
.service(static_files)
|
||||
})
|
||||
.bind(self.config.web.listen)?
|
||||
|
|
|
@ -21,5 +21,11 @@ use askama::Template;
|
|||
#[derive(Template)]
|
||||
#[template(path = "login.html")]
|
||||
pub struct LoginTemplate {
|
||||
pub flash: Option<String>
|
||||
pub flash: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "register.html")]
|
||||
pub struct RegisterTemplate {
|
||||
pub flash: Option<String>,
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
{% block title %}Login{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<h1>Log in</h1>
|
||||
{% match flash %}
|
||||
{% when Some with (flash) %}
|
||||
<small style="color: var(--del-color)">{{flash}}</small>
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
{% extends "base.html" %}
|
||||
{% block title %}Login{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<h1>Register</h1>
|
||||
{% match flash %}
|
||||
{% when Some with (flash) %}
|
||||
<small style="color: var(--del-color)">{{flash}}</small>
|
||||
{% when None %}
|
||||
{% endmatch %}
|
||||
<form action="/register" method="post">
|
||||
<label for="login">Login</label>
|
||||
<input type="text" name="login" id="login" required>
|
||||
<label for="pass">Password</label>
|
||||
<input type="password" name="password" id="pass" required>
|
||||
<input type="submit" value="Register">
|
||||
</form>
|
||||
<small style="float: right;"><a href="/">Log in instead</a></small>
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in New Issue