Fix login loop and add documentation

This commit is contained in:
Jackzie 2025-04-16 17:05:41 -05:00
parent 6ffa89a936
commit bf2a87d746
8 changed files with 112 additions and 10 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
**/.idea
target
config
.env

2
Cargo.lock generated
View file

@ -2356,7 +2356,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "storage-app"
name = "storage_app"
version = "0.1.0"
dependencies = [
"anyhow",

View file

@ -1,5 +1,5 @@
[package]
name = "storage-app"
name = "storage_app"
version = "0.1.0"
edition = "2024"
repository = "https://github.com/jackzmc/storage"

59
README.md Normal file
View file

@ -0,0 +1,59 @@
# storage-app
## Overview
This project takes heavily inspiration from [Seafile](https://www.seafile.com/) in its functionality and UI design. File hosting service with performance, ease of use, and being lightweight.
Key features include:
- Web UI for managing files, with minimal/no client-side javascript
- Multiple storage backends supported (local filesystem, S3, etc)
- Multiple libraries per user, each with configurable storage backends
- WebDAV (soon)
## Getting Started
### Prerequisites
- Rust 1.86+ (stable) and Cargo
- PostgreSQL 13+ database
- 512MB RAM minimum
### Installing
```bash
# Clone the repository
git clone https://github.com/jackzmc/storage.git
cd storage
# Configure your database (create .env file with your PostgreSQL connection)
echo "DATABASE_URL=postgres://username:password@localhost" > .env
# Build the project
cargo build --release
# Run database migrations
#cargo run --bin migrate --features migrations
# Run the server
cargo run --release
```
## Roadmap
* [ ] WebDAV Support
* [ ] S3 backend support
* [ ] Administration panel
* [ ] Add storage backends
* [ ] Manage users
* [ ] Change app settings
* [ ] Email support (for password resets, user invites)
## Documentation
Todo, will be available at https://git.jackz.me/jackz/storage/wiki
# License
Available under the AGPL-3.0 license. [LICENSE](LICENSE)

36
migrations/default.sql Normal file
View file

@ -0,0 +1,36 @@
create table libraries
(
owner_id uuid not null
constraint libraries_owner_id
references users
on update cascade on delete cascade,
created_at timestamp default now() not null,
name varchar(255) not null,
repo_id varchar(64) not null
constraint libraries_repo_id
references repos
on update cascade on delete cascade,
id uuid not null
constraint libraries_pk
primary key
);
create table repos
(
id varchar(64) not null
primary key,
created_at timestamp default now() not null,
storage_type varchar(32) not null,
storage_settings json not null,
flags smallint default 0 not null
);
create table users
(
id uuid not null
primary key,
created_at timestamp default now() not null,
name varchar(255) not null,
password varchar(128),
email varchar(128) not null,
username varchar(64) not null
);

View file

@ -142,8 +142,10 @@ async fn rocket() -> _ {
ui::auth::forgot_password::page, ui::auth::forgot_password::handler,
])
.mount("/", routes![
ui::help::about,
ui::user::index, ui::user::redirect_list_library_files, ui::user::list_library_files, ui::user::get_library_file,
])
.mount("/", routes![
ui::help::about,
ui::help::test_get
])
.register("/api", catchers![

View file

@ -1,5 +1,5 @@
use std::net::IpAddr;
use log::debug;
use log::{debug, trace};
use rocket::{get, post, FromForm, Responder, Route, State};
use rocket::form::{Context, Contextual, Form};
use rocket::http::{Header, Status};
@ -59,8 +59,10 @@ pub async fn handler(
mut form: Form<Contextual<'_, LoginForm<'_>>>,
return_to: Option<String>,
) -> Result<HackyRedirectBecauseRocketBug, Template> {
trace!("handler");
validate_csrf_form(&mut form.context, &session).await;
let user = validate_user_form(&mut form.context, &pool).await;
trace!("check form");
if form.context.status() == Status::Ok {
if let Some(submission) = &form.value {
session.set(SessionData {
@ -70,17 +72,19 @@ pub async fn handler(
ip_address: ip_addr,
}),
}).await.unwrap();
debug!("returning user to {:?}", return_to);
let return_to_path = return_to.unwrap_or("/".to_string());
let mut return_to_path = return_to.unwrap_or("/".to_string());
if return_to_path == "" { return_to_path.push_str("/"); }
debug!("returning user to {:?}", return_to_path);
// Rocket redirect fails when `Redirect::to("/path/ has spaces")` has spaces, so manually do location... works better
return Ok(HackyRedirectBecauseRocketBug {
inner: "Login successful, redirecting...".to_string(),
location: Header::new("Location", return_to_path),
})
// let return_to_uri = Uri::parse::<Origin>(&return_to_path).unwrap_or(Uri::parse::<Origin>("/").unwrap());
// return Ok(Redirect::found(return_to_uri))
}
trace!("submission failed");
}
trace!("form failed");
let csrf_token = set_csrf(&session).await;
let ctx = context! {

View file

@ -25,7 +25,7 @@ pub(crate) fn setup_logger() {
tracing_subscriber::registry()
.with(
tracing_subscriber::filter::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| format!("warn,rocket=warn,storage_server=trace").into()),
.unwrap_or_else(|_| format!("warn,rocket=warn,{}=trace", env!("CARGO_PKG_NAME")).into()),
)
.with(tracing_subscriber::fmt::layer())
.init();