forked from jmug/stoatchat
feat(users): implement fetch self / user, open dm
This commit is contained in:
@@ -1,25 +1,26 @@
|
|||||||
use revolt_quark::{EmptyResponse, Result};
|
use revolt_quark::{Error, EmptyResponse, Result, models::User, Database};
|
||||||
use crate::util::regex::RE_USERNAME;
|
use crate::util::regex::RE_USERNAME;
|
||||||
use mongodb::bson::doc;
|
use mongodb::bson::doc;
|
||||||
use rauth::entities::Account;
|
use rauth::entities::Account;
|
||||||
use rocket::serde::json::Json;
|
use rocket::{serde::json::Json, State};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
#[derive(Validate, Serialize, Deserialize)]
|
#[derive(Validate, Serialize, Deserialize)]
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
#[validate(length(min = 2, max = 32), regex = "RE_USERNAME")]
|
#[validate(length(min = 2, max = 32), regex = "RE_USERNAME")]
|
||||||
username: Option<String>,
|
username: String,
|
||||||
#[validate(length(min = 8, max = 1024))]
|
#[validate(length(min = 8, max = 1024))]
|
||||||
password: String,
|
password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[patch("/<_ignore_id>/username", data = "<data>")]
|
#[patch("/@me/username", data = "<data>")]
|
||||||
pub async fn req(
|
pub async fn req(
|
||||||
|
db: &State<Database>,
|
||||||
account: Account,
|
account: Account,
|
||||||
//user: UserRef,
|
user: User,
|
||||||
data: Json<Data>,
|
data: Json<Data>,
|
||||||
_ignore_id: String,
|
|
||||||
) -> Result<EmptyResponse> {
|
) -> Result<EmptyResponse> {
|
||||||
todo!()
|
account.verify_password(&data.password).map_err(|_| Error::InvalidCredentials)?;
|
||||||
|
user.update_username(db, &data.username).await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
use revolt_quark::{Error, Result};
|
|
||||||
|
|
||||||
use rocket::serde::json::Value;
|
|
||||||
|
|
||||||
#[get("/<target>/relationship")]
|
|
||||||
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<Value> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
use revolt_quark::{Error, Result};
|
|
||||||
|
|
||||||
use rocket::serde::json::Value;
|
|
||||||
|
|
||||||
#[get("/relationships")]
|
|
||||||
pub async fn req(/*user: UserRef*/) -> Result<Value> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
//! Fetch the currently authenticated session's user account
|
||||||
|
|
||||||
use revolt_quark::Result;
|
use revolt_quark::Result;
|
||||||
use revolt_quark::models::User;
|
use revolt_quark::models::User;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,19 @@
|
|||||||
use revolt_quark::{Ref, Result, models::User};
|
//! Fetch another user
|
||||||
|
//!
|
||||||
|
//! Will fail if the authenticated user does not
|
||||||
|
//! have permission to access the other user.
|
||||||
|
|
||||||
use rocket::serde::json::Value;
|
use revolt_quark::{Ref, Result, Error, models::User, perms, Database};
|
||||||
|
|
||||||
|
use rocket::{serde::json::Json, State};
|
||||||
|
|
||||||
#[get("/<target>")]
|
#[get("/<target>")]
|
||||||
pub async fn req(user: User, target: Ref) -> Result<Value> {
|
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Json<User>> {
|
||||||
todo!()
|
let target = target.as_user(db).await?;
|
||||||
|
|
||||||
|
if perms(&user).user(&target).calc_user(db).await.get_access() {
|
||||||
|
Ok(Json(target))
|
||||||
|
} else {
|
||||||
|
Err(Error::NotFound)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use std::path::Path;
|
|||||||
|
|
||||||
pub struct CachedFile(NamedFile);
|
pub struct CachedFile(NamedFile);
|
||||||
|
|
||||||
pub static CACHE_CONTROL: &'static str = "public, max-age=31536000, immutable";
|
pub static CACHE_CONTROL: &str = "public, max-age=31536000, immutable";
|
||||||
|
|
||||||
impl<'r> Responder<'r, 'static> for CachedFile {
|
impl<'r> Responder<'r, 'static> for CachedFile {
|
||||||
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
|
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> {
|
||||||
@@ -19,22 +19,22 @@ impl<'r> Responder<'r, 'static> for CachedFile {
|
|||||||
pub async fn req(target: String) -> Option<CachedFile> {
|
pub async fn req(target: String) -> Option<CachedFile> {
|
||||||
match target.chars().nth(25).unwrap() {
|
match target.chars().nth(25).unwrap() {
|
||||||
'0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' => {
|
'0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' => {
|
||||||
NamedFile::open(Path::new("assets/user_red.png")).await.ok().map(|n| CachedFile(n))
|
NamedFile::open(Path::new("assets/user_red.png")).await.ok().map(CachedFile)
|
||||||
}
|
}
|
||||||
'8' | '9' | 'A' | 'C' | 'B' | 'D' | 'E' | 'F' => {
|
'8' | '9' | 'A' | 'C' | 'B' | 'D' | 'E' | 'F' => {
|
||||||
NamedFile::open(Path::new("assets/user_green.png"))
|
NamedFile::open(Path::new("assets/user_green.png"))
|
||||||
.await
|
.await
|
||||||
.ok().map(|n| CachedFile(n))
|
.ok().map(CachedFile)
|
||||||
}
|
}
|
||||||
'G' | 'H' | 'J' | 'K' | 'M' | 'N' | 'P' | 'Q' => {
|
'G' | 'H' | 'J' | 'K' | 'M' | 'N' | 'P' | 'Q' => {
|
||||||
NamedFile::open(Path::new("assets/user_blue.png"))
|
NamedFile::open(Path::new("assets/user_blue.png"))
|
||||||
.await
|
.await
|
||||||
.ok().map(|n| CachedFile(n))
|
.ok().map(CachedFile)
|
||||||
}
|
}
|
||||||
'R' | 'S' | 'T' | 'V' | 'W' | 'X' | 'Y' | 'Z' => {
|
'R' | 'S' | 'T' | 'V' | 'W' | 'X' | 'Y' | 'Z' => {
|
||||||
NamedFile::open(Path::new("assets/user_yellow.png"))
|
NamedFile::open(Path::new("assets/user_yellow.png"))
|
||||||
.await
|
.await
|
||||||
.ok().map(|n| CachedFile(n))
|
.ok().map(CachedFile)
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ mod change_username;
|
|||||||
mod edit_user;
|
mod edit_user;
|
||||||
mod fetch_dms;
|
mod fetch_dms;
|
||||||
mod fetch_profile;
|
mod fetch_profile;
|
||||||
mod fetch_relationship;
|
|
||||||
mod fetch_relationships;
|
|
||||||
mod fetch_user;
|
mod fetch_user;
|
||||||
mod find_mutual;
|
mod find_mutual;
|
||||||
mod get_default_avatar;
|
mod get_default_avatar;
|
||||||
@@ -30,8 +28,6 @@ pub fn routes() -> Vec<Route> {
|
|||||||
open_dm::req,
|
open_dm::req,
|
||||||
// Relationships
|
// Relationships
|
||||||
find_mutual::req,
|
find_mutual::req,
|
||||||
fetch_relationships::req,
|
|
||||||
fetch_relationship::req,
|
|
||||||
add_friend::req,
|
add_friend::req,
|
||||||
remove_friend::req,
|
remove_friend::req,
|
||||||
block_user::req,
|
block_user::req,
|
||||||
|
|||||||
@@ -1,10 +1,31 @@
|
|||||||
use revolt_quark::{Error, Result};
|
//! Open a direct message with another user
|
||||||
|
|
||||||
|
use revolt_quark::{Error, Result, Ref, models::{User, Channel}, Database, perms, UserPermission};
|
||||||
|
|
||||||
use mongodb::bson::doc;
|
use mongodb::bson::doc;
|
||||||
use rocket::serde::json::Value;
|
use rocket::{State, serde::json::Json};
|
||||||
use ulid::Ulid;
|
use ulid::Ulid;
|
||||||
|
|
||||||
#[get("/<target>/dm")]
|
#[get("/<target>/dm")]
|
||||||
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<Value> {
|
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Json<Channel>> {
|
||||||
todo!()
|
let target = target.as_user(db).await?;
|
||||||
|
|
||||||
|
if let Ok(channel) = db.find_direct_message_channel(&user.id, &target.id).await {
|
||||||
|
Ok(Json(channel))
|
||||||
|
} else if perms(&user).user(&target).calc_user(db).await.get_send_message() {
|
||||||
|
let new_channel = Channel::DirectMessage {
|
||||||
|
id: Ulid::new().to_string(),
|
||||||
|
active: false,
|
||||||
|
recipients: vec! [
|
||||||
|
user.id.clone(),
|
||||||
|
target.id.clone()
|
||||||
|
],
|
||||||
|
last_message_id: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
db.insert_channel(&new_channel).await?;
|
||||||
|
Ok(Json(new_channel))
|
||||||
|
} else {
|
||||||
|
Error::from_permission(UserPermission::SendMessage)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user