feat(servers): role and permission routes

This commit is contained in:
Paul Makles
2022-02-10 22:14:00 +00:00
parent 734dc2bb59
commit 9f1eda4af0
10 changed files with 306 additions and 60 deletions

View File

@@ -1,9 +1,11 @@
use std::collections::HashMap; use std::collections::HashMap;
use revolt_quark::{Error, Result}; use revolt_quark::{
models::{server::PartialServer, Channel, User},
perms, Db, Error, Ref, Result, ServerPermission,
};
use mongodb::bson::doc; use rocket::serde::json::Json;
use rocket::serde::json::{Json, Value};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ulid::Ulid; use ulid::Ulid;
use validator::Validate; use validator::Validate;
@@ -33,9 +35,74 @@ pub struct Data {
} }
#[post("/<target>/channels", data = "<info>")] #[post("/<target>/channels", data = "<info>")]
pub async fn req( pub async fn req(db: &Db, user: User, target: Ref, info: Json<Data>) -> Result<Json<Channel>> {
/*_idempotency: IdempotencyKey, user: User, target: Ref,*/ target: String, let info = info.into_inner();
info: Json<Data>, info.validate()
) -> Result<Value> { .map_err(|error| Error::FailedValidation { error })?;
todo!()
let server = target.as_server(db).await?;
if !perms(&user)
.server(&server)
.calc_server(db)
.await
.get_manage_channels()
{
return Err(Error::MissingPermission {
permission: ServerPermission::ManageChannels as i32,
});
}
let id = Ulid::new().to_string();
let mut channels = server.channels;
channels.push(id.clone());
let Data {
name,
description,
nsfw,
channel_type,
} = info;
let channel = match channel_type {
ChannelType::Text => Channel::TextChannel {
id,
server: server.id.clone(),
name,
description,
icon: None,
last_message_id: None,
default_permissions: None,
role_permissions: HashMap::new(),
nsfw: nsfw.unwrap_or(false),
},
ChannelType::Voice => Channel::VoiceChannel {
id,
server: server.id.clone(),
name,
description,
icon: None,
default_permissions: None,
role_permissions: HashMap::new(),
nsfw: nsfw.unwrap_or(false),
},
};
db.insert_channel(&channel).await?;
db.update_server(
&server.id,
&PartialServer {
channels: Some(channels),
..Default::default()
},
vec![],
)
.await?;
Ok(Json(channel))
} }

View File

@@ -1,8 +1,9 @@
use revolt_quark::{Error, Result}; use revolt_quark::{
models::{Invite, User},
perms, Db, Error, Ref, Result, ServerPermission,
};
use futures::StreamExt; use rocket::serde::json::Json;
use mongodb::bson::{doc, from_document};
use rocket::serde::json::Value;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
@@ -14,6 +15,18 @@ pub struct ServerInvite {
} }
#[get("/<target>/invites")] #[get("/<target>/invites")]
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<Value> { pub async fn req(db: &Db, user: User, target: Ref) -> Result<Json<Vec<Invite>>> {
todo!() let server = target.as_server(db).await?;
if !perms(&user)
.server(&server)
.calc_server(db)
.await
.get_manage_server()
{
return Err(Error::MissingPermission {
permission: ServerPermission::ManageServer as i32,
});
}
db.fetch_invites_for_server(&server.id).await.map(Json)
} }

View File

@@ -2,7 +2,7 @@ use mongodb::bson::doc;
use rocket::serde::json::Json; use rocket::serde::json::Json;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use revolt_quark::{EmptyResponse, Result}; use revolt_quark::{models::User, perms, Db, EmptyResponse, Error, Ref, Result};
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Values { pub struct Values {
@@ -17,9 +17,30 @@ pub struct Data {
#[put("/<target>/permissions/<role_id>", data = "<data>", rank = 2)] #[put("/<target>/permissions/<role_id>", data = "<data>", rank = 2)]
pub async fn req( pub async fn req(
/*user: UserRef, target: Ref,*/ target: String, db: &Db,
user: User,
target: Ref,
role_id: String, role_id: String,
data: Json<Data>, data: Json<Data>,
) -> Result<EmptyResponse> { ) -> Result<EmptyResponse> {
todo!() let server = target.as_server(db).await?;
if !perms(&user)
.server(&server)
.calc_server(db)
.await
.get_manage_roles()
{
return Err(Error::NotFound);
}
db.update_role_permission(
&server.id,
&role_id,
&(
data.permissions.server as i32,
data.permissions.channel as i32,
),
)
.await
.map(|_| EmptyResponse)
} }

View File

@@ -2,7 +2,10 @@ use mongodb::bson::doc;
use rocket::serde::json::Json; use rocket::serde::json::Json;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use revolt_quark::{EmptyResponse, Result}; use revolt_quark::{
models::{server::PartialServer, User},
perms, Db, EmptyResponse, Error, Ref, Result,
};
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Values { pub struct Values {
@@ -16,9 +19,30 @@ pub struct Data {
} }
#[put("/<target>/permissions/default", data = "<data>", rank = 1)] #[put("/<target>/permissions/default", data = "<data>", rank = 1)]
pub async fn req( pub async fn req(db: &Db, user: User, target: Ref, data: Json<Data>) -> Result<EmptyResponse> {
/*user: UserRef, target: Ref,*/ target: String, let data = data.into_inner();
data: Json<Data>,
) -> Result<EmptyResponse> { let server = target.as_server(db).await?;
todo!() if !perms(&user)
.server(&server)
.calc_server(db)
.await
.get_manage_roles()
{
return Err(Error::NotFound);
}
db.update_server(
&server.id,
&PartialServer {
default_permissions: Some((
data.permissions.server as i32,
data.permissions.channel as i32,
)),
..Default::default()
},
vec![],
)
.await
.map(|_| EmptyResponse)
} }

View File

@@ -1,6 +1,8 @@
use revolt_quark::{Error, Result}; use revolt_quark::{
models::{server::Role, User},
perms, Db, Error, Ref, Result, DEFAULT_PERMISSION_CHANNEL_SERVER, DEFAULT_SERVER_PERMISSION,
};
use mongodb::bson::doc;
use rocket::serde::json::{Json, Value}; use rocket::serde::json::{Json, Value};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ulid::Ulid; use ulid::Ulid;
@@ -13,9 +15,35 @@ pub struct Data {
} }
#[post("/<target>/roles", data = "<data>")] #[post("/<target>/roles", data = "<data>")]
pub async fn req( pub async fn req(db: &Db, user: User, target: Ref, data: Json<Data>) -> Result<Value> {
/*user: UserRef, target: Ref,*/ target: String, let data = data.into_inner();
data: Json<Data>, data.validate()
) -> Result<Value> { .map_err(|error| Error::FailedValidation { error })?;
todo!()
let server = target.as_server(db).await?;
if !perms(&user)
.server(&server)
.calc_server(db)
.await
.get_manage_roles()
{
return Err(Error::NotFound);
}
let role_id = Ulid::new().to_string();
db.insert_role(
&server.id,
&role_id,
&Role {
name: data.name,
permissions: (
*DEFAULT_SERVER_PERMISSION as i32,
*DEFAULT_PERMISSION_CHANNEL_SERVER as i32,
),
..Default::default()
},
)
.await?;
Ok(json!({ "id": role_id }))
} }

View File

@@ -1,9 +1,18 @@
use revolt_quark::{EmptyResponse, Result}; use revolt_quark::{models::User, perms, Db, EmptyResponse, Error, Ref, Result};
#[delete("/<target>/roles/<role_id>")] #[delete("/<target>/roles/<role_id>")]
pub async fn req( pub async fn req(db: &Db, user: User, target: Ref, role_id: String) -> Result<EmptyResponse> {
/*user: UserRef, target: Ref,*/ target: String, let server = target.as_server(db).await?;
role_id: String, if !perms(&user)
) -> Result<EmptyResponse> { .server(&server)
todo!() .calc_server(db)
.await
.get_manage_roles()
{
return Err(Error::NotFound);
}
db.delete_role(&server.id, &role_id)
.await
.map(|_| EmptyResponse)
} }

View File

@@ -1,6 +1,11 @@
use revolt_quark::{EmptyResponse, Result}; use revolt_quark::{
models::{
server::{FieldsRole, PartialRole, Role},
User,
},
perms, Db, Error, Ref, Result,
};
use mongodb::bson::doc;
use rocket::serde::json::Json; use rocket::serde::json::Json;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use validator::Validate; use validator::Validate;
@@ -13,15 +18,66 @@ pub struct Data {
colour: Option<String>, colour: Option<String>,
hoist: Option<bool>, hoist: Option<bool>,
rank: Option<i64>, rank: Option<i64>,
// #[validate(length(min = 1))] #[validate(length(min = 1))]
// remove: Option<Vec<FieldsRole>>, remove: Option<Vec<FieldsRole>>,
} }
#[patch("/<target>/roles/<role_id>", data = "<data>")] #[patch("/<target>/roles/<role_id>", data = "<data>")]
pub async fn req( pub async fn req(
/*user: UserRef, target: Ref,*/ target: String, db: &Db,
user: User,
target: Ref,
role_id: String, role_id: String,
data: Json<Data>, data: Json<Data>,
) -> Result<EmptyResponse> { ) -> Result<Json<Role>> {
todo!() let data = data.into_inner();
data.validate()
.map_err(|error| Error::FailedValidation { error })?;
let mut server = target.as_server(db).await?;
if !perms(&user)
.server(&server)
.calc_server(db)
.await
.get_manage_roles()
{
return Err(Error::NotFound);
}
if let Some(mut role) = server.roles.remove(&role_id) {
let Data {
name,
colour,
hoist,
rank,
remove,
} = data;
let partial = PartialRole {
name,
colour,
hoist,
rank,
..Default::default()
};
if let Some(remove) = &remove {
for field in remove {
role.remove(field);
}
}
db.update_role(
&server.id,
&role_id,
&partial,
remove.unwrap_or_else(Vec::new),
)
.await?;
role.apply_options(partial.clone());
Ok(Json(role))
} else {
Err(Error::NotFound)
}
} }

View File

@@ -1,6 +1,18 @@
use revolt_quark::{EmptyResponse, Result}; use revolt_quark::{models::User, perms, Db, EmptyResponse, Error, Ref, Result};
#[put("/<target>/ack")] #[put("/<target>/ack")]
pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result<EmptyResponse> { pub async fn req(db: &Db, user: User, target: Ref) -> Result<EmptyResponse> {
todo!() let server = target.as_server(db).await?;
if !perms(&user)
.server(&server)
.calc_server(db)
.await
.get_view()
{
return Err(Error::NotFound);
}
db.acknowledge_channels(&user.id, &server.channels)
.await
.map(|_| EmptyResponse)
} }

View File

@@ -1,9 +1,10 @@
use std::collections::HashMap;
use revolt_quark::{ use revolt_quark::{
models::{Server, User}, models::{Channel, Server, User},
Db, Error, Result, DEFAULT_PERMISSION_CHANNEL_SERVER, DEFAULT_SERVER_PERMISSION, Db, Error, Result, DEFAULT_PERMISSION_CHANNEL_SERVER, DEFAULT_SERVER_PERMISSION,
}; };
use mongodb::bson::doc;
use rocket::serde::json::Json; use rocket::serde::json::Json;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use ulid::Ulid; use ulid::Ulid;
@@ -38,11 +39,32 @@ pub async fn req(db: &Db, user: User, info: Json<Data>) -> Result<Json<Server>>
description, description,
nsfw, nsfw,
} = info; } = info;
let channel_id = Ulid::new().to_string();
let server_id = Ulid::new().to_string();
let channel = Channel::TextChannel {
id: channel_id.clone(),
server: server_id.clone(),
name: "General".into(),
description: None,
icon: None,
last_message_id: None,
default_permissions: None,
role_permissions: HashMap::new(),
nsfw: nsfw.unwrap_or(false),
};
let server = Server { let server = Server {
id: Ulid::new().to_string(), id: server_id,
owner: user.id,
name, name,
description, description,
channels: vec![channel_id],
nsfw: nsfw.unwrap_or(false), nsfw: nsfw.unwrap_or(false),
default_permissions: ( default_permissions: (
*DEFAULT_SERVER_PERMISSION as i32, *DEFAULT_SERVER_PERMISSION as i32,
@@ -51,6 +73,7 @@ pub async fn req(db: &Db, user: User, info: Json<Data>) -> Result<Json<Server>>
..Default::default() ..Default::default()
}; };
db.insert_channel(&channel).await?;
db.insert_server(&server).await?; db.insert_server(&server).await?;
Ok(Json(server)) Ok(Json(server))
} }

View File

@@ -1,23 +1,16 @@
use revolt_quark::{models::User, perms, Db, EmptyResponse, Error, Ref, Result}; use revolt_quark::{models::User, Db, EmptyResponse, Ref, Result};
use mongodb::bson::doc; use mongodb::bson::doc;
#[delete("/<target>")] #[delete("/<target>")]
pub async fn req(db: &Db, user: User, target: Ref) -> Result<EmptyResponse> { pub async fn req(db: &Db, user: User, target: Ref) -> Result<EmptyResponse> {
let server = target.as_server(db).await?; let server = target.as_server(db).await?;
if !perms(&user) let member = db.fetch_member(&target.id, &user.id).await?;
.server(&server)
.calc_server(db)
.await
.get_view()
{
return Err(Error::NotFound);
}
if server.owner == user.id { if server.owner == user.id {
db.delete_server(&server.id).await?; db.delete_server(&server.id).await?;
} else { } else {
db.delete_member(&server.id, &user.id).await?; db.delete_member(&member.id).await?;
} }
Ok(EmptyResponse) Ok(EmptyResponse)