add(backend): move to dorsal for database

add(backend): accept Extended_Pictographic in custom url
TODO: punycode custom urls
chore: bump version (v0.12.0 -> v0.12.1)
This commit is contained in:
hkau 2024-04-08 14:00:43 -04:00
parent dd9d5597c9
commit 942f762949
16 changed files with 342 additions and 1110 deletions

2
.cargo/config Normal file
View file

@ -0,0 +1,2 @@
[registries]
stellular = { index = "sparse+https://code.stellular.org/api/packages/stellular/cargo/" }

View file

@ -3,7 +3,7 @@ name = "bundlrs"
authors = ["hkau"]
license = "MIT"
version = "0.12.0"
version = "0.12.1"
edition = "2021"
rust-version = "1.75"
@ -11,20 +11,21 @@ rust-version = "1.75"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
postgres = []
mysql = []
sqlite = []
default = ["sqlite"]
postgres = ["dorsal/postgres"]
mysql = ["dorsal/mysql"]
sqlite = ["dorsal/sqlite"]
default = ["dorsal/sqlite"]
[dependencies]
awc = { version = "3.4.0", features = ["rustls"] }
actix-files = "0.6.5"
actix-web = "4.4.1"
comrak = "0.21.0"
comrak = "0.22.0"
dotenv = "0.15.0"
either = "1.9.0"
env_logger = "0.11.2"
hex_fmt = "0.3.0"
dorsal = { version = "0.1.1", registry = "stellular", default-features = false } # crates: disable-check
idna = "0.5.0"
once_cell = "1.19.0"
pest = "2.7.7"
@ -33,16 +34,7 @@ regex = "1.10.2"
serde = "1.0.195"
serde_json = "1.0.111"
sha2 = "0.10.8"
sqlx = { version = "0.7.3", features = [
"sqlite",
"postgres",
"mysql",
"any",
"runtime-tokio",
"tls-native-tls",
] }
uuid = { version = "1.6.1", features = ["v4"] }
yew = { version = "0.21.0", features = ["ssr"] }
redis = "0.25.2"
handlebars = "5.1.2"
actix-cors = "0.7.0"

View file

@ -1,6 +1,8 @@
build database="sqlite":
just docs
./scripts/download_styles.sh
just styles
bun i
bun run static_build.ts
cargo build -r --no-default-features --features {{database}}
docs:
@ -14,3 +16,11 @@ test:
run:
chmod +x ./target/release/bundlrs
./target/release/bundlrs
styles:
wget https://codeberg.org/api/packages/hkau/npm/fusion/-/1.0.11/fusion-1.0.11.tgz -O fusion.tgz
tar -xzf fusion.tgz
mv ./package/src/css ./static/css
sed -i -e 's/\"\/utility.css\"/\"\/static\/css\/utility.css\"/' ./static/css/fusion.css
rm -r ./package
rm ./fusion.tgz

View file

@ -1,14 +0,0 @@
wget https://codeberg.org/api/packages/hkau/npm/fusion/-/1.0.11/fusion-1.0.11.tgz -O fusion.tgz
mv ./fusion.tgz ./static/fusion.tgz
cd static
tar -xzf fusion.tgz
mv package/src/css ./css
sed -i -e 's/\"\/utility.css\"/\"\/static\/css\/utility.css\"/' ./css/fusion.css
rm -r package
rm ./fusion.tgz
cd ../
bun run static_build.ts

View file

@ -1,4 +1,4 @@
use crate::db::bundlesdb::{self, AppData};
use crate::db::{self, AppData};
use actix_web::{get, post, web, HttpRequest, HttpResponse, Responder};
#[derive(Default, PartialEq, serde::Deserialize)]
@ -57,29 +57,27 @@ pub async fn logout(req: HttpRequest, data: web::Data<AppData>) -> impl Responde
/// Get all pastes by owner
pub async fn get_from_owner_request(
req: HttpRequest,
data: web::Data<bundlesdb::AppData>,
data: web::Data<db::AppData>,
info: web::Query<crate::api::pastes::OffsetQueryProps>,
) -> impl Responder {
let name: String = req.match_info().get("name").unwrap().to_string();
// get pastes
let res: bundlesdb::DefaultReturn<Option<Vec<bundlesdb::PasteIdentifier>>> =
let res: db::DefaultReturn<Option<Vec<db::PasteIdentifier>>> =
data.db.get_pastes_by_owner_limited(name, info.offset).await;
// return
return HttpResponse::Ok()
.append_header(("Content-Type", "application/json"))
.body(
serde_json::to_string::<
bundlesdb::DefaultReturn<Option<Vec<bundlesdb::PasteIdentifier>>>,
>(&res)
.unwrap(),
serde_json::to_string::<db::DefaultReturn<Option<Vec<db::PasteIdentifier>>>>(&res)
.unwrap(),
);
}
#[post("/api/auth/users/{name:.*?}/ban")]
/// Ban user
pub async fn ban_request(req: HttpRequest, data: web::Data<bundlesdb::AppData>) -> impl Responder {
pub async fn ban_request(req: HttpRequest, data: web::Data<db::AppData>) -> impl Responder {
let name: String = req.match_info().get("name").unwrap().to_string();
// get token user
@ -116,10 +114,10 @@ pub async fn ban_request(req: HttpRequest, data: web::Data<bundlesdb::AppData>)
}
// ban user
let res: bundlesdb::DefaultReturn<Option<String>> = data.db.ban_user_by_name(name).await;
let res: db::DefaultReturn<Option<String>> = data.db.ban_user_by_name(name).await;
// return
return HttpResponse::Ok()
.append_header(("Content-Type", "application/json"))
.body(serde_json::to_string::<bundlesdb::DefaultReturn<Option<String>>>(&res).unwrap());
.body(serde_json::to_string::<db::DefaultReturn<Option<String>>>(&res).unwrap());
}

View file

@ -1,6 +1,6 @@
use actix_web::{get, post, web, HttpRequest, HttpResponse, Responder};
use crate::db::bundlesdb::{self, AtomicPasteFSFile, DefaultReturn, FullPaste, PasteMetadata};
use crate::db::{self, AtomicPasteFSFile, DefaultReturn, FullPaste, PasteMetadata};
use crate::{markdown, ssm, utility};
#[derive(Default, PartialEq, serde::Deserialize)]
@ -47,7 +47,7 @@ struct DeleteInfo {
struct MetadataInfo {
custom_url: String,
edit_password: String,
metadata: bundlesdb::PasteMetadata,
metadata: db::PasteMetadata,
}
#[post("/api/markdown")]
@ -67,7 +67,7 @@ pub async fn render_ssm_request(body: web::Json<RenderInfo>) -> impl Responder {
#[get("/api/ssm/{url:.*}")]
pub async fn render_paste_ssm_request(
req: HttpRequest,
data: web::Data<bundlesdb::AppData>,
data: web::Data<db::AppData>,
) -> impl Responder {
let custom_url: String = req.match_info().get("url").unwrap().to_string();
let res = data.db.get_paste_by_url(custom_url).await;
@ -109,7 +109,7 @@ pub async fn render_paste_ssm_request(
pub async fn create_request(
req: HttpRequest,
body: web::Json<CreateInfo>,
data: web::Data<bundlesdb::AppData>,
data: web::Data<db::AppData>,
) -> impl Responder {
let custom_url: String = body.custom_url.trim().to_string();
let edit_password: &String = &body.edit_password;
@ -153,7 +153,7 @@ pub async fn create_request(
let res = data
.db
.create_paste(
&mut bundlesdb::Paste {
&mut db::Paste {
custom_url: custom_url.clone(),
id: String::new(), // reassigned anyways, this doesn't matter
edit_password: edit_password.to_string(),
@ -184,7 +184,7 @@ pub async fn create_request(
pub async fn edit_request(
req: HttpRequest,
body: web::Json<EditInfo>,
data: web::Data<bundlesdb::AppData>,
data: web::Data<db::AppData>,
) -> impl Responder {
let custom_url: String = body.custom_url.trim().to_string();
let content: String = body.content.trim().to_string();
@ -239,7 +239,7 @@ pub async fn edit_request(
pub async fn edit_atomic_request(
req: HttpRequest,
body: web::Json<EditAtomicInfo>,
data: web::Data<bundlesdb::AppData>,
data: web::Data<db::AppData>,
) -> impl Responder {
// this is essentially the same as edit_request but it handles the atomic JSON file system
// ...it does NOT accept an edit password! users must be authenticated
@ -285,7 +285,7 @@ pub async fn edit_atomic_request(
}
// get file from path
let real_content = serde_json::from_str::<bundlesdb::AtomicPaste>(&unwrap.paste.content);
let real_content = serde_json::from_str::<db::AtomicPaste>(&unwrap.paste.content);
if real_content.is_err() {
return HttpResponse::NotAcceptable().body("Paste failed to deserialize");
@ -312,7 +312,7 @@ pub async fn edit_atomic_request(
.db
.edit_paste_by_url(
custom_url,
serde_json::to_string::<bundlesdb::AtomicPaste>(&decoded).unwrap(), // encode content
serde_json::to_string::<db::AtomicPaste>(&decoded).unwrap(), // encode content
String::new(),
Option::None,
Option::None,
@ -335,7 +335,7 @@ pub async fn edit_atomic_request(
pub async fn delete_request(
req: HttpRequest,
body: web::Json<DeleteInfo>,
data: web::Data<bundlesdb::AppData>,
data: web::Data<db::AppData>,
) -> impl Responder {
let custom_url: String = body.custom_url.trim().to_string();
let edit_password: String = body.edit_password.to_owned();
@ -384,13 +384,13 @@ pub async fn delete_request(
pub async fn metadata_request(
req: HttpRequest,
body: web::Json<MetadataInfo>,
data: web::Data<bundlesdb::AppData>,
data: web::Data<db::AppData>,
) -> impl Responder {
let custom_url: String = body.custom_url.trim().to_string();
let edit_password: String = body.edit_password.to_owned();
let m = body.metadata.to_owned();
let metadata: bundlesdb::PasteMetadata = m;
let metadata: db::PasteMetadata = m;
// get token user
let token_cookie = req.cookie("__Secure-Token");
@ -434,10 +434,7 @@ pub async fn metadata_request(
#[get("/api/exists/{url:.*}")]
/// Check if a paste exists
pub async fn exists_request(
req: HttpRequest,
data: web::Data<bundlesdb::AppData>,
) -> impl Responder {
pub async fn exists_request(req: HttpRequest, data: web::Data<db::AppData>) -> impl Responder {
let custom_url: String = req.match_info().get("url").unwrap().to_string();
let res = data.db.get_paste_by_url(custom_url).await;
@ -451,7 +448,7 @@ pub async fn exists_request(
/// Get paste by `custom_url`
pub async fn get_from_url_request(
req: HttpRequest,
data: web::Data<bundlesdb::AppData>,
data: web::Data<db::AppData>,
) -> impl Responder {
let custom_url: String = req.match_info().get("url").unwrap().to_string();
let res: DefaultReturn<Option<FullPaste<PasteMetadata, String>>> =
@ -489,10 +486,7 @@ pub async fn get_from_url_request(
#[get("/api/id/{id:.*}")]
/// Get paste by ID
pub async fn get_from_id_request(
req: HttpRequest,
data: web::Data<bundlesdb::AppData>,
) -> impl Responder {
pub async fn get_from_id_request(req: HttpRequest, data: web::Data<db::AppData>) -> impl Responder {
let id: String = req.match_info().get("id").unwrap().to_string();
let res: DefaultReturn<Option<FullPaste<PasteMetadata, String>>> =
data.db.get_paste_by_id(id).await;

File diff suppressed because it is too large Load diff

View file

@ -1,112 +0,0 @@
//! # CacheDB
//!
//! Redis connection.
//!
//! Identifiers should be a string following this format: `TYPE_OF_OBJECT:OBJECT_ID`. For pastes this would look like: `paste:{custom_url}`
use redis::Commands;
#[derive(Clone)]
pub struct CacheDB {
pub client: redis::Client,
}
impl CacheDB {
pub async fn new() -> CacheDB {
return CacheDB {
client: redis::Client::open("redis://127.0.0.1:6379").unwrap(),
};
}
pub async fn get_con(&self) -> redis::Connection {
self.client.get_connection().unwrap()
}
// GET
/// Get a cache object by its identifier
///
/// # Arguments:
/// * `id` - `String` of the object's id
pub async fn get(&self, id: String) -> Option<String> {
// fetch from database
let mut c = self.get_con().await;
let res = c.get(id);
if res.is_err() {
return Option::None;
}
// return
Option::Some(res.unwrap())
}
// SET
/// Set a cache object by its identifier and content
///
/// # Arguments:
/// * `id` - `String` of the object's id
/// * `content` - `String` of the object's content
pub async fn set(&self, id: String, content: String) -> bool {
// set
let mut c = self.get_con().await;
let res: Result<String, redis::RedisError> = c.set(id, content);
if res.is_err() {
return false;
}
// return
true
}
/// Update a cache object by its identifier and content
///
/// # Arguments:
/// * `id` - `String` of the object's id
/// * `content` - `String` of the object's content
pub async fn update(&self, id: String, content: String) -> bool {
self.set(id, content).await
}
/// Remove a cache object by its identifier
///
/// # Arguments:
/// * `id` - `String` of the object's id
pub async fn remove(&self, id: String) -> bool {
// remove
let mut c = self.get_con().await;
let res: Result<String, redis::RedisError> = c.del(id);
if res.is_err() {
return false;
}
// return
true
}
/// Remove a cache object by its identifier('s start)
///
/// # Arguments:
/// * `id` - `String` of the object's id('s start)
pub async fn remove_starting_with(&self, id: String) -> bool {
let mut c = self.get_con().await;
// get keys
let mut cmd = redis::cmd("DEL");
let keys: Result<Vec<String>, redis::RedisError> = c.keys(id);
for key in keys.unwrap() {
cmd.arg(key);
}
// remove
let res: Result<String, redis::RedisError> = cmd.query(&mut c);
if res.is_err() {
return false;
}
// return
true
}
}

View file

@ -1,4 +0,0 @@
//! Database handling
pub mod bundlesdb;
pub mod cachedb;
pub mod sql;

View file

@ -1,100 +0,0 @@
#[derive(Debug, Clone)]
pub struct DatabaseOpts {
pub _type: Option<String>,
pub host: Option<String>,
pub user: String,
pub pass: String,
pub name: String,
}
// ...
#[derive(Clone)]
pub struct Database<T> {
pub client: T,
pub _type: String,
}
// ...
#[cfg(feature = "mysql")]
/// Create a new "mysql" database
pub async fn create_db(options: DatabaseOpts) -> Database<sqlx::MySqlPool> {
// mysql
let opts = sqlx::mysql::MySqlPoolOptions::new()
.max_connections(25)
.acquire_timeout(std::time::Duration::from_millis(2000))
.idle_timeout(Some(std::time::Duration::from_secs(60 * 5)));
// .max_lifetime(Some(std::time::Duration::from_secs(120)));
let client = opts
.connect(&format!(
"mysql://{}:{}@{}/{}",
options.user,
options.pass,
if options.host.is_some() {
options.host.unwrap()
} else {
"localhost".to_string()
},
options.name
))
.await;
if client.is_err() {
panic!("failed to connect to database: {}", client.err().unwrap());
}
return Database {
client: client.unwrap(),
_type: String::from("mysql"),
};
}
#[cfg(feature = "postgres")]
/// Create a new "postgres" database
pub async fn create_db(options: DatabaseOpts) -> Database<sqlx::PgPool> {
// postgres
let opts = sqlx::postgres::PgPoolOptions::new()
.max_connections(25)
.acquire_timeout(std::time::Duration::from_millis(2000))
.idle_timeout(Some(std::time::Duration::from_secs(60 * 5)));
// .max_lifetime(Some(std::time::Duration::from_secs(120)));
let client = opts
.connect(&format!(
"postgres://{}:{}@{}/{}",
options.user,
options.pass,
if options.host.is_some() {
options.host.unwrap()
} else {
"localhost".to_string()
},
options.name
))
.await;
if client.is_err() {
panic!("failed to connect to database: {}", client.err().unwrap());
}
return Database {
client: client.unwrap(),
_type: String::from("postgres"),
};
}
#[cfg(feature = "sqlite")]
/// Create a new "sqlite" database
pub async fn create_db(_options: DatabaseOpts) -> Database<sqlx::SqlitePool> {
// sqlite
let client = sqlx::SqlitePool::connect("sqlite://bundlrs.db").await;
if client.is_err() {
panic!("Failed to connect to database!");
}
return Database {
client: client.unwrap(),
_type: String::from("sqlite"),
};
}

View file

@ -2,7 +2,6 @@ use actix_files as fs;
use actix_web::{web, App, HttpResponse, HttpServer};
use dotenv;
use sqlx;
use yew::ServerRenderer;
mod config;
@ -16,8 +15,7 @@ mod pages;
mod markdown;
mod ssm;
use crate::db::bundlesdb::{AppData, BundlesDB};
use crate::db::sql::DatabaseOpts;
use crate::db::{AppData, Database};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
@ -53,8 +51,7 @@ async fn main() -> std::io::Result<()> {
panic!("Missing required database config settings!");
}
sqlx::any::install_default_drivers(); // install database drivers
let db: BundlesDB = BundlesDB::new(DatabaseOpts {
let db: Database = Database::new(dorsal::DatabaseOpts {
_type: db_type,
host: db_host,
user: if db_is_other {

View file

@ -5,8 +5,7 @@ use yew::prelude::*;
use yew::ServerRenderer;
use crate::components::navigation::{Footer, GlobalMenu};
use crate::db::bundlesdb::{AtomicPasteFSFile, FullPaste, PasteMetadata};
use crate::db::{self, bundlesdb};
use crate::db::{self, AtomicPasteFSFile, FullPaste, PasteMetadata};
use crate::utility::{self, format_html};
#[derive(Default, Properties, PartialEq, serde::Deserialize)]
@ -16,14 +15,14 @@ struct EditQueryProps {
#[derive(Default, Properties, PartialEq, serde::Deserialize)]
struct FSProps {
pub files: Vec<bundlesdb::AtomicPasteFSFile>,
pub files: Vec<db::AtomicPasteFSFile>,
pub auth_state: Option<bool>,
}
#[derive(Default, Properties, PartialEq, serde::Deserialize)]
struct EditProps {
pub custom_url: String,
pub file: bundlesdb::AtomicPasteFSFile,
pub file: db::AtomicPasteFSFile,
pub auth_state: Option<bool>,
}
@ -34,7 +33,7 @@ struct NewProps {
#[derive(Default, Properties, PartialEq, serde::Deserialize)]
struct Props {
pub pastes: Vec<bundlesdb::PasteIdentifier>,
pub pastes: Vec<db::PasteIdentifier>,
pub auth_state: Option<bool>,
}
@ -105,10 +104,7 @@ fn build_dashboard_renderer_with_props(props: Props) -> ServerRenderer<Dashboard
#[get("/d/atomic")]
/// Available at "/d/atomic"
pub async fn dashboard_request(
req: HttpRequest,
data: web::Data<db::bundlesdb::AppData>,
) -> impl Responder {
pub async fn dashboard_request(req: HttpRequest, data: web::Data<db::AppData>) -> impl Responder {
// verify auth status
let token_cookie = req.cookie("__Secure-Token");
let mut set_cookie: &str = "";
@ -212,10 +208,7 @@ fn build_new_renderer_with_props(props: NewProps) -> ServerRenderer<CreateNew> {
#[get("/d/atomic/new")]
/// Available at "/d/atomic/new"
pub async fn new_request(
req: HttpRequest,
data: web::Data<db::bundlesdb::AppData>,
) -> impl Responder {
pub async fn new_request(req: HttpRequest, data: web::Data<db::AppData>) -> impl Responder {
// verify auth status
let token_cookie = req.cookie("__Secure-Token");
let mut set_cookie: &str = "";
@ -334,7 +327,7 @@ fn build_fs_renderer_with_props(props: FSProps) -> ServerRenderer<PasteFiles> {
/// Available at "/d/atomic/{id}"
pub async fn edit_request(
req: HttpRequest,
data: web::Data<db::bundlesdb::AppData>,
data: web::Data<db::AppData>,
info: web::Query<EditQueryProps>,
) -> impl Responder {
// verify auth status
@ -369,7 +362,7 @@ You can create an account at: /d/auth/register",
// get paste
let id: String = req.match_info().get("id").unwrap().to_string();
let paste: bundlesdb::DefaultReturn<Option<FullPaste<PasteMetadata, String>>> =
let paste: db::DefaultReturn<Option<FullPaste<PasteMetadata, String>>> =
data.db.get_paste_by_id(id).await;
if paste.success == false {
@ -391,7 +384,7 @@ You can create an account at: /d/auth/register",
}
// get file from path
let real_content = serde_json::from_str::<bundlesdb::AtomicPaste>(&unwrap.content);
let real_content = serde_json::from_str::<db::AtomicPaste>(&unwrap.content);
if real_content.is_err() {
return HttpResponse::NotAcceptable().body("Paste failed to deserialize");

View file

@ -6,7 +6,7 @@ use yew::ServerRenderer;
use crate::components::avatar::AvatarDisplay;
use crate::components::navigation::{Footer, GlobalMenu};
use crate::db::{self, bundlesdb};
use crate::db::{self, AppData};
use crate::utility::format_html;
#[derive(Default, Properties, PartialEq, serde::Deserialize)]
@ -19,21 +19,21 @@ struct Props {
#[derive(Default, Properties, PartialEq, serde::Deserialize)]
struct DashboardProps {
pub user: bundlesdb::UserState<String>,
pub user: db::UserState<String>,
pub has_unread_notification: bool,
pub auth_state: Option<bool>,
}
#[derive(Default, Properties, PartialEq, serde::Deserialize)]
struct NotificationsProps {
pub notifications: Vec<bundlesdb::Log>,
pub notifications: Vec<db::Log>,
pub offset: i32,
pub auth_state: Option<bool>,
}
#[derive(Default, Properties, PartialEq, serde::Deserialize)]
struct InboxProps {
pub boards: Vec<bundlesdb::BoardIdentifier>,
pub boards: Vec<db::BoardIdentifier>,
pub offset: i32,
pub auth_state: Option<bool>,
}
@ -218,7 +218,7 @@ fn build_renderer_with_props(props: Props) -> ServerRenderer<Home> {
/// Available at "/"
pub async fn home_request(
req: HttpRequest,
data: web::Data<db::bundlesdb::AppData>,
data: web::Data<AppData>,
info: web::Query<Props>,
) -> impl Responder {
// verify auth status
@ -488,10 +488,7 @@ fn build_dashboard_renderer_with_props(props: DashboardProps) -> ServerRenderer<
#[get("/d")]
/// Available at "/d"
pub async fn dashboard_request(
req: HttpRequest,
data: web::Data<db::bundlesdb::AppData>,
) -> impl Responder {
pub async fn dashboard_request(req: HttpRequest, data: web::Data<AppData>) -> impl Responder {
// verify auth status
let token_cookie = req.cookie("__Secure-Token");
let mut set_cookie: &str = "";
@ -591,7 +588,7 @@ fn Notifications(props: &NotificationsProps) -> Html {
<div class="flex g-4 flex-wrap">
{for props.notifications.iter().map(|n| {
let notif = serde_json::from_str::<bundlesdb::Notification>(&n.content).unwrap();
let notif = serde_json::from_str::<db::Notification>(&n.content).unwrap();
html! {
<a class="button secondary round full justify-start" href={notif.address} title={notif.content.clone()}>
@ -631,7 +628,7 @@ fn build_notifications_renderer_with_props(
/// Available at "/d/notifications"
pub async fn notifications_request(
req: HttpRequest,
data: web::Data<db::bundlesdb::AppData>,
data: web::Data<AppData>,
info: web::Query<crate::api::pastes::OffsetQueryProps>,
) -> impl Responder {
// verify auth status
@ -783,7 +780,7 @@ fn build_inbox_renderer_with_props(props: InboxProps) -> ServerRenderer<Inbox> {
/// Available at "/d/inbox"
pub async fn inbox_request(
req: HttpRequest,
data: web::Data<db::bundlesdb::AppData>,
data: web::Data<AppData>,
info: web::Query<crate::api::pastes::OffsetQueryProps>,
) -> impl Responder {
// verify auth status

View file

@ -5,9 +5,7 @@ use serde_json::json;
use yew::prelude::*;
use yew::ServerRenderer;
use crate::db::bundlesdb::{
self, AppData, FullPaste, FullUser, Paste, PasteMetadata, UserMetadata,
};
use crate::db::{self, AppData, FullPaste, FullUser, Paste, PasteMetadata, UserMetadata};
use crate::utility;
use crate::utility::format_html;
@ -28,7 +26,7 @@ pub struct PasteViewProps {
#[derive(Default, Properties, PartialEq, serde::Deserialize)]
struct DashboardProps {
pub pastes: Vec<bundlesdb::PasteIdentifier>,
pub pastes: Vec<db::PasteIdentifier>,
pub auth_state: Option<bool>,
pub offset: i32,
}
@ -204,7 +202,7 @@ pub async fn paste_view_request(
let url: String = req.match_info().get("url").unwrap().to_string();
let url_c = url.clone();
let paste: bundlesdb::DefaultReturn<Option<FullPaste<PasteMetadata, String>>> =
let paste: db::DefaultReturn<Option<FullPaste<PasteMetadata, String>>> =
data.db.get_paste_by_url(url).await;
if paste.success == false {
@ -265,7 +263,7 @@ pub async fn paste_view_request(
// handle atomic pastes (just return index.html)
if unwrap.paste.content.contains("\"_is_atomic\":true") {
let real_content = serde_json::from_str::<bundlesdb::AtomicPaste>(&unwrap.paste.content);
let real_content = serde_json::from_str::<db::AtomicPaste>(&unwrap.paste.content);
if real_content.is_err() {
return HttpResponse::NotAcceptable().body("Paste failed to deserialize");
@ -396,7 +394,7 @@ pub async fn atomic_paste_view_request(
let url: String = req.match_info().get("url").unwrap().to_string();
let path: String = req.match_info().get("path").unwrap().to_string();
let paste: bundlesdb::DefaultReturn<Option<FullPaste<PasteMetadata, String>>> =
let paste: db::DefaultReturn<Option<FullPaste<PasteMetadata, String>>> =
data.db.get_paste_by_url(url).await;
if paste.success == false {
@ -413,7 +411,7 @@ pub async fn atomic_paste_view_request(
// handle atomic pastes (just return index.html)
if unwrap.paste.content.contains("\"_is_atomic\":true") {
let real_content = serde_json::from_str::<bundlesdb::AtomicPaste>(&unwrap.paste.content);
let real_content = serde_json::from_str::<db::AtomicPaste>(&unwrap.paste.content);
if real_content.is_err() {
return HttpResponse::NotAcceptable().body("Paste failed to deserialize");
@ -526,7 +524,7 @@ fn build_dashboard_renderer_with_props(props: DashboardProps) -> ServerRenderer<
/// Available at "/d/pastes"
pub async fn dashboard_request(
req: HttpRequest,
data: web::Data<bundlesdb::AppData>,
data: web::Data<db::AppData>,
info: web::Query<crate::api::pastes::OffsetQueryProps>,
) -> impl Responder {
// verify auth status

View file

@ -4,7 +4,7 @@ use actix_web::{get, web, HttpRequest, Responder};
use yew::prelude::*;
use yew::ServerRenderer;
use crate::db::bundlesdb::{self, AppData, FullPaste, Paste, PasteMetadata};
use crate::db::{self, AppData, FullPaste, Paste, PasteMetadata};
use crate::utility::format_html;
use crate::components::navigation::Footer;
@ -151,7 +151,7 @@ pub async fn paste_settings_request(
let url: String = req.match_info().get("url").unwrap().to_string();
let url_c = url.clone();
let paste: bundlesdb::DefaultReturn<Option<FullPaste<PasteMetadata, String>>> =
let paste: db::DefaultReturn<Option<FullPaste<PasteMetadata, String>>> =
data.db.get_paste_by_url(url).await;
if paste.success == false {

View file

@ -5,8 +5,7 @@ use yew::prelude::*;
use yew::ServerRenderer;
use crate::components::navigation::{Footer, GlobalMenu};
use crate::db::bundlesdb::{DefaultReturn, FullUser};
use crate::db::{self, bundlesdb};
use crate::db::{self, DefaultReturn, FullUser};
use crate::utility::format_html;
use crate::api::pastes::OffsetQueryProps;
@ -19,7 +18,7 @@ struct DashboardProps {
#[derive(Default, Properties, PartialEq, serde::Deserialize)]
struct BoardsProps {
pub offset: i32,
pub posts: Vec<bundlesdb::Log>,
pub posts: Vec<db::Log>,
pub auth_state: Option<bool>,
}
@ -84,10 +83,7 @@ fn build_dashboard_renderer_with_props(props: DashboardProps) -> ServerRenderer<
#[get("/d/staff")]
/// Available at "/d/staff"
pub async fn dashboard_request(
req: HttpRequest,
data: web::Data<db::bundlesdb::AppData>,
) -> impl Responder {
pub async fn dashboard_request(req: HttpRequest, data: web::Data<db::AppData>) -> impl Responder {
// verify auth status
let token_cookie = req.cookie("__Secure-Token");
let mut set_cookie: &str = "";
@ -196,7 +192,7 @@ fn BoardsDashboard(props: &BoardsProps) -> Html {
<div class="card round secondary flex g-4 flex-column justify-center" id="boards_list">
{for props.posts.iter().map(|p| {
let post = serde_json::from_str::<bundlesdb::BoardPostLog>(&p.content).unwrap();
let post = serde_json::from_str::<db::BoardPostLog>(&p.content).unwrap();
html! {
<a class="button secondary round full justify-start" href={format!("::PUFFER_ROOT::/{}/posts/{}", &post.board, &p.id)}>
@ -228,7 +224,7 @@ fn build_boards_dashboard_renderer_with_props(
/// Available at "/d/staff/boards"
pub async fn staff_boards_dashboard_request(
req: HttpRequest,
data: web::Data<db::bundlesdb::AppData>,
data: web::Data<db::AppData>,
info: web::Query<OffsetQueryProps>,
) -> impl Responder {
// verify auth status
@ -272,7 +268,7 @@ You can create an account at: /d/auth/register",
}
// get posts
let posts: bundlesdb::DefaultReturn<Option<Vec<bundlesdb::Log>>> =
let posts: db::DefaultReturn<Option<Vec<db::Log>>> =
data.db.fetch_most_recent_posts(info.offset).await;
// ...
@ -398,7 +394,7 @@ fn build_users_dashboard_renderer_with_props(props: UsersProps) -> ServerRendere
/// Available at "/d/staff/users"
pub async fn staff_users_dashboard_request(
req: HttpRequest,
data: web::Data<db::bundlesdb::AppData>,
data: web::Data<db::AppData>,
info: web::Query<UsersQueryProps>,
) -> impl Responder {
// verify auth status
@ -442,7 +438,7 @@ You can create an account at: /d/auth/register",
}
// get user
let user: bundlesdb::DefaultReturn<Option<FullUser<String>>> = if info.username.is_some() {
let user: db::DefaultReturn<Option<FullUser<String>>> = if info.username.is_some() {
data.db
.get_user_by_username(info.username.as_ref().unwrap().to_owned())
.await