Compare commits
No commits in common. "wip/auditlog" and "main" have entirely different histories.
wip/auditl
...
main
16 changed files with 36 additions and 251 deletions
|
@ -1,2 +0,0 @@
|
|||
-- This file should undo anything in `up.sql`
|
||||
DROP TABLE audit_logs;
|
|
@ -1,14 +0,0 @@
|
|||
-- Your SQL goes here
|
||||
CREATE TABLE audit_logs (
|
||||
uuid UUID PRIMARY KEY NOT NULL,
|
||||
guild_uuid UUID NOT NULL,
|
||||
action_id INT2 NOT NULL,
|
||||
by_uuid UUID NOT NULL REFERENCES guild_members(uuid),
|
||||
channel_uuid UUID REFERENCES channels(uuid) DEFAULT NULL,
|
||||
user_uuid UUID REFERENCES users(uuid) DEFAULT NULL,
|
||||
message_uuid UUID REFERENCES messages(uuid) DEFAULT NULL,
|
||||
role_uuid UUID REFERENCES roles(uuid) DEFAULT NULL,
|
||||
audit_message VARCHAR(200) DEFAULT NULL,
|
||||
changed_from VARCHAR(200) DEFAULT NULL,
|
||||
changed_to VARCHAR(200) DEFAULT NULL
|
||||
);
|
|
@ -6,7 +6,11 @@ pub mod socket;
|
|||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
api::v1::auth::CurrentUser, error::Error, objects::{AuditLog, AuditLogId, Channel, Member, Permissions}, utils::global_checks, AppState
|
||||
AppState,
|
||||
api::v1::auth::CurrentUser,
|
||||
error::Error,
|
||||
objects::{Channel, Member, Permissions},
|
||||
utils::global_checks,
|
||||
};
|
||||
use axum::{
|
||||
Extension, Json,
|
||||
|
@ -51,9 +55,7 @@ pub async fn delete(
|
|||
.check_permission(&mut conn, &app_state.cache_pool, Permissions::ManageChannel)
|
||||
.await?;
|
||||
|
||||
let log_entry = AuditLog::new(channel.guild_uuid, AuditLogId::ChannelDelete as i16, member.uuid, None, None, None, None, Some(channel.name.clone()), None, None).await;
|
||||
channel.delete(&mut conn, &app_state.cache_pool).await?;
|
||||
log_entry.push(&mut conn).await?;
|
||||
|
||||
Ok(StatusCode::OK)
|
||||
}
|
||||
|
@ -115,15 +117,12 @@ pub async fn patch(
|
|||
.await?;
|
||||
|
||||
if let Some(new_name) = &new_info.name {
|
||||
let log_entry = AuditLog::new(channel.guild_uuid, AuditLogId::ChannelUpdateName as i16, member.uuid, Some(channel_uuid), None, None, None, None, Some(channel.name.clone()), Some(new_name.clone())).await;
|
||||
channel
|
||||
.set_name(&mut conn, &app_state.cache_pool, new_name.to_string())
|
||||
.await?;
|
||||
log_entry.push(&mut conn).await?;
|
||||
}
|
||||
|
||||
if let Some(new_description) = &new_info.description {
|
||||
let log_entry = AuditLog::new(channel.guild_uuid, AuditLogId::ChannelUpdateDescripiton as i16, member.uuid, Some(channel_uuid), None, None, None, None, Some(channel.description.clone().unwrap_or("".to_string())), Some(new_description.clone())).await;
|
||||
channel
|
||||
.set_description(
|
||||
&mut conn,
|
||||
|
@ -131,7 +130,6 @@ pub async fn patch(
|
|||
new_description.to_string(),
|
||||
)
|
||||
.await?;
|
||||
log_entry.push(&mut conn).await?;
|
||||
}
|
||||
|
||||
if let Some(new_is_above) = &new_info.is_above {
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use ::uuid::Uuid;
|
||||
use axum::{
|
||||
Extension, Json,
|
||||
extract::{Path, Query, State},
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
AppState,
|
||||
api::v1::auth::CurrentUser,
|
||||
error::Error,
|
||||
objects::{AuditLog, Member, PaginationRequest, Permissions},
|
||||
utils::global_checks,
|
||||
};
|
||||
|
||||
pub async fn get(
|
||||
State(app_state): State<Arc<AppState>>,
|
||||
Path(guild_uuid): Path<Uuid>,
|
||||
Query(pagination): Query<PaginationRequest>,
|
||||
Extension(CurrentUser(uuid)): Extension<CurrentUser<Uuid>>,
|
||||
) -> Result<impl IntoResponse, Error> {
|
||||
let mut conn = app_state.pool.get().await?;
|
||||
|
||||
global_checks(&mut conn, &app_state.config, uuid).await?;
|
||||
|
||||
let caller = Member::check_membership(&mut conn, uuid, guild_uuid).await?;
|
||||
caller
|
||||
.check_permission(&mut conn, &app_state.cache_pool, Permissions::ManageGuild)
|
||||
.await?;
|
||||
|
||||
let logs = AuditLog::fetch_page(&mut conn, guild_uuid, pagination).await?;
|
||||
|
||||
Ok((StatusCode::OK, Json(logs)))
|
||||
}
|
|
@ -9,7 +9,11 @@ use axum::{
|
|||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
api::v1::auth::CurrentUser, error::Error, objects::{AuditLog, AuditLogId, GuildBan, Member, Permissions}, utils::global_checks, AppState
|
||||
AppState,
|
||||
api::v1::auth::CurrentUser,
|
||||
error::Error,
|
||||
objects::{GuildBan, Member, Permissions},
|
||||
utils::global_checks,
|
||||
};
|
||||
|
||||
pub async fn get(
|
||||
|
@ -47,9 +51,7 @@ pub async fn unban(
|
|||
|
||||
let ban = GuildBan::fetch_one(&mut conn, guild_uuid, user_uuid).await?;
|
||||
|
||||
let log_entry = AuditLog::new(guild_uuid, AuditLogId::MemberUnban as i16, caller.uuid, None, Some(ban.user_uuid), None, None, None, None, None).await;
|
||||
ban.unban(&mut conn).await?;
|
||||
log_entry.push(&mut conn).await?;
|
||||
|
||||
Ok(StatusCode::OK)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,11 @@ use axum::{
|
|||
use serde::Deserialize;
|
||||
|
||||
use crate::{
|
||||
api::v1::auth::CurrentUser, error::Error, objects::{AuditLog, AuditLogId, Channel, Member, Permissions}, utils::{global_checks, order_by_is_above, CacheFns}, AppState
|
||||
AppState,
|
||||
api::v1::auth::CurrentUser,
|
||||
error::Error,
|
||||
objects::{Channel, Member, Permissions},
|
||||
utils::{CacheFns, global_checks, order_by_is_above},
|
||||
};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -79,7 +83,5 @@ pub async fn create(
|
|||
)
|
||||
.await?;
|
||||
|
||||
AuditLog::new(guild_uuid, AuditLogId::ChannelCreate as i16, member.uuid, Some(channel.uuid), None, None, None, Some(channel.name.clone()), None, None).await.push(&mut conn).await?;
|
||||
|
||||
Ok((StatusCode::OK, Json(channel)))
|
||||
}
|
||||
|
|
|
@ -10,7 +10,11 @@ use serde::Deserialize;
|
|||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
api::v1::auth::CurrentUser, error::Error, objects::{AuditLog, AuditLogId, Guild, Member, Permissions}, utils::global_checks, AppState
|
||||
AppState,
|
||||
api::v1::auth::CurrentUser,
|
||||
error::Error,
|
||||
objects::{Guild, Member, Permissions},
|
||||
utils::global_checks,
|
||||
};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -58,7 +62,5 @@ pub async fn create(
|
|||
.create_invite(&mut conn, uuid, invite_request.custom_id.clone())
|
||||
.await?;
|
||||
|
||||
AuditLog::new(guild_uuid, AuditLogId::InviteCreate as i16, member.uuid, None, None, None, None, Some(invite.id.clone()), None, None).await.push(&mut conn).await?;
|
||||
|
||||
Ok((StatusCode::OK, Json(invite)))
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ use axum::{
|
|||
use bytes::Bytes;
|
||||
use uuid::Uuid;
|
||||
|
||||
mod auditlogs;
|
||||
mod bans;
|
||||
mod channels;
|
||||
mod invites;
|
||||
|
@ -47,8 +46,6 @@ pub fn router() -> Router<Arc<AppState>> {
|
|||
// Bans
|
||||
.route("/bans", get(bans::get))
|
||||
.route("/bans/{uuid}", delete(bans::unban))
|
||||
// Audit Logs
|
||||
.route("/auditlogs", get(auditlogs::get))
|
||||
}
|
||||
|
||||
/// `GET /api/v1/guilds/{uuid}` DESCRIPTION
|
||||
|
|
|
@ -10,7 +10,11 @@ use axum::{
|
|||
use serde::Deserialize;
|
||||
|
||||
use crate::{
|
||||
api::v1::auth::CurrentUser, error::Error, objects::{AuditLog, AuditLogId, Member, Permissions, Role}, utils::{global_checks, order_by_is_above, CacheFns}, AppState
|
||||
AppState,
|
||||
api::v1::auth::CurrentUser,
|
||||
error::Error,
|
||||
objects::{Member, Permissions, Role},
|
||||
utils::{CacheFns, global_checks, order_by_is_above},
|
||||
};
|
||||
|
||||
pub mod uuid;
|
||||
|
@ -67,10 +71,7 @@ pub async fn create(
|
|||
.check_permission(&mut conn, &app_state.cache_pool, Permissions::ManageRole)
|
||||
.await?;
|
||||
|
||||
// TODO: roles permission
|
||||
let role = Role::new(&mut conn, guild_uuid, role_info.name.clone()).await?;
|
||||
|
||||
AuditLog::new(guild_uuid, AuditLogId::RoleCreate as i16, member.uuid, None, None, None, Some(role.uuid), Some(role_info.name.clone()) , None, None).await.push(&mut conn).await?;
|
||||
|
||||
Ok((StatusCode::OK, Json(role)).into_response())
|
||||
}
|
||||
|
|
|
@ -9,7 +9,11 @@ use axum::{
|
|||
use serde::Deserialize;
|
||||
|
||||
use crate::{
|
||||
api::v1::auth::CurrentUser, error::Error, objects::{AuditLog, AuditLogId, Member, Permissions}, utils::global_checks, AppState
|
||||
AppState,
|
||||
api::v1::auth::CurrentUser,
|
||||
error::Error,
|
||||
objects::{Member, Permissions},
|
||||
utils::global_checks,
|
||||
};
|
||||
|
||||
use uuid::Uuid;
|
||||
|
@ -38,9 +42,7 @@ pub async fn post(
|
|||
.check_permission(&mut conn, &app_state.cache_pool, Permissions::BanMember)
|
||||
.await?;
|
||||
|
||||
let log_entry = AuditLog::new(member.guild_uuid, AuditLogId::MemberBan as i16, caller.uuid, None, Some(member.user_uuid), None, None, Some(payload.reason.clone()), None, None).await;
|
||||
member.ban(&mut conn, &payload.reason).await?;
|
||||
log_entry.push(&mut conn).await?;
|
||||
|
||||
Ok(StatusCode::OK)
|
||||
}
|
||||
|
|
|
@ -54,9 +54,9 @@ pub async fn delete(
|
|||
Member::fetch_one_with_uuid(&mut conn, &app_state.cache_pool, Some(&me), member_uuid)
|
||||
.await?;
|
||||
|
||||
let caller = Member::check_membership(&mut conn, uuid, member.guild_uuid).await?;
|
||||
let deleter = Member::check_membership(&mut conn, uuid, member.guild_uuid).await?;
|
||||
|
||||
caller
|
||||
deleter
|
||||
.check_permission(&mut conn, &app_state.cache_pool, Permissions::KickMember)
|
||||
.await?;
|
||||
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
use crate::{
|
||||
Conn,
|
||||
error::Error,
|
||||
objects::{Pagination, PaginationRequest, load_or_empty},
|
||||
schema::audit_logs,
|
||||
};
|
||||
use diesel::{
|
||||
ExpressionMethods, Insertable, QueryDsl, Queryable, Selectable, SelectableHelper, insert_into,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
pub enum AuditLogId {
|
||||
MessageDelete = 100,
|
||||
MessageEdit = 101,
|
||||
|
||||
ChannelCreate = 200,
|
||||
ChannelDelete = 201,
|
||||
ChannelUpdateName = 202,
|
||||
ChannelUpdateDescripiton = 203,
|
||||
|
||||
RoleCreate = 300,
|
||||
RoleDelete = 301,
|
||||
RoleUpdateName = 302,
|
||||
RoleUpdatePermission = 303,
|
||||
InviteCreate = 304,
|
||||
InviteDelete = 305,
|
||||
|
||||
MemberKick = 400,
|
||||
MemberBan = 401,
|
||||
MemberUnban = 402,
|
||||
MemberUpdateNickname = 403,
|
||||
MemberUpdateRoles = 404,
|
||||
}
|
||||
|
||||
#[derive(Insertable, Selectable, Queryable, Serialize, Deserialize, Clone)]
|
||||
#[diesel(table_name = audit_logs)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct AuditLog {
|
||||
pub uuid: Uuid,
|
||||
pub guild_uuid: Uuid,
|
||||
pub action_id: i16,
|
||||
pub by_uuid: Uuid,
|
||||
pub channel_uuid: Option<Uuid>,
|
||||
pub user_uuid: Option<Uuid>,
|
||||
pub message_uuid: Option<Uuid>,
|
||||
pub role_uuid: Option<Uuid>,
|
||||
pub audit_message: Option<String>,
|
||||
pub changed_from: Option<String>,
|
||||
pub changed_to: Option<String>,
|
||||
}
|
||||
|
||||
impl AuditLog {
|
||||
pub async fn count(conn: &mut Conn, guild_uuid: Uuid) -> Result<i64, Error> {
|
||||
use audit_logs::dsl;
|
||||
let count: i64 = dsl::audit_logs
|
||||
.filter(dsl::guild_uuid.eq(guild_uuid))
|
||||
.count()
|
||||
.get_result(conn)
|
||||
.await?;
|
||||
|
||||
Ok(count)
|
||||
}
|
||||
pub async fn fetch_page(
|
||||
conn: &mut Conn,
|
||||
guild_uuid: Uuid,
|
||||
pagination: PaginationRequest,
|
||||
) -> Result<Pagination<AuditLog>, Error> {
|
||||
// TODO: Maybe add cache, but I do not know how
|
||||
let per_page = pagination.per_page.unwrap_or(20);
|
||||
let offset = (pagination.page - 1) * per_page;
|
||||
|
||||
if !(10..=100).contains(&per_page) {
|
||||
return Err(Error::BadRequest(
|
||||
"Invalid amount per page requested".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
use audit_logs::dsl;
|
||||
let logs: Vec<AuditLog> = load_or_empty(
|
||||
dsl::audit_logs
|
||||
.filter(dsl::guild_uuid.eq(guild_uuid))
|
||||
.limit(per_page.into())
|
||||
.offset(offset as i64)
|
||||
.select(AuditLog::as_select())
|
||||
.load(conn)
|
||||
.await,
|
||||
)?;
|
||||
|
||||
let pages = (AuditLog::count(conn, guild_uuid).await? as f32 / per_page as f32).ceil();
|
||||
|
||||
let paginated_logs = Pagination::<AuditLog> {
|
||||
objects: logs.clone(),
|
||||
amount: logs.len() as i32,
|
||||
pages: pages as i32,
|
||||
page: pagination.page,
|
||||
};
|
||||
|
||||
Ok(paginated_logs)
|
||||
}
|
||||
|
||||
pub async fn new(
|
||||
guild_uuid: Uuid,
|
||||
action_id: i16,
|
||||
by_uuid: Uuid,
|
||||
channel_uuid: Option<Uuid>,
|
||||
user_uuid: Option<Uuid>,
|
||||
message_uuid: Option<Uuid>,
|
||||
role_uuid: Option<Uuid>,
|
||||
audit_message: Option<String>,
|
||||
changed_from: Option<String>,
|
||||
changed_to: Option<String>,
|
||||
) -> AuditLog{
|
||||
AuditLog {
|
||||
uuid: Uuid::now_v7(),
|
||||
guild_uuid,
|
||||
action_id,
|
||||
by_uuid,
|
||||
channel_uuid,
|
||||
user_uuid,
|
||||
message_uuid,
|
||||
role_uuid,
|
||||
audit_message,
|
||||
changed_from,
|
||||
changed_to,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn push(self, conn: &mut Conn) -> Result<(), Error>{
|
||||
insert_into(audit_logs::table)
|
||||
.values(self.clone())
|
||||
.execute(conn)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -52,8 +52,8 @@ impl ChannelBuilder {
|
|||
pub struct Channel {
|
||||
pub uuid: Uuid,
|
||||
pub guild_uuid: Uuid,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
name: String,
|
||||
description: Option<String>,
|
||||
pub is_above: Option<Uuid>,
|
||||
pub permissions: Vec<ChannelPermission>,
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ use log::debug;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
mod auditlog;
|
||||
mod bans;
|
||||
mod channel;
|
||||
mod email_token;
|
||||
|
@ -21,8 +20,6 @@ mod password_reset_token;
|
|||
mod role;
|
||||
mod user;
|
||||
|
||||
pub use auditlog::AuditLog;
|
||||
pub use auditlog::AuditLogId;
|
||||
pub use bans::GuildBan;
|
||||
pub use channel::Channel;
|
||||
pub use email_token::EmailToken;
|
||||
|
|
|
@ -21,9 +21,9 @@ use super::{HasIsAbove, HasUuid, load_or_empty, member::MemberBuilder};
|
|||
#[diesel(primary_key(uuid))]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct Role {
|
||||
pub uuid: Uuid,
|
||||
uuid: Uuid,
|
||||
guild_uuid: Uuid,
|
||||
pub name: String,
|
||||
name: String,
|
||||
color: i32,
|
||||
is_above: Option<Uuid>,
|
||||
pub permissions: i64,
|
||||
|
|
|
@ -11,25 +11,6 @@ diesel::table! {
|
|||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
audit_logs (uuid) {
|
||||
uuid -> Uuid,
|
||||
guild_uuid -> Uuid,
|
||||
action_id -> Int2,
|
||||
by_uuid -> Uuid,
|
||||
channel_uuid -> Nullable<Uuid>,
|
||||
user_uuid -> Nullable<Uuid>,
|
||||
message_uuid -> Nullable<Uuid>,
|
||||
role_uuid -> Nullable<Uuid>,
|
||||
#[max_length = 200]
|
||||
audit_message -> Nullable<Varchar>,
|
||||
#[max_length = 200]
|
||||
changed_from -> Nullable<Varchar>,
|
||||
#[max_length = 200]
|
||||
changed_to -> Nullable<Varchar>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
channel_permissions (channel_uuid, role_uuid) {
|
||||
channel_uuid -> Uuid,
|
||||
|
@ -182,11 +163,6 @@ diesel::table! {
|
|||
|
||||
diesel::joinable!(access_tokens -> refresh_tokens (refresh_token));
|
||||
diesel::joinable!(access_tokens -> users (uuid));
|
||||
diesel::joinable!(audit_logs -> channels (channel_uuid));
|
||||
diesel::joinable!(audit_logs -> guild_members (by_uuid));
|
||||
diesel::joinable!(audit_logs -> messages (message_uuid));
|
||||
diesel::joinable!(audit_logs -> roles (role_uuid));
|
||||
diesel::joinable!(audit_logs -> users (user_uuid));
|
||||
diesel::joinable!(channel_permissions -> channels (channel_uuid));
|
||||
diesel::joinable!(channel_permissions -> roles (role_uuid));
|
||||
diesel::joinable!(channels -> guilds (guild_uuid));
|
||||
|
@ -206,7 +182,6 @@ diesel::joinable!(roles -> guilds (guild_uuid));
|
|||
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
access_tokens,
|
||||
audit_logs,
|
||||
channel_permissions,
|
||||
channels,
|
||||
friend_requests,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue