gourami

[UNMAINTAINED] Activitypub server in Rust
Log | Files | Refs | README | LICENSE

commit c03cbb543de11116c3ea9f00030be6d68d298df9
parent 0b2292cb015fa1194f240dfef45a4f888013ab33
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Wed, 22 Apr 2020 20:03:19 -0500

Add registration key codes

Diffstat:
Mmigrations/2020-04-13-014917_initialize/up.sql | 4++++
Msrc/db/schema.rs | 6++++++
Msrc/db/user.rs | 28++++++++++++++++++++++++++++
Msrc/lib.rs | 48+++++++++++++++++++++++++++++++++++-------------
Mtemplates/login.html | 2+-
Mtemplates/register.html | 6+++++-
6 files changed, 79 insertions(+), 15 deletions(-)

diff --git a/migrations/2020-04-13-014917_initialize/up.sql b/migrations/2020-04-13-014917_initialize/up.sql @@ -12,6 +12,10 @@ CREATE TABLE users ( CREATE UNIQUE INDEX users_username_idx ON users (username); CREATE UNIQUE INDEX users_email_idx ON users (email); +CREATE TABLE registration_keys ( + value VARCHAR PRIMARY KEY +); + CREATE TABLE activities ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, json_text TEXT diff --git a/src/db/schema.rs b/src/db/schema.rs @@ -10,6 +10,12 @@ table! { } table! { + registration_keys (value) { + value -> Varchar, + } +} + +table! { users (id) { id -> Integer, username -> Varchar, diff --git a/src/db/user.rs b/src/db/user.rs @@ -6,6 +6,34 @@ use serde::{Deserialize, Serialize}; use bcrypt; #[derive(Debug, Clone, Default, Queryable, Deserialize)] +pub struct RegistrationKey { + value: String, +} + +impl RegistrationKey { + pub fn is_valid(conn: &SqliteConnection, key: &str) -> bool { + use crate::db::schema::registration_keys::dsl::*; + let key: Option<String> = registration_keys + .select(value) + .filter(value.eq(key)) + .first(conn) + .ok(); + match key { + Some(_) => true, + None => false + } + } + + pub fn clear_key(conn: &SqliteConnection, key: &str) { + use crate::db::schema::registration_keys::dsl::*; + diesel::delete( + registration_keys + .filter(value.eq(key))) + .execute(conn).ok(); + } +} + +#[derive(Debug, Clone, Default, Queryable, Deserialize)] pub struct User { pub id: i32, pub username: String, diff --git a/src/lib.rs b/src/lib.rs @@ -18,7 +18,7 @@ use askama::Template; use env_logger; use db::note::{NoteInput, Note}; use db::note; -use db::user::{User, NewUser}; +use db::user::{RegistrationKey, User, NewUser}; use diesel::prelude::*; use diesel::sqlite::SqliteConnection; use diesel::insert_into; @@ -148,13 +148,24 @@ fn send_to_outbox(activity: bool) { // activitystreams object #[template(path = "register.html")] struct RegisterTemplate<'a>{ page: &'a str, + keyed: bool, + key: &'a str, global: Global<'a>, } -fn register_page() -> impl warp::Reply { +fn register_page(query_params: serde_json::Value) -> impl warp::Reply { let global = Global::from_session(None); + let keyed; + if let Some(k) = query_params.get("key") { + let key_str = k.as_str().unwrap(); + keyed = RegistrationKey::is_valid(&POOL.get().unwrap(), &key_str); + render_template(&RegisterTemplate{keyed: keyed, key: key_str, page: "register", global:global}) + } + else { + keyed = false; + render_template(&RegisterTemplate{keyed: keyed, key: "", page: "register", global:global}) + } // TODO -- do... something if session is not none - render_template(&RegisterTemplate{page: "register", global:global}) } @@ -179,14 +190,23 @@ impl RegisterForm { } // TODO move all authentication -fn do_register(form: RegisterForm) -> impl Reply{ +fn do_register(form: RegisterForm, query_params: serde_json::Value) -> impl Reply { + let conn = &POOL.get().unwrap(); use db::schema::users::dsl::*; - let hash = bcrypt::hash(&form.password, bcrypt::DEFAULT_COST).unwrap(); - let new_user = NewUser {username: &form.username, password: &hash, email: &form.email}; - // todo data validation - insert_into(users).values(new_user).execute(&POOL.get().unwrap()).unwrap(); - - // insert into database + if let Some(k) = query_params.get("key") { + let keyed = RegistrationKey::is_valid(&POOL.get().unwrap(), &k.as_str().unwrap()); + if keyed { + let hash = bcrypt::hash(&form.password, bcrypt::DEFAULT_COST).unwrap(); + let new_user = NewUser {username: &form.username, password: &hash, email: &form.email}; + // todo data validation + insert_into(users) + .values(new_user) + .execute(conn).unwrap(); + + // insert into database + } + } + // not good do_login(LoginForm{username: form.username, password: form.password}) } @@ -347,7 +367,7 @@ pub async fn run_server() { let public = false; // std::env::var("PUBLIC").unwrap_or("false"); let session_filter = move || session::create_session_filter(public).clone(); - use warp::{path, body::json, body::form}; + use warp::{path, body::json, body::form, filters::query::query}; let home = warp::path::end() .and(session_filter()) @@ -367,10 +387,12 @@ pub async fn run_server() { // auth functions let register_page = path("register") - .map(|| register_page()); + .and(query()) + .map(register_page); - let do_register = path("register") + let do_register = path("do_register") .and(form()) + .and(query()) .map(do_register); let login_page = path("login") diff --git a/templates/login.html b/templates/login.html @@ -13,7 +13,7 @@ <button class="submit-button-style" type="submit">Login</button> <br> {% if login_failed %} - failed login. try again. + Failed login. Try again. {% endif %} </div> </form> diff --git a/templates/register.html b/templates/register.html @@ -1,8 +1,9 @@ {% extends "base.html" %} {% block content %} <div class="container"> -<form action="/register" method="POST"> + <form action="/do_register?key={{key}}" method="POST"> <div class="container"> + {% if keyed %} <label for="email"><b>Email</b></label> <input type="text" placeholder="Enter Email" name="email" required> <br> @@ -13,6 +14,9 @@ <label for="password"><b>Password</b></label> <input type="password" placeholder="Enter Password" name="password" required> <button class="submit-button-style" type="submit">Register</button> + {% else %} + Invalid registration key -- contact the admin for an invite. + {% endif %} <br> </div> </form>