add: user follows, user blocks, ip bans

TODO: implement user following API endpoints
TODO: implement user blocking API endpoints
TODO: don't allow blocked users to interact with the users who blocked them
This commit is contained in:
trisua 2025-03-25 21:19:55 -04:00
parent 81005a6e1c
commit 559ce19932
25 changed files with 628 additions and 127 deletions

View file

@ -42,6 +42,11 @@ pub async fn register_request(
.unwrap_or("")
.to_string();
// check for ip ban
if let Ok(_) = data.get_ipban_by_ip(&real_ip).await {
return (None, Json(Error::NotAllowed.into()));
}
// ...
let mut user = User::new(props.username, props.password);
let (initial_token, t) = User::create_token(&real_ip);
@ -90,6 +95,11 @@ pub async fn login_request(
.unwrap_or("")
.to_string();
// check for ip ban
if let Ok(_) = data.get_ipban_by_ip(&real_ip).await {
return (None, Json(Error::NotAllowed.into()));
}
// verify password
let user = match data.get_user_by_username(&props.username).await {
Ok(ua) => ua,

View file

@ -1,19 +1,19 @@
use axum::{Extension, Json, extract::Path, response::IntoResponse};
use axum_extra::extract::CookieJar;
use tetratto_core::model::{ApiReturn, Error, journal::JournalPage};
use tetratto_core::model::{ApiReturn, Error, journal::Journal};
use crate::{
State, get_user_from_token,
routes::api::v1::{
CreateJournalPage, UpdateJournalPagePrompt, UpdateJournalPageReadAccess,
UpdateJournalPageTitle, UpdateJournalPageWriteAccess,
CreateJournal, UpdateJournalPrompt, UpdateJournalReadAccess, UpdateJournalTitle,
UpdateJournalWriteAccess,
},
};
pub async fn create_request(
jar: CookieJar,
Extension(data): Extension<State>,
Json(req): Json<CreateJournalPage>,
Json(req): Json<CreateJournal>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data) {
@ -22,7 +22,7 @@ pub async fn create_request(
};
match data
.create_page(JournalPage::new(req.title, req.prompt, user.id))
.create_page(Journal::new(req.title, req.prompt, user.id))
.await
{
Ok(_) => Json(ApiReturn {
@ -59,7 +59,7 @@ pub async fn update_title_request(
jar: CookieJar,
Extension(data): Extension<State>,
Path(id): Path<usize>,
Json(req): Json<UpdateJournalPageTitle>,
Json(req): Json<UpdateJournalTitle>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data) {
@ -81,7 +81,7 @@ pub async fn update_prompt_request(
jar: CookieJar,
Extension(data): Extension<State>,
Path(id): Path<usize>,
Json(req): Json<UpdateJournalPagePrompt>,
Json(req): Json<UpdateJournalPrompt>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data) {
@ -103,7 +103,7 @@ pub async fn update_read_access_request(
jar: CookieJar,
Extension(data): Extension<State>,
Path(id): Path<usize>,
Json(req): Json<UpdateJournalPageReadAccess>,
Json(req): Json<UpdateJournalReadAccess>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data) {
@ -125,7 +125,7 @@ pub async fn update_write_access_request(
jar: CookieJar,
Extension(data): Extension<State>,
Path(id): Path<usize>,
Json(req): Json<UpdateJournalPageWriteAccess>,
Json(req): Json<UpdateJournalWriteAccess>,
) -> impl IntoResponse {
let data = &(data.read().await).0;
let user = match get_user_from_token!(jar, data) {

View file

@ -1,2 +1,2 @@
pub mod entries;
pub mod pages;
pub mod journals;
pub mod posts;

View file

@ -1,6 +1,6 @@
use axum::{Extension, Json, extract::Path, response::IntoResponse};
use axum_extra::extract::CookieJar;
use tetratto_core::model::{ApiReturn, Error, journal::JournalEntry};
use tetratto_core::model::{ApiReturn, Error, journal::JournalPost};
use crate::{
State, get_user_from_token,
@ -19,7 +19,7 @@ pub async fn create_request(
};
match data
.create_entry(JournalEntry::new(req.content, req.journal, user.id))
.create_entry(JournalPost::new(req.content, req.journal, user.id))
.await
{
Ok(_) => Json(ApiReturn {
@ -64,7 +64,7 @@ pub async fn update_content_request(
None => return Json(Error::NotAllowed.into()),
};
match data.update_entry_content(id, user, req.content).await {
match data.update_post_content(id, user, req.content).await {
Ok(_) => Json(ApiReturn {
ok: true,
message: "Entry updated".to_string(),
@ -86,7 +86,7 @@ pub async fn update_context_request(
None => return Json(Error::NotAllowed.into()),
};
match data.update_entry_context(id, user, req.context).await {
match data.update_post_context(id, user, req.context).await {
Ok(_) => Json(ApiReturn {
ok: true,
message: "Entry updated".to_string(),

View file

@ -8,7 +8,7 @@ use axum::{
};
use serde::Deserialize;
use tetratto_core::model::{
journal::{JournalEntryContext, JournalPageReadAccess, JournalPageWriteAccess},
journal::{JournalPostContext, JournalReadAccess, JournalWriteAccess},
reactions::AssetType,
};
@ -18,35 +18,35 @@ pub fn routes() -> Router {
.route("/reactions", post(reactions::create_request))
.route("/reactions/{id}", get(reactions::get_request))
.route("/reactions/{id}", delete(reactions::delete_request))
// journal pages
.route("/pages", post(journal::pages::create_request))
.route("/pages/{id}", delete(journal::pages::delete_request))
// journal journals
.route("/journals", post(journal::journals::create_request))
.route("/journals/{id}", delete(journal::journals::delete_request))
.route(
"/pages/{id}/title",
post(journal::pages::update_title_request),
"/journals/{id}/title",
post(journal::journals::update_title_request),
)
.route(
"/pages/{id}/prompt",
post(journal::pages::update_prompt_request),
"/journals/{id}/prompt",
post(journal::journals::update_prompt_request),
)
.route(
"/pages/{id}/access/read",
post(journal::pages::update_read_access_request),
"/journals/{id}/access/read",
post(journal::journals::update_read_access_request),
)
.route(
"/pages/{id}/access/write",
post(journal::pages::update_write_access_request),
"/journals/{id}/access/write",
post(journal::journals::update_write_access_request),
)
// journal entries
.route("/entries", post(journal::entries::create_request))
.route("/entries/{id}", delete(journal::entries::delete_request))
// journal posts
.route("/posts", post(journal::posts::create_request))
.route("/posts/{id}", delete(journal::posts::delete_request))
.route(
"/entries/{id}/content",
post(journal::entries::update_content_request),
"/posts/{id}/content",
post(journal::posts::update_content_request),
)
.route(
"/entries/{id}/context",
post(journal::entries::update_context_request),
"/posts/{id}/context",
post(journal::posts::update_context_request),
)
// auth
// global
@ -79,29 +79,29 @@ pub struct AuthProps {
}
#[derive(Deserialize)]
pub struct CreateJournalPage {
pub struct CreateJournal {
pub title: String,
pub prompt: String,
}
#[derive(Deserialize)]
pub struct UpdateJournalPageTitle {
pub struct UpdateJournalTitle {
pub title: String,
}
#[derive(Deserialize)]
pub struct UpdateJournalPagePrompt {
pub struct UpdateJournalPrompt {
pub prompt: String,
}
#[derive(Deserialize)]
pub struct UpdateJournalPageReadAccess {
pub access: JournalPageReadAccess,
pub struct UpdateJournalReadAccess {
pub access: JournalReadAccess,
}
#[derive(Deserialize)]
pub struct UpdateJournalPageWriteAccess {
pub access: JournalPageWriteAccess,
pub struct UpdateJournalWriteAccess {
pub access: JournalWriteAccess,
}
#[derive(Deserialize)]
@ -117,7 +117,7 @@ pub struct UpdateJournalEntryContent {
#[derive(Deserialize)]
pub struct UpdateJournalEntryContext {
pub context: JournalEntryContext,
pub context: JournalPostContext,
}
#[derive(Deserialize)]