add username limits (no special characters, max and min size) and start working on image support for blog posts (because yes, this is a template, but i also want to get all the basic things for a blog working
This commit is contained in:
parent
17f46ce71d
commit
860399e4fc
|
@ -520,6 +520,7 @@ dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"rand",
|
"rand",
|
||||||
"rand_hc",
|
"rand_hc",
|
||||||
|
"regex",
|
||||||
"rocket",
|
"rocket",
|
||||||
"rocket_db_pools",
|
"rocket_db_pools",
|
||||||
"sha256",
|
"sha256",
|
||||||
|
@ -1384,13 +1385,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.10.2"
|
version = "1.10.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata 0.4.3",
|
"regex-automata 0.4.5",
|
||||||
"regex-syntax 0.8.2",
|
"regex-syntax 0.8.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1405,9 +1406,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.4.3"
|
version = "0.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
|
@ -9,6 +9,7 @@ edition = "2021"
|
||||||
base64 = "0.21.7"
|
base64 = "0.21.7"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
rand_hc = "0.3.2"
|
rand_hc = "0.3.2"
|
||||||
|
regex = "1.10.3"
|
||||||
rocket = {version="0.5.0",features=["secrets","json"]}
|
rocket = {version="0.5.0",features=["secrets","json"]}
|
||||||
rocket_db_pools = {version="0.1.0",features=["sqlx_postgres"]}
|
rocket_db_pools = {version="0.1.0",features=["sqlx_postgres"]}
|
||||||
sha256 = "1.5.0"
|
sha256 = "1.5.0"
|
||||||
|
|
10
src/lib.rs
10
src/lib.rs
|
@ -1 +1,11 @@
|
||||||
pub mod tables;
|
pub mod tables;
|
||||||
|
|
||||||
|
pub struct Status<T> {
|
||||||
|
pub status: StatusTypes,
|
||||||
|
pub data: T
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum StatusTypes {
|
||||||
|
Success,
|
||||||
|
Faliure
|
||||||
|
}
|
||||||
|
|
41
src/main.rs
41
src/main.rs
|
@ -1,3 +1,4 @@
|
||||||
|
use fossil::StatusTypes;
|
||||||
use rocket::fairing::AdHoc;
|
use rocket::fairing::AdHoc;
|
||||||
use rocket::fs::FileServer;
|
use rocket::fs::FileServer;
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
|
@ -43,27 +44,34 @@ async fn createuser(
|
||||||
mut db: Connection<Db>,
|
mut db: Connection<Db>,
|
||||||
info: Json<LoginInfo>,
|
info: Json<LoginInfo>,
|
||||||
cookies: &CookieJar<'_>,
|
cookies: &CookieJar<'_>,
|
||||||
) -> &'static str {
|
) -> String {
|
||||||
let token = cookies.get_private("token");
|
let token = cookies.get_private("token");
|
||||||
match token.is_some() {
|
match token.is_some() {
|
||||||
true => "You're already logged in. Log out before trying to create a new account.",
|
true => "You're already logged in. Log out before trying to create a new account.".to_string(),
|
||||||
false => {
|
false => {
|
||||||
match User::get_by_username(&mut db, &info.username).await {
|
match User::get_by_username(&mut db, &info.username).await {
|
||||||
Some(_) => "Username already taken. Please try again.",
|
Some(_) => "Username already taken. Please try again.".to_string(),
|
||||||
None => {
|
None => {
|
||||||
User::create(&mut db, &info.username, &info.password).await;
|
let created = User::create(&mut db, &info.username, &info.password).await;
|
||||||
|
match created.status {
|
||||||
|
StatusTypes::Success => {
|
||||||
match User::get_by_username(&mut db, &info.username).await {
|
match User::get_by_username(&mut db, &info.username).await {
|
||||||
Some(user) => match user.set_new_token(&mut db).await {
|
Some(user) => match user.set_new_token(&mut db).await {
|
||||||
Ok(t) => {
|
Ok(t) => {
|
||||||
cookies.add_private(("token", t));
|
cookies.add_private(("token", t));
|
||||||
"Your account has been created and you've been automatically logged in."
|
"Your account has been created and you've been automatically logged in.".to_string()
|
||||||
},
|
},
|
||||||
Err(why) => {
|
Err(why) => {
|
||||||
eprintln!("{why:?}");
|
eprintln!("{why:?}");
|
||||||
"Couldn't log you in. Your account has been created, though."
|
"Couldn't log you in. Your account has been created, though.".to_string()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
None => "Something went really wrong. I don't know what."
|
None => "Something went really wrong. I don't know what.".to_string()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StatusTypes::Faliure => {
|
||||||
|
format!("Couldn't create user: {}", created.data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,7 +286,7 @@ async fn migrate(rocket: Rocket<Build>) -> Rocket<Build> {
|
||||||
let mut conn: PoolConnection<Postgres> = db.acquire().await.unwrap();
|
let mut conn: PoolConnection<Postgres> = db.acquire().await.unwrap();
|
||||||
|
|
||||||
let _ = conn
|
let _ = conn
|
||||||
.fetch_one(sqlx::query_as::<_, Post>(
|
.execute(sqlx::query_as::<_, Post>(
|
||||||
"CREATE TABLE IF NOT EXISTS posts (
|
"CREATE TABLE IF NOT EXISTS posts (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
title VARCHAR NOT NULL,
|
title VARCHAR NOT NULL,
|
||||||
|
@ -288,7 +296,7 @@ async fn migrate(rocket: Rocket<Build>) -> Rocket<Build> {
|
||||||
))
|
))
|
||||||
.await;
|
.await;
|
||||||
let _ = conn
|
let _ = conn
|
||||||
.fetch_one(sqlx::query(
|
.execute(sqlx::query(
|
||||||
"CREATE TABLE IF NOT EXISTS users (
|
"CREATE TABLE IF NOT EXISTS users (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
username VARCHAR NOT NULL UNIQUE,
|
username VARCHAR NOT NULL UNIQUE,
|
||||||
|
@ -298,7 +306,7 @@ async fn migrate(rocket: Rocket<Build>) -> Rocket<Build> {
|
||||||
))
|
))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let _ = conn.fetch_one(sqlx::query(
|
let _ = conn.execute(sqlx::query(
|
||||||
"ALTER TABLE users
|
"ALTER TABLE users
|
||||||
ADD COLUMN IF NOT EXISTS admin BOOLEAN NOT NULL DEFAULT FALSE,
|
ADD COLUMN IF NOT EXISTS admin BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
ADD COLUMN IF NOT EXISTS make_posts BOOLEAN NOT NULL DEFAULT FALSE,
|
ADD COLUMN IF NOT EXISTS make_posts BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
@ -326,7 +334,18 @@ async fn migrate(rocket: Rocket<Build>) -> Rocket<Build> {
|
||||||
.await
|
.await
|
||||||
.expect("couldn't create admin user");
|
.expect("couldn't create admin user");
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let _ = conn
|
||||||
|
.execute(sqlx::query(
|
||||||
|
"CREATE TABLE IF NOT EXISTS images (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
uuid VARCHAR NOT NULL UNIQUE,
|
||||||
|
owner_name TEXT NOT NULL,
|
||||||
|
image TEXT NOT NULL
|
||||||
|
)",
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
|
||||||
rocket
|
rocket
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use base64::{engine::general_purpose, Engine};
|
use base64::{engine::general_purpose, Engine};
|
||||||
use rand::{RngCore, SeedableRng};
|
use rand::{RngCore, SeedableRng};
|
||||||
|
use regex::Regex;
|
||||||
use rocket::http::Cookie;
|
use rocket::http::Cookie;
|
||||||
use rocket_db_pools::sqlx::Executor;
|
use rocket_db_pools::sqlx::Executor;
|
||||||
use rocket_db_pools::Connection;
|
use rocket_db_pools::Connection;
|
||||||
|
@ -9,6 +10,8 @@ use rocket_db_pools::{
|
||||||
};
|
};
|
||||||
use sqlx::FromRow;
|
use sqlx::FromRow;
|
||||||
|
|
||||||
|
use crate::{Status, StatusTypes};
|
||||||
|
|
||||||
#[derive(Database)]
|
#[derive(Database)]
|
||||||
#[database("fossil_postgres")]
|
#[database("fossil_postgres")]
|
||||||
pub struct Db(PgPool);
|
pub struct Db(PgPool);
|
||||||
|
@ -67,7 +70,22 @@ pub struct User {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
pub async fn create(db: &mut Connection<Db>, username: &String, password: &String) {
|
pub async fn create(db: &mut Connection<Db>, username: &String, password: &String) -> Status<String> {
|
||||||
|
match Regex::new(r"[^A-Za-z0-9_]") {
|
||||||
|
Ok(r) => {
|
||||||
|
match r.captures(username) {
|
||||||
|
Some(_) => Status {
|
||||||
|
status: StatusTypes::Faliure,
|
||||||
|
data:"The username contains invalid characters. Only letters, numbers, and underscores are allowed.".to_string()
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
if username.len().gt(&32) || username.len().lt(&3) { // i can Never
|
||||||
|
// remember which symbol is which. this works better for me.
|
||||||
|
Status {
|
||||||
|
status: StatusTypes::Faliure,
|
||||||
|
data: "Please choose a username between 3 and 32 characters.".to_string()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
match db
|
match db
|
||||||
.execute(
|
.execute(
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
|
@ -78,12 +96,30 @@ impl User {
|
||||||
)
|
)
|
||||||
.bind(username)
|
.bind(username)
|
||||||
.bind(sha256::digest(password)),
|
.bind(sha256::digest(password)),
|
||||||
)
|
).await
|
||||||
.await
|
|
||||||
{
|
{
|
||||||
Ok(_) => (),
|
Ok(_) => Status {
|
||||||
|
status: StatusTypes::Success,
|
||||||
|
data: "Created user.".to_string()
|
||||||
|
},
|
||||||
Err(why) => {
|
Err(why) => {
|
||||||
eprintln!("Couldn't create database entry: {why:?}");
|
eprintln!("Couldn't create database entry: {why:?}");
|
||||||
|
Status {
|
||||||
|
status: StatusTypes::Faliure,
|
||||||
|
data: "Failed to create user.".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(why) => {
|
||||||
|
eprintln!("Couldn't compile name regex: {why:?}");
|
||||||
|
Status {
|
||||||
|
status: StatusTypes::Faliure,
|
||||||
|
data: "Couldn't compile name regex.".to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,3 +231,10 @@ impl User {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Image {
|
||||||
|
pub id: i32,
|
||||||
|
pub uuid: String,
|
||||||
|
pub owner_name: String,
|
||||||
|
pub image: String,
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue