From 5297e5c8c92ef0edad759ad1492908f34948201d Mon Sep 17 00:00:00 2001 From: Eason <30045503+Eason0729@users.noreply.github.com> Date: Fri, 12 Jul 2024 12:43:49 +0000 Subject: [PATCH] cilppy(backend): add template for exposing access control to frontend --- backend/src/endpoint/announcement.rs | 25 +++++++++++++++---------- backend/src/endpoint/mod.rs | 4 ++-- backend/src/entity/announcement.rs | 3 +++ backend/src/entity/chat.rs | 3 +++ backend/src/entity/contest.rs | 3 +++ backend/src/entity/education.rs | 3 +++ backend/src/entity/mod.rs | 1 + backend/src/entity/problem.rs | 3 +++ backend/src/entity/testcase.rs | 3 +++ backend/src/entity/user.rs | 3 +++ backend/src/entity/util/filter.rs | 3 +++ backend/src/entity/util/paginator.rs | 1 + grpc/proto/backend.proto | 1 + 13 files changed, 44 insertions(+), 12 deletions(-) diff --git a/backend/src/endpoint/announcement.rs b/backend/src/endpoint/announcement.rs index cfc8b38c..4d14d580 100644 --- a/backend/src/endpoint/announcement.rs +++ b/backend/src/endpoint/announcement.rs @@ -9,21 +9,26 @@ use crate::{ NonZeroU32, }; -impl From for AnnouncementFullInfo { - fn from(value: Model) -> Self { +impl<'a> From> for AnnouncementFullInfo { + fn from(value: WithAuth<'a, Model>) -> Self { + let model = value.1; + let writable = Entity::writable(&model, value.0); AnnouncementFullInfo { info: AnnouncementInfo { - id: value.id, - title: value.title, - update_date: into_prost(value.update_at), + id: model.id, + title: model.title, + update_date: into_prost(model.update_at), }, - author_id: value.user_id, - content: value.content, - public: value.public, + author_id: model.user_id, + content: model.content, + public: model.public, + writable, } } } +impl<'a> WithAuthTrait for Model {} + impl From for AnnouncementInfo { fn from(value: Model) -> Self { AnnouncementInfo { @@ -107,7 +112,7 @@ impl Announcement for ArcServer { .map_err(Into::::into)? .ok_or(Error::NotInDB)?; - Ok(Response::new(model.into())) + Ok(Response::new(model.with_auth(&auth).into())) } #[instrument(skip_all, level = "debug")] async fn create( @@ -376,6 +381,6 @@ impl Announcement for ArcServer { .map_err(Into::::into)? .ok_or(Error::NotInDB)?; - Ok(Response::new(model.into())) + Ok(Response::new(model.with_auth(&auth).into())) } } diff --git a/backend/src/endpoint/mod.rs b/backend/src/endpoint/mod.rs index 1ea39521..fe416d0d 100644 --- a/backend/src/endpoint/mod.rs +++ b/backend/src/endpoint/mod.rs @@ -17,7 +17,7 @@ mod user; mod tools { pub use crate::NonZeroU32; - pub use grpc::backend::*; + pub use grpc::backend::{Id, Order, *}; pub use sea_orm::*; pub use std::ops::Deref; pub use tonic::*; @@ -27,7 +27,7 @@ mod tools { pub use crate::entity::util::{ filter::*, paginator::{PaginateRaw, Remain}, - with::{WithAuthTrait, WithDBTrait}, + with::*, }; pub use crate::util::{ auth::RoleLv, diff --git a/backend/src/entity/announcement.rs b/backend/src/entity/announcement.rs index ba8a635f..c9a07309 100644 --- a/backend/src/entity/announcement.rs +++ b/backend/src/entity/announcement.rs @@ -91,6 +91,9 @@ impl super::Filter for Entity { } Err(Error::NotInDB) } + fn writable(model: &Self::Model, auth: &Auth) -> bool { + auth.user_perm().admin() || Some(model.user_id) == auth.user_id() + } } #[async_trait] diff --git a/backend/src/entity/chat.rs b/backend/src/entity/chat.rs index d442df4e..f5ba0afb 100644 --- a/backend/src/entity/chat.rs +++ b/backend/src/entity/chat.rs @@ -61,6 +61,9 @@ impl super::Filter for Entity { } Err(Error::RequirePermission(RoleLv::Admin)) } + fn writable(model: &Self::Model, auth: &Auth) -> bool { + auth.user_perm().admin() + } } #[async_trait] diff --git a/backend/src/entity/contest.rs b/backend/src/entity/contest.rs index 5f090fd3..2eae82b4 100644 --- a/backend/src/entity/contest.rs +++ b/backend/src/entity/contest.rs @@ -190,6 +190,9 @@ impl super::Filter for Entity { } Err(Error::NotInDB) } + fn writable(model: &Self::Model, auth: &Auth) -> bool { + auth.user_perm().admin() || Some(model.hoster) == auth.user_id() + } } #[async_trait] diff --git a/backend/src/entity/education.rs b/backend/src/entity/education.rs index 15bbb842..ef8901f7 100644 --- a/backend/src/entity/education.rs +++ b/backend/src/entity/education.rs @@ -80,6 +80,9 @@ impl super::Filter for Entity { } Err(Error::NotInDB) } + fn writable(model: &Self::Model, auth: &Auth) -> bool { + auth.user_perm().admin() || Some(model.user_id) == auth.user_id() + } } #[async_trait] diff --git a/backend/src/entity/mod.rs b/backend/src/entity/mod.rs index 37bd73e5..071c4e59 100644 --- a/backend/src/entity/mod.rs +++ b/backend/src/entity/mod.rs @@ -21,6 +21,7 @@ use sea_orm::{ use crate::util::{auth::Auth, error::Error}; use tonic::async_trait; +use crate::util::auth::RoleLv; use util::filter::{Filter, ParentalTrait}; use util::paginator::*; use util::with::*; diff --git a/backend/src/entity/problem.rs b/backend/src/entity/problem.rs index 4c6a8790..c2a024e5 100644 --- a/backend/src/entity/problem.rs +++ b/backend/src/entity/problem.rs @@ -221,6 +221,9 @@ impl super::Filter for Entity { } Err(Error::NotInDB) } + fn writable(model: &Self::Model, auth: &Auth) -> bool { + auth.user_perm().admin() || Some(model.user_id) == auth.user_id() + } } #[async_trait] diff --git a/backend/src/entity/testcase.rs b/backend/src/entity/testcase.rs index ae08abde..b758bee1 100644 --- a/backend/src/entity/testcase.rs +++ b/backend/src/entity/testcase.rs @@ -85,6 +85,9 @@ impl super::Filter for Entity { } Err(Error::NotInDB) } + fn writable(model: &Self::Model, auth: &Auth) -> bool { + auth.user_perm().admin() || Some(model.user_id) == auth.user_id() + } } #[async_trait] diff --git a/backend/src/entity/user.rs b/backend/src/entity/user.rs index 7de967c8..b30ad57a 100644 --- a/backend/src/entity/user.rs +++ b/backend/src/entity/user.rs @@ -156,6 +156,9 @@ impl super::Filter for Entity { } Ok(query.filter(Column::Id.eq(user_id))) } + fn writable(model: &Self::Model, auth: &Auth) -> bool { + auth.user_perm().admin() || Some(model.id) == auth.user_id() + } } #[async_trait] diff --git a/backend/src/entity/util/filter.rs b/backend/src/entity/util/filter.rs index f416ab5d..2e4bf977 100644 --- a/backend/src/entity/util/filter.rs +++ b/backend/src/entity/util/filter.rs @@ -42,4 +42,7 @@ where { Self::write_filter(Self::find_by_id(id), auth) } + fn writable(model: &Self::Model, auth: &Auth) -> bool { + false + } } diff --git a/backend/src/entity/util/paginator.rs b/backend/src/entity/util/paginator.rs index 73c33751..22739d4d 100644 --- a/backend/src/entity/util/paginator.rs +++ b/backend/src/entity/util/paginator.rs @@ -384,6 +384,7 @@ impl UninitPaginator

{ ) -> Result, Error> { if let UninitPaginator::Init(x) = self { let size = size.min((i64::MAX - 1) as u64) as i64; + let offset = offset.max(i64::MIN + 1); let (size, offset) = match offset < 0 { true => ( -size, diff --git a/grpc/proto/backend.proto b/grpc/proto/backend.proto index 31268c76..7bdd2ea9 100644 --- a/grpc/proto/backend.proto +++ b/grpc/proto/backend.proto @@ -224,6 +224,7 @@ message AnnouncementFullInfo { required int32 author_id = 2; required string content = 3; required bool public = 4; + required bool writable = 5; } message ListAnnouncementResponse {