add: app_data api

This commit is contained in:
trisua 2025-07-17 13:34:10 -04:00
parent 5c520f4308
commit f423daf2fc
38 changed files with 410 additions and 91 deletions

View file

@ -2,7 +2,10 @@ use std::fmt::Display;
use serde::{Deserialize, Serialize};
use tetratto_shared::{snow::Snowflake, unix_epoch_timestamp};
use crate::model::oauth::AppScope;
use crate::{
database::app_data::{FREE_DATA_LIMIT, PASS_DATA_LIMIT},
model::{auth::User, oauth::AppScope, permissions::SecondaryPermission},
};
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum AppQuota {
@ -83,6 +86,10 @@ pub struct ThirdPartyApp {
///
/// Your app should handle informing users when scopes change.
pub scopes: Vec<AppScope>,
/// The app's secret API key (for app_data access).
pub api_key: String,
/// The number of bytes the app's app_data rows are using.
pub data_used: usize,
}
impl ThirdPartyApp {
@ -99,6 +106,8 @@ impl ThirdPartyApp {
banned: false,
grants: 0,
scopes: Vec::new(),
api_key: String::new(),
data_used: 0,
}
}
}
@ -106,7 +115,6 @@ impl ThirdPartyApp {
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AppData {
pub id: usize,
pub owner: usize,
pub app: usize,
pub key: String,
pub value: String,
@ -114,15 +122,26 @@ pub struct AppData {
impl AppData {
/// Create a new [`AppData`].
pub fn new(owner: usize, app: usize, key: String, value: String) -> Self {
pub fn new(app: usize, key: String, value: String) -> Self {
Self {
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
owner,
app,
key,
value,
}
}
/// Get the data limit of a given user.
pub fn user_limit(user: &User) -> usize {
if user
.secondary_permissions
.check(SecondaryPermission::DEVELOPER_PASS)
{
PASS_DATA_LIMIT
} else {
FREE_DATA_LIMIT
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
@ -154,7 +173,8 @@ impl Display for AppDataSelectMode {
Self::One => "LIMIT 1".to_string(),
Self::Many(order_by_top_level_key, limit, offset) => {
format!(
"ORDER BY v::jsonb->>'{order_by_top_level_key}' LIMIT {limit} OFFSET {offset}"
"ORDER BY v::jsonb->>'{order_by_top_level_key}' LIMIT {} OFFSET {offset}",
if *limit > 1024 { 1024 } else { *limit }
)
}
})
@ -171,8 +191,14 @@ pub struct AppDataQuery {
impl Display for AppDataQuery {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&format!(
"SELECT * FROM app_data WHERE app = {} AND v LIKE $1 {}",
"SELECT * FROM app_data WHERE app = {} AND %q% {}",
self.app, self.mode
))
}
}
#[derive(Serialize, Deserialize)]
pub enum AppDataQueryResult {
One(AppData),
Many(Vec<AppData>),
}