add: policy achievements
This commit is contained in:
parent
d90b08720a
commit
973373426a
7 changed files with 83 additions and 13 deletions
|
@ -1135,15 +1135,13 @@
|
|||
(icon (text "rabbit"))
|
||||
(str (text "general:link.reference")))
|
||||
|
||||
(a
|
||||
("href" "{{ config.policies.terms_of_service }}")
|
||||
("class" "button")
|
||||
(button
|
||||
("onclick" "trigger('me::achievement', ['OpenTos']); Turbo.visit('{{ config.policies.terms_of_service }}')")
|
||||
(icon (text "heart-handshake"))
|
||||
(text "Terms of service"))
|
||||
|
||||
(a
|
||||
("href" "{{ config.policies.privacy }}")
|
||||
("class" "button")
|
||||
(button
|
||||
("onclick" "trigger('me::achievement', ['OpenPrivacyPolicy']); Turbo.visit('{{ config.policies.privacy }}')")
|
||||
(icon (text "cookie"))
|
||||
(text "Privacy policy"))
|
||||
(b ("class" "title") (str (text "general:label.account")))
|
||||
|
|
|
@ -1522,7 +1522,7 @@
|
|||
[
|
||||
[
|
||||
\"hide_associated_blocked_users\",
|
||||
\"Hide users that you've blocked on your other accounts from timelines.\",
|
||||
\"Hide users that you've blocked on your other accounts from timelines\",
|
||||
],
|
||||
\"{{ profile.settings.hide_associated_blocked_users }}\",
|
||||
\"checkbox\",
|
||||
|
|
|
@ -342,6 +342,27 @@
|
|||
},
|
||||
);
|
||||
|
||||
self.define("achievement", async (_, name) => {
|
||||
fetch("/api/v1/auth/user/me/achievement", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name,
|
||||
}),
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
if (!res.ok) {
|
||||
trigger("atto::toast", [
|
||||
res.ok ? "success" : "error",
|
||||
res.message,
|
||||
]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
self.define("report", (_, asset, asset_type) => {
|
||||
window.open(
|
||||
`/mod_panel/file_report?asset=${asset}&asset_type=${asset_type}`,
|
||||
|
|
|
@ -3,8 +3,9 @@ use crate::{
|
|||
get_user_from_token,
|
||||
model::{ApiReturn, Error},
|
||||
routes::api::v1::{
|
||||
AppendAssociations, DeleteUser, DisableTotp, RefreshGrantToken, UpdateSecondaryUserRole,
|
||||
UpdateUserIsVerified, UpdateUserPassword, UpdateUserRole, UpdateUserUsername,
|
||||
AppendAssociations, AwardAchievement, DeleteUser, DisableTotp, RefreshGrantToken,
|
||||
UpdateSecondaryUserRole, UpdateUserIsVerified, UpdateUserPassword, UpdateUserRole,
|
||||
UpdateUserUsername,
|
||||
},
|
||||
State,
|
||||
};
|
||||
|
@ -21,7 +22,7 @@ use futures_util::{sink::SinkExt, stream::StreamExt};
|
|||
use tetratto_core::{
|
||||
cache::Cache,
|
||||
model::{
|
||||
auth::{AchievementName, InviteCode, Token, UserSettings},
|
||||
auth::{AchievementName, InviteCode, Token, UserSettings, SELF_SERVE_ACHIEVEMENTS},
|
||||
moderation::AuditLogEntry,
|
||||
oauth,
|
||||
permissions::FinePermission,
|
||||
|
@ -920,3 +921,31 @@ pub async fn generate_invite_codes_request(
|
|||
payload: Some((out_string, errors_string)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Award an achievement to the current user.
|
||||
/// Only works with specific "self-serve" achievements.
|
||||
pub async fn self_serve_achievement_request(
|
||||
jar: CookieJar,
|
||||
Extension(data): Extension<State>,
|
||||
Json(req): Json<AwardAchievement>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let mut user = match get_user_from_token!(jar, data) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
if !SELF_SERVE_ACHIEVEMENTS.contains(&req.name) {
|
||||
return Json(Error::MiscError("Cannot grant this achievement manually".to_string()).into());
|
||||
}
|
||||
|
||||
// award achievement
|
||||
match data.add_achievement(&mut user, req.name.into()).await {
|
||||
Ok(_) => Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "Achievement granted".to_string(),
|
||||
payload: (),
|
||||
}),
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ use axum::{
|
|||
use serde::Deserialize;
|
||||
use tetratto_core::model::{
|
||||
apps::AppQuota,
|
||||
auth::AchievementName,
|
||||
communities::{
|
||||
CommunityContext, CommunityJoinAccess, CommunityReadAccess, CommunityWriteAccess,
|
||||
PollOption, PostContext,
|
||||
|
@ -387,6 +388,10 @@ pub fn routes() -> Router {
|
|||
"/auth/user/{id}/grants/{app}/refresh",
|
||||
post(auth::profile::refresh_grant_request),
|
||||
)
|
||||
.route(
|
||||
"/auth/user/me/achievement",
|
||||
post(auth::profile::self_serve_achievement_request),
|
||||
)
|
||||
// apps
|
||||
.route("/apps", post(apps::create_request))
|
||||
.route("/apps/{id}/title", post(apps::update_title_request))
|
||||
|
@ -976,7 +981,13 @@ pub struct AddJournalDir {
|
|||
pub struct RemoveJournalDir {
|
||||
pub dir: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct UpdateNoteTags {
|
||||
pub tags: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct AwardAchievement {
|
||||
pub name: AchievementName,
|
||||
}
|
||||
|
|
|
@ -493,7 +493,10 @@ pub struct ExternalConnectionData {
|
|||
}
|
||||
|
||||
/// The total number of achievements needed to 100% Tetratto!
|
||||
pub const ACHIEVEMENTS: usize = 28;
|
||||
pub const ACHIEVEMENTS: usize = 30;
|
||||
/// "self-serve" achievements can be granted by the user through the API.
|
||||
pub const SELF_SERVE_ACHIEVEMENTS: &[AchievementName] =
|
||||
&[AchievementName::OpenTos, AchievementName::OpenPrivacyPolicy];
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub enum AchievementName {
|
||||
|
@ -525,6 +528,8 @@ pub enum AchievementName {
|
|||
EditNote,
|
||||
CreatePostWithTitle,
|
||||
CreateRepost,
|
||||
OpenTos,
|
||||
OpenPrivacyPolicy,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
|
@ -565,6 +570,8 @@ impl AchievementName {
|
|||
Self::EditNote => "I take it back!",
|
||||
Self::CreatePostWithTitle => "Must declutter",
|
||||
Self::CreateRepost => "More than a like or comment...",
|
||||
Self::OpenTos => "Well informed!",
|
||||
Self::OpenPrivacyPolicy => "Privacy conscious",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -598,6 +605,8 @@ impl AchievementName {
|
|||
Self::EditNote => "Edit a note.",
|
||||
Self::CreatePostWithTitle => "Create a post with a title.",
|
||||
Self::CreateRepost => "Create a repost or quote.",
|
||||
Self::OpenTos => "Open the terms of service.",
|
||||
Self::OpenPrivacyPolicy => "Open the privacy policy.",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -633,6 +642,8 @@ impl AchievementName {
|
|||
Self::EditNote => Uncommon,
|
||||
Self::CreatePostWithTitle => Common,
|
||||
Self::CreateRepost => Common,
|
||||
Self::OpenTos => Uncommon,
|
||||
Self::OpenPrivacyPolicy => Uncommon,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,8 +38,8 @@ user = "user"
|
|||
password = "postgres"
|
||||
|
||||
[policies]
|
||||
terms_of_service = "/public/tos.html"
|
||||
privacy = "/public/privacy.html"
|
||||
terms_of_service = "/doc/tos.md"
|
||||
privacy = "/doc/privacy.md"
|
||||
|
||||
[turnstile]
|
||||
site_key = "1x00000000000000000000AA"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue