add: implement 9 new scopes, 21 new api endpoints
This commit is contained in:
parent
c3139ef1d2
commit
8f16068a34
14 changed files with 973 additions and 35 deletions
|
@ -5,6 +5,8 @@
|
|||
|
||||
# Usage
|
||||
|
||||
Make sure you have AT LEAST rustc version 1.89.0-nightly.
|
||||
|
||||
Everything Tetratto needs will be built into the main binary. You can build Tetratto with the following command:
|
||||
|
||||
```bash
|
||||
|
|
|
@ -292,6 +292,48 @@ macro_rules! check_user_blocked_or_private {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
($user:expr, $other_user:ident, $data:ident, @api) => {
|
||||
// check if we're blocked
|
||||
if let Some(ref ua) = $user {
|
||||
if $data
|
||||
.get_userblock_by_initiator_receiver($other_user.id, ua.id)
|
||||
.await
|
||||
.is_ok()
|
||||
&& !ua
|
||||
.permissions
|
||||
.check(tetratto_core::model::permissions::FinePermission::MANAGE_USERS)
|
||||
{
|
||||
return Json(
|
||||
tetratto_core::model::Error::MiscError("You're blocked".to_string()).into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// check for private profile
|
||||
if $other_user.settings.private_profile {
|
||||
if let Some(ref ua) = $user {
|
||||
if (ua.id != $other_user.id)
|
||||
&& !ua
|
||||
.permissions
|
||||
.check(tetratto_core::model::permissions::FinePermission::MANAGE_USERS)
|
||||
&& $data
|
||||
.get_userfollow_by_initiator_receiver($other_user.id, ua.id)
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
return Json(
|
||||
tetratto_core::model::Error::MiscError("Profile is private".to_string())
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return Json(
|
||||
tetratto_core::model::Error::MiscError("Profile is private".to_string()).into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
|
@ -318,4 +360,12 @@ macro_rules! ignore_users_gen {
|
|||
]
|
||||
.concat()
|
||||
};
|
||||
|
||||
($user:ident!, #$data:ident) => {
|
||||
[
|
||||
$data.get_userblocks_receivers($user.id).await,
|
||||
$data.get_userblocks_initiator_by_receivers($user.id).await,
|
||||
]
|
||||
.concat()
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
use crate::{
|
||||
State, get_user_from_token,
|
||||
check_user_blocked_or_private, get_user_from_token,
|
||||
model::{ApiReturn, Error},
|
||||
routes::pages::PaginatedQuery,
|
||||
State,
|
||||
};
|
||||
use axum::{
|
||||
extract::{Path, Query},
|
||||
response::IntoResponse,
|
||||
Extension, Json,
|
||||
};
|
||||
use axum::{Extension, Json, extract::Path, response::IntoResponse};
|
||||
use axum_extra::extract::CookieJar;
|
||||
use tetratto_core::model::auth::{FollowResult, IpBlock, Notification, UserBlock, UserFollow};
|
||||
use tetratto_core::model::{
|
||||
auth::{FollowResult, IpBlock, Notification, UserBlock, UserFollow},
|
||||
oauth,
|
||||
};
|
||||
|
||||
/// Toggle following on the given user.
|
||||
pub async fn follow_request(
|
||||
|
@ -13,7 +22,7 @@ pub async fn follow_request(
|
|||
Extension(data): Extension<State>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageFollowing) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -74,7 +83,7 @@ pub async fn cancel_follow_request(
|
|||
Path(id): Path<usize>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageFollowing) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -95,7 +104,7 @@ pub async fn accept_follow_request(
|
|||
Path(id): Path<usize>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageFollowers) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -142,7 +151,7 @@ pub async fn block_request(
|
|||
Extension(data): Extension<State>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageBlocks) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -205,7 +214,7 @@ pub async fn ip_block_request(
|
|||
Extension(data): Extension<State>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserCreateIpBlock) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -232,3 +241,67 @@ pub async fn ip_block_request(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the followers of the given user.
|
||||
pub async fn followers_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadProfiles) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
let other_user = match data.get_user_by_id(id).await {
|
||||
Ok(ua) => ua,
|
||||
Err(e) => return Json(e.into()),
|
||||
};
|
||||
|
||||
check_user_blocked_or_private!(Some(&user), other_user, data, @api);
|
||||
match data.get_userfollows_by_receiver(id, 12, props.page).await {
|
||||
Ok(f) => Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data.fill_userfollows_with_initiator(f).await {
|
||||
Ok(f) => Some(data.userfollows_user_filter(&f)),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
}),
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the following of the given user.
|
||||
pub async fn following_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadProfiles) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
let other_user = match data.get_user_by_id(id).await {
|
||||
Ok(ua) => ua,
|
||||
Err(e) => return Json(e.into()),
|
||||
};
|
||||
|
||||
check_user_blocked_or_private!(Some(&user), other_user, data, @api);
|
||||
match data.get_userfollows_by_initiator(id, 12, props.page).await {
|
||||
Ok(f) => Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data.fill_userfollows_with_receiver(f).await {
|
||||
Ok(f) => Some(data.userfollows_user_filter(&f)),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
}),
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
use crate::{
|
||||
get_user_from_token,
|
||||
model::{ApiReturn, Error},
|
||||
routes::api::v1::CreateUserWarning,
|
||||
routes::{api::v1::CreateUserWarning, pages::PaginatedQuery},
|
||||
State,
|
||||
};
|
||||
use axum::{Extension, Json, extract::Path, response::IntoResponse};
|
||||
use axum::{
|
||||
extract::{Path, Query},
|
||||
response::IntoResponse,
|
||||
Extension, Json,
|
||||
};
|
||||
use axum_extra::extract::CookieJar;
|
||||
use tetratto_core::model::{auth::UserWarning, permissions::FinePermission};
|
||||
use tetratto_core::model::{auth::UserWarning, oauth, permissions::FinePermission};
|
||||
|
||||
/// Create a new user warning.
|
||||
pub async fn create_request(
|
||||
|
@ -16,7 +20,7 @@ pub async fn create_request(
|
|||
Json(req): Json<CreateUserWarning>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::ModManageWarnings) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -45,7 +49,7 @@ pub async fn delete_request(
|
|||
Extension(data): Extension<State>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::ModManageWarnings) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -63,3 +67,58 @@ pub async fn delete_request(
|
|||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all warnings for the given user.
|
||||
pub async fn on_user_request(
|
||||
jar: CookieJar,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::ModManageWarnings) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
if !user.permissions.check(FinePermission::MANAGE_WARNINGS) {
|
||||
return Json(Error::NotAllowed.into());
|
||||
}
|
||||
|
||||
match data
|
||||
.get_user_warnings_by_user(user.id, 12, props.page)
|
||||
.await
|
||||
{
|
||||
Ok(w) => Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: Some(w),
|
||||
}),
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a single warning.
|
||||
pub async fn get_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::ModManageWarnings) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
if !user.permissions.check(FinePermission::MANAGE_WARNINGS) {
|
||||
return Json(Error::NotAllowed.into());
|
||||
}
|
||||
|
||||
match data.get_user_warning_by_id(id).await {
|
||||
Ok(w) => Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: Some(w),
|
||||
}),
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use axum::{
|
||||
extract::Path,
|
||||
extract::{Path, Query},
|
||||
http::{HeaderMap, HeaderValue},
|
||||
response::IntoResponse,
|
||||
Extension, Json,
|
||||
|
@ -14,11 +14,14 @@ use tetratto_core::model::{
|
|||
ApiReturn, Error,
|
||||
};
|
||||
use crate::{
|
||||
get_user_from_token,
|
||||
check_user_blocked_or_private, get_user_from_token,
|
||||
image::{save_webp_buffer, JsonMultipart},
|
||||
routes::api::v1::{
|
||||
CreatePost, CreateRepost, UpdatePostContent, UpdatePostContext, UpdatePostIsOpen,
|
||||
VoteInPoll,
|
||||
routes::{
|
||||
api::v1::{
|
||||
CreatePost, CreateRepost, UpdatePostContent, UpdatePostContext, UpdatePostIsOpen,
|
||||
VoteInPoll,
|
||||
},
|
||||
pages::{PaginatedQuery, SearchedQuery},
|
||||
},
|
||||
State,
|
||||
};
|
||||
|
@ -409,3 +412,550 @@ pub async fn update_is_open_request(
|
|||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get posts by the given user.
|
||||
pub async fn posts_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
let other_user = match data.get_user_by_id(id).await {
|
||||
Ok(ua) => ua,
|
||||
Err(e) => return Json(e.into()),
|
||||
};
|
||||
|
||||
check_user_blocked_or_private!(Some(&user), other_user, data, @api);
|
||||
match data
|
||||
.get_posts_by_user(id, 12, props.page, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get posts in the given community.
|
||||
pub async fn community_posts_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
match data.get_posts_by_community(id, 12, props.page).await {
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get replies by the given user.
|
||||
pub async fn replies_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
let other_user = match data.get_user_by_id(id).await {
|
||||
Ok(ua) => ua,
|
||||
Err(e) => return Json(e.into()),
|
||||
};
|
||||
|
||||
check_user_blocked_or_private!(Some(&user), other_user, data, @api);
|
||||
match data
|
||||
.get_replies_by_user(id, 12, props.page, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get posts (with media) by the given user.
|
||||
pub async fn posts_with_media_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
let other_user = match data.get_user_by_id(id).await {
|
||||
Ok(ua) => ua,
|
||||
Err(e) => return Json(e.into()),
|
||||
};
|
||||
|
||||
check_user_blocked_or_private!(Some(&user), other_user, data, @api);
|
||||
match data
|
||||
.get_media_posts_by_user(id, 12, props.page, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get posts (searched) by the given user.
|
||||
pub async fn posts_searched_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<SearchedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
let other_user = match data.get_user_by_id(id).await {
|
||||
Ok(ua) => ua,
|
||||
Err(e) => return Json(e.into()),
|
||||
};
|
||||
|
||||
check_user_blocked_or_private!(Some(&user), other_user, data, @api);
|
||||
match data
|
||||
.get_posts_by_user_searched(id, 12, props.page, &props.text, &Some(&user))
|
||||
.await
|
||||
{
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all posts (searched).
|
||||
pub async fn all_posts_searched_request(
|
||||
jar: CookieJar,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<SearchedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
if !user.permissions.check(FinePermission::SUPPORTER) {
|
||||
return Json(Error::RequiresSupporter.into());
|
||||
}
|
||||
|
||||
match data.get_posts_searched(12, props.page, &props.text).await {
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all posts (from user communities).
|
||||
pub async fn from_communities_request(
|
||||
jar: CookieJar,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
match data.get_popular_posts(12, props.page, 604_800_000).await {
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all posts (from stack).
|
||||
pub async fn from_stack_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
let stack = match data.get_stack_by_id(id).await {
|
||||
Ok(s) => s,
|
||||
Err(e) => return Json(e.into()),
|
||||
};
|
||||
|
||||
if stack.owner != user.id && !user.permissions.check(FinePermission::MANAGE_STACKS) {
|
||||
return Json(Error::NotAllowed.into());
|
||||
}
|
||||
|
||||
match data
|
||||
.get_posts_from_stack(id, 12, props.page, stack.sort)
|
||||
.await
|
||||
{
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all posts (by likes).
|
||||
pub async fn popular_request(
|
||||
jar: CookieJar,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
match data.get_popular_posts(12, props.page, 604_800_000).await {
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all posts (from any community).
|
||||
pub async fn all_request(
|
||||
jar: CookieJar,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
match data.get_latest_posts(12, props.page).await {
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all posts (from following).
|
||||
pub async fn following_request(
|
||||
jar: CookieJar,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
match data
|
||||
.get_posts_from_user_following(user.id, 12, props.page)
|
||||
.await
|
||||
{
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a single post.
|
||||
pub async fn get_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
if get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts).is_none() {
|
||||
return Json(Error::NotAllowed.into());
|
||||
}
|
||||
|
||||
match data.get_post_by_id(id).await {
|
||||
Ok(p) => Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: Some(p),
|
||||
}),
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get replies for the given post.
|
||||
pub async fn post_replies_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
match data.get_replies_by_post(id, 12, props.page).await {
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get reposts for the given post.
|
||||
pub async fn reposts_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
match data.get_reposts_by_quoting(id, 12, props.page).await {
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get quotes for the given post.
|
||||
pub async fn quotes_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadPosts) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
match data.get_quoting_posts_by_quoting(id, 12, props.page).await {
|
||||
Ok(posts) => {
|
||||
let ignore_users = crate::ignore_users_gen!(user!, #data);
|
||||
Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: match data
|
||||
.fill_posts_with_community(posts, user.id, &ignore_users, &Some(user.clone()))
|
||||
.await
|
||||
{
|
||||
Ok(l) => data.posts_owner_filter(
|
||||
&data.posts_muted_phrase_filter(&l, Some(&user.settings.muted)),
|
||||
),
|
||||
Err(e) => return Json(e.into()),
|
||||
},
|
||||
})
|
||||
}
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,6 +133,60 @@ pub fn routes() -> Router {
|
|||
"/posts/{id}/open",
|
||||
post(communities::posts::update_is_open_request),
|
||||
)
|
||||
.route(
|
||||
"/posts/from_user/{id}",
|
||||
get(communities::posts::posts_request),
|
||||
)
|
||||
.route(
|
||||
"/posts/from_user/{id}/replies",
|
||||
get(communities::posts::replies_request),
|
||||
)
|
||||
.route(
|
||||
"/posts/from_user/{id}/media",
|
||||
get(communities::posts::posts_with_media_request),
|
||||
)
|
||||
.route(
|
||||
"/posts/from_user/{id}/searched",
|
||||
get(communities::posts::posts_searched_request),
|
||||
)
|
||||
.route(
|
||||
"/posts/from_community/{id}",
|
||||
get(communities::posts::community_posts_request),
|
||||
)
|
||||
.route(
|
||||
"/posts/from_stack/{id}",
|
||||
get(communities::posts::from_stack_request),
|
||||
)
|
||||
.route(
|
||||
"/posts/searched",
|
||||
get(communities::posts::all_posts_searched_request),
|
||||
)
|
||||
.route(
|
||||
"/posts/timeline/communities",
|
||||
get(communities::posts::from_communities_request),
|
||||
)
|
||||
.route(
|
||||
"/posts/timeline/popular",
|
||||
get(communities::posts::popular_request),
|
||||
)
|
||||
.route("/posts/timeline/all", get(communities::posts::all_request))
|
||||
.route(
|
||||
"/posts/timeline/following",
|
||||
get(communities::posts::following_request),
|
||||
)
|
||||
.route("/posts/{id}", get(communities::posts::get_request))
|
||||
.route(
|
||||
"/posts/{id}/replies",
|
||||
delete(communities::posts::post_replies_request),
|
||||
)
|
||||
.route(
|
||||
"/posts/{id}/reposts",
|
||||
delete(communities::posts::reposts_request),
|
||||
)
|
||||
.route(
|
||||
"/posts/{id}/quotes",
|
||||
delete(communities::posts::quotes_request),
|
||||
)
|
||||
// drafts
|
||||
.route("/drafts", post(communities::drafts::create_request))
|
||||
.route("/drafts/my", get(communities::drafts::get_drafts_request))
|
||||
|
@ -251,12 +305,25 @@ pub fn routes() -> Router {
|
|||
"/auth/user/{id}/_connect/{stream}/send",
|
||||
post(auth::profile::post_to_socket_request),
|
||||
)
|
||||
.route(
|
||||
"/auth/user/{id}/following",
|
||||
get(auth::social::following_request),
|
||||
)
|
||||
.route(
|
||||
"/auth/user/{id}/followers",
|
||||
get(auth::social::followers_request),
|
||||
)
|
||||
// warnings
|
||||
.route("/warnings/{id}", get(auth::user_warnings::get_request))
|
||||
.route("/warnings/{id}", post(auth::user_warnings::create_request))
|
||||
.route(
|
||||
"/warnings/{id}",
|
||||
delete(auth::user_warnings::delete_request),
|
||||
)
|
||||
.route(
|
||||
"/warnings/on_user/{id}",
|
||||
post(auth::user_warnings::on_user_request),
|
||||
)
|
||||
// notifications
|
||||
.route(
|
||||
"/notifications/my",
|
||||
|
@ -275,6 +342,7 @@ pub fn routes() -> Router {
|
|||
"/notifications/all/read_status",
|
||||
post(notifications::update_all_read_status_request),
|
||||
)
|
||||
.route("/notifications/my", get(notifications::get_list_request))
|
||||
// community memberships
|
||||
.route(
|
||||
"/communities/{id}/join",
|
||||
|
@ -304,6 +372,7 @@ pub fn routes() -> Router {
|
|||
delete(requests::delete_request),
|
||||
)
|
||||
.route("/requests/my", delete(requests::delete_all_request))
|
||||
.route("/requests/my", get(requests::get_list_request))
|
||||
// connections
|
||||
.route(
|
||||
"/auth/user/connections/_data",
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
use super::UpdateNotificationRead;
|
||||
use crate::{State, get_user_from_token};
|
||||
use axum::{Extension, Json, extract::Path, response::IntoResponse};
|
||||
use crate::{get_user_from_token, routes::pages::PaginatedQuery, State};
|
||||
use axum::{
|
||||
extract::{Path, Query},
|
||||
response::IntoResponse,
|
||||
Extension, Json,
|
||||
};
|
||||
use axum_extra::extract::CookieJar;
|
||||
use tetratto_core::model::{ApiReturn, Error};
|
||||
use tetratto_core::model::{oauth, ApiReturn, Error};
|
||||
|
||||
pub async fn delete_request(
|
||||
jar: CookieJar,
|
||||
|
@ -10,7 +14,7 @@ pub async fn delete_request(
|
|||
Path(id): Path<usize>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageNotifications) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -30,7 +34,7 @@ pub async fn delete_all_request(
|
|||
Extension(data): Extension<State>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageNotifications) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -51,7 +55,7 @@ pub async fn delete_all_by_tag_request(
|
|||
Path(tag): Path<String>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageNotifications) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -73,7 +77,7 @@ pub async fn update_read_status_request(
|
|||
Json(req): Json<UpdateNotificationRead>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageNotifications) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -94,7 +98,7 @@ pub async fn update_all_read_status_request(
|
|||
Json(req): Json<UpdateNotificationRead>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageNotifications) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -108,3 +112,27 @@ pub async fn update_all_read_status_request(
|
|||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_list_request(
|
||||
jar: CookieJar,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadNotifications) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
match data
|
||||
.get_notifications_by_owner_paginated(user.id, 12, props.page)
|
||||
.await
|
||||
{
|
||||
Ok(l) => Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: Some(l),
|
||||
}),
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
use crate::{State, get_user_from_token};
|
||||
use axum::{Extension, Json, extract::Path, response::IntoResponse};
|
||||
use crate::{get_user_from_token, routes::pages::PaginatedQuery, State};
|
||||
use axum::{
|
||||
extract::{Path, Query},
|
||||
response::IntoResponse,
|
||||
Extension, Json,
|
||||
};
|
||||
use axum_extra::extract::CookieJar;
|
||||
use tetratto_core::model::{ApiReturn, Error};
|
||||
use tetratto_core::model::{oauth, ApiReturn, Error};
|
||||
|
||||
pub async fn delete_request(
|
||||
jar: CookieJar,
|
||||
|
@ -9,7 +13,7 @@ pub async fn delete_request(
|
|||
Path((id, linked_asset)): Path<(usize, usize)>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageRequests) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -29,7 +33,7 @@ pub async fn delete_all_request(
|
|||
Extension(data): Extension<State>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserManageRequests) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
@ -43,3 +47,27 @@ pub async fn delete_all_request(
|
|||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_list_request(
|
||||
jar: CookieJar,
|
||||
Extension(data): Extension<State>,
|
||||
Query(props): Query<PaginatedQuery>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data, oauth::AppScope::UserReadRequests) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
match data
|
||||
.get_requests_by_owner_paginated(user.id, 12, props.page)
|
||||
.await
|
||||
{
|
||||
Ok(l) => Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Success".to_string(),
|
||||
payload: Some(l),
|
||||
}),
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -738,7 +738,7 @@ pub async fn post_request(
|
|||
// ...
|
||||
let ignore_users = crate::ignore_users_gen!(user, data);
|
||||
|
||||
let feed = match data.0.get_post_comments(post.id, 12, props.page).await {
|
||||
let feed = match data.0.get_replies_by_post(post.id, 12, props.page).await {
|
||||
Ok(p) => match data.0.fill_posts(p, &ignore_users, &user).await {
|
||||
Ok(p) => p,
|
||||
Err(e) => return Err(Html(render_error(e, &jar, &data, &user).await)),
|
||||
|
|
|
@ -136,7 +136,7 @@ impl DataManager {
|
|||
/// * `id` - the ID of the post the requested posts are commenting on
|
||||
/// * `batch` - the limit of posts in each page
|
||||
/// * `page` - the page number
|
||||
pub async fn get_post_comments(
|
||||
pub async fn get_replies_by_post(
|
||||
&self,
|
||||
id: usize,
|
||||
batch: usize,
|
||||
|
@ -517,6 +517,30 @@ impl DataManager {
|
|||
out
|
||||
}
|
||||
|
||||
/// Filter to update posts to clean their owner for public APIs.
|
||||
pub fn posts_owner_filter(&self, posts: &Vec<FullPost>) -> Vec<FullPost> {
|
||||
let mut out: Vec<FullPost> = Vec::new();
|
||||
|
||||
for mut post in posts.clone() {
|
||||
post.1.clean();
|
||||
|
||||
// reposting
|
||||
if let Some((ref mut x, _)) = post.3 {
|
||||
x.clean();
|
||||
}
|
||||
|
||||
// question
|
||||
if let Some((_, ref mut x)) = post.4 {
|
||||
x.clean();
|
||||
}
|
||||
|
||||
// ...
|
||||
out.push(post);
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
/// Get all posts from the given user (from most recent).
|
||||
///
|
||||
/// # Arguments
|
||||
|
|
|
@ -27,7 +27,7 @@ impl DataManager {
|
|||
}
|
||||
}
|
||||
|
||||
auto_method!(get_user_warning_by_ip(&str)@get_user_warning_from_row -> "SELECT * FROM user_warnings WHERE ip = $1" --name="user warning" --returns=UserWarning --cache-key-tmpl="atto.user_warning:{}");
|
||||
auto_method!(get_user_warning_by_id(usize)@get_user_warning_from_row -> "SELECT * FROM user_warnings WHERE id = $1" --name="user warning" --returns=UserWarning --cache-key-tmpl="atto.user_warning:{}");
|
||||
|
||||
/// Get all user warnings by user (paginated).
|
||||
///
|
||||
|
|
|
@ -28,6 +28,18 @@ impl DataManager {
|
|||
|
||||
auto_method!(get_userfollow_by_id()@get_userfollow_from_row -> "SELECT * FROM userfollows WHERE id = $1" --name="user follow" --returns=UserFollow --cache-key-tmpl="atto.userfollow:{}");
|
||||
|
||||
/// Filter to update userfollows to clean their users for public APIs.
|
||||
pub fn userfollows_user_filter(&self, x: &Vec<(UserFollow, User)>) -> Vec<(UserFollow, User)> {
|
||||
let mut out: Vec<(UserFollow, User)> = Vec::new();
|
||||
|
||||
for mut y in x.clone() {
|
||||
y.1.clean();
|
||||
out.push(y);
|
||||
}
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
/// Get a user follow by `initiator` and `receiver` (in that order).
|
||||
pub async fn get_userfollow_by_initiator_receiver(
|
||||
&self,
|
||||
|
|
|
@ -387,6 +387,22 @@ impl User {
|
|||
)
|
||||
.ok()
|
||||
}
|
||||
|
||||
/// Clean the struct for public viewing.
|
||||
pub fn clean(&mut self) {
|
||||
self.password = String::new();
|
||||
self.salt = String::new();
|
||||
|
||||
self.tokens = Vec::new();
|
||||
self.grants = Vec::new();
|
||||
|
||||
self.recovery_codes = Vec::new();
|
||||
self.totp = String::new();
|
||||
|
||||
self.settings = UserSettings::default();
|
||||
self.stripe_id = String::new();
|
||||
self.connections = HashMap::new();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
|
@ -446,7 +462,7 @@ impl Notification {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct UserFollow {
|
||||
pub id: usize,
|
||||
pub created: usize,
|
||||
|
|
|
@ -36,6 +36,8 @@ pub enum PkceChallengeMethod {
|
|||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum AppScope {
|
||||
/// Read the profile of other user's on behalf of the user.
|
||||
UserReadProfiles,
|
||||
/// Read the user's profile (username, bio, etc).
|
||||
UserReadProfile,
|
||||
/// Read the user's settings.
|
||||
|
@ -52,6 +54,10 @@ pub enum AppScope {
|
|||
UserReadCommunities,
|
||||
/// Connect to sockets on the user's behalf.
|
||||
UserReadSockets,
|
||||
/// Read the user's notifications.
|
||||
UserReadNotifications,
|
||||
/// Read the user's requests.
|
||||
UserReadRequests,
|
||||
/// Create posts as the user.
|
||||
UserCreatePosts,
|
||||
/// Create messages as the user.
|
||||
|
@ -82,6 +88,16 @@ pub enum AppScope {
|
|||
///
|
||||
/// Also includes managing the membership of users in the user's communities.
|
||||
UserManageMemberships,
|
||||
/// Follow/unfollow users on behalf of the user.
|
||||
UserManageFollowing,
|
||||
/// Accept follow requests on behalf of the user.
|
||||
UserManageFollowers,
|
||||
/// Block/unblock users on behalf of the user.
|
||||
UserManageBlocks,
|
||||
/// Manage the user's notifications.
|
||||
UserManageNotifications,
|
||||
/// Manage the user's requests.
|
||||
UserManageRequests,
|
||||
/// Edit posts created by the user.
|
||||
UserEditPosts,
|
||||
/// Edit drafts created by the user.
|
||||
|
@ -94,6 +110,8 @@ pub enum AppScope {
|
|||
ModPurgePosts,
|
||||
/// Restore deleted posts.
|
||||
ModDeletePosts,
|
||||
/// Manage user warnings.
|
||||
ModManageWarnings,
|
||||
/// Get a list of all emojis available to the user.
|
||||
UserReadEmojis,
|
||||
/// Create emojis on behalf of the user.
|
||||
|
@ -116,6 +134,7 @@ impl AppScope {
|
|||
let mut out: Vec<AppScope> = Vec::new();
|
||||
for scope in input.split(" ") {
|
||||
out.push(match scope {
|
||||
"user-read-profiles" => Self::UserReadProfiles,
|
||||
"user-read-profile" => Self::UserReadProfile,
|
||||
"user-read-settings" => Self::UserReadSettings,
|
||||
"user-read-sessions" => Self::UserReadSessions,
|
||||
|
@ -124,6 +143,8 @@ impl AppScope {
|
|||
"user-read-drafts" => Self::UserReadDrafts,
|
||||
"user-read-communities" => Self::UserReadCommunities,
|
||||
"user-read-sockets" => Self::UserReadSockets,
|
||||
"user-read-notifications" => Self::UserReadNotifications,
|
||||
"user-read-requests" => Self::UserReadRequests,
|
||||
"user-create-posts" => Self::UserCreatePosts,
|
||||
"user-create-messages" => Self::UserCreateMessages,
|
||||
"user-create-questions" => Self::UserCreateQuestions,
|
||||
|
@ -138,12 +159,18 @@ impl AppScope {
|
|||
"user-manage-stacks" => Self::UserManageStacks,
|
||||
"user-manage-relationships" => Self::UserManageRelationships,
|
||||
"user-manage-memberships" => Self::UserManageMemberships,
|
||||
"user-manage-following" => Self::UserManageFollowing,
|
||||
"user-manage-followers" => Self::UserManageFollowers,
|
||||
"user-manage-blocks" => Self::UserManageBlocks,
|
||||
"user-manage-notifications" => Self::UserManageNotifications,
|
||||
"user-manage-requests" => Self::UserManageRequests,
|
||||
"user-edit-posts" => Self::UserEditPosts,
|
||||
"user-edit-drafts" => Self::UserEditDrafts,
|
||||
"user-vote" => Self::UserVote,
|
||||
"user-join-communities" => Self::UserJoinCommunities,
|
||||
"mod-purge-posts" => Self::ModPurgePosts,
|
||||
"mod-delete-posts" => Self::ModDeletePosts,
|
||||
"mod-manage-warnings" => Self::ModManageWarnings,
|
||||
"user-read-emojis" => Self::UserReadEmojis,
|
||||
"community-create-emojis" => Self::CommunityCreateEmojis,
|
||||
"community-manage-emojis" => Self::CommunityManageEmojis,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue