add: developer panel
This commit is contained in:
parent
ebded00fd3
commit
39574df691
44 changed files with 982 additions and 84 deletions
|
@ -1,5 +1,6 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use tetratto_shared::{snow::Snowflake, unix_epoch_timestamp};
|
||||
use crate::model::oauth::AppScope;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
pub enum AppQuota {
|
||||
|
@ -33,6 +34,37 @@ pub struct ThirdPartyApp {
|
|||
/// Upon accepting a grant request, the user will be redirected to this URL
|
||||
/// with a query parameter named `token`, which should be saved by the app
|
||||
/// for future authentication.
|
||||
///
|
||||
/// The developer dashboard lists the URL you should send users to in order to
|
||||
/// create a grant on their account in the information section under the label
|
||||
/// "Grant URL".
|
||||
///
|
||||
/// Any search parameters sent with your grant URL (such as an internal user ID)
|
||||
/// will also be sent back when the user is redirected to your redirect URL.
|
||||
///
|
||||
/// You can use this behaviour to keep track of what user you should save the grant
|
||||
/// token under.
|
||||
///
|
||||
/// 1. Redirect user to grant URL with their ID: `{grant_url}?my_app_user_id={id}`
|
||||
/// 2. In your redirect endpoint, read that ID and the added `token` parameter to
|
||||
/// store the `token` under the given `my_app_user_id`
|
||||
///
|
||||
/// The redirect URL will also have a `verifier` search parameter appended.
|
||||
/// This verifier is required to refresh the grant's token (which is what is
|
||||
/// used in the `Atto-Grant` cookie).
|
||||
///
|
||||
/// Tokens only last a week after they were generated (with the verifier),
|
||||
/// but you can refresh them by sending a request to:
|
||||
/// `{tetratto}/api/v1/auth/user/{user_id}/grants/{app_id}/refresh`.
|
||||
///
|
||||
/// Tetratto will generate the verifier and challenge for you. The challenge
|
||||
/// is an SHA-256 hashed + base64 url encoded version of the verifier. This means
|
||||
/// if the verifier doesn't match, it won't pass the challenge.
|
||||
///
|
||||
/// Requests to API endpoints using your grant token should be sent with a
|
||||
/// cookie (in the `Cookie` header) named `Atto-Grant`. This cookie should
|
||||
/// contain the token you received from either the initial connection,
|
||||
/// or a token refresh.
|
||||
pub redirect: String,
|
||||
/// The app's quota status, which determines how many grants the app is allowed to maintain.
|
||||
pub quota_status: AppQuota,
|
||||
|
@ -40,6 +72,15 @@ pub struct ThirdPartyApp {
|
|||
pub banned: bool,
|
||||
/// The number of accepted grants the app maintains.
|
||||
pub grants: usize,
|
||||
/// The scopes used for every grant the app maintains.
|
||||
///
|
||||
/// These scopes are only cloned into **new** grants created for the app.
|
||||
/// An app *cannot* change scopes and have them affect users who already have the
|
||||
/// app connected. Users must delete the app's grant and authenticate it again
|
||||
/// to update their scopes.
|
||||
///
|
||||
/// Your app should handle informing users when scopes change.
|
||||
pub scopes: Vec<AppScope>,
|
||||
}
|
||||
|
||||
impl ThirdPartyApp {
|
||||
|
@ -47,7 +88,7 @@ impl ThirdPartyApp {
|
|||
pub fn new(title: String, owner: usize, homepage: String, redirect: String) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
owner,
|
||||
title,
|
||||
homepage,
|
||||
|
@ -55,6 +96,7 @@ impl ThirdPartyApp {
|
|||
quota_status: AppQuota::Limited,
|
||||
banned: false,
|
||||
grants: 0,
|
||||
scopes: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -251,7 +251,7 @@ impl User {
|
|||
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
username,
|
||||
password,
|
||||
salt,
|
||||
|
@ -262,7 +262,7 @@ impl User {
|
|||
notification_count: 0,
|
||||
follower_count: 0,
|
||||
following_count: 0,
|
||||
last_seen: unix_epoch_timestamp() as usize,
|
||||
last_seen: unix_epoch_timestamp(),
|
||||
totp: String::new(),
|
||||
recovery_codes: Vec::new(),
|
||||
post_count: 0,
|
||||
|
@ -312,7 +312,7 @@ impl User {
|
|||
(
|
||||
ip.to_string(),
|
||||
tetratto_shared::hash::hash(unhashed),
|
||||
unix_epoch_timestamp() as usize,
|
||||
unix_epoch_timestamp(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
@ -460,7 +460,7 @@ impl Notification {
|
|||
pub fn new(title: String, content: String, owner: usize) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
title,
|
||||
content,
|
||||
owner,
|
||||
|
@ -483,7 +483,7 @@ impl UserFollow {
|
|||
pub fn new(initiator: usize, receiver: usize) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
initiator,
|
||||
receiver,
|
||||
}
|
||||
|
@ -511,7 +511,7 @@ impl UserBlock {
|
|||
pub fn new(initiator: usize, receiver: usize) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
initiator,
|
||||
receiver,
|
||||
}
|
||||
|
@ -531,7 +531,7 @@ impl IpBlock {
|
|||
pub fn new(initiator: usize, receiver: String) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
initiator,
|
||||
receiver,
|
||||
}
|
||||
|
@ -551,7 +551,7 @@ impl IpBan {
|
|||
pub fn new(ip: String, moderator: usize, reason: String) -> Self {
|
||||
Self {
|
||||
ip,
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
reason,
|
||||
moderator,
|
||||
}
|
||||
|
@ -572,7 +572,7 @@ impl UserWarning {
|
|||
pub fn new(user: usize, moderator: usize, content: String) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
receiver: user,
|
||||
moderator,
|
||||
content,
|
||||
|
|
|
@ -33,7 +33,7 @@ impl Channel {
|
|||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
community,
|
||||
owner,
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
minimum_role_read: (CommunityPermission::DEFAULT | CommunityPermission::MEMBER).bits(),
|
||||
minimum_role_write: (CommunityPermission::DEFAULT | CommunityPermission::MEMBER).bits(),
|
||||
position,
|
||||
|
@ -78,7 +78,7 @@ pub struct Message {
|
|||
|
||||
impl Message {
|
||||
pub fn new(channel: usize, owner: usize, content: String) -> Self {
|
||||
let now = unix_epoch_timestamp() as usize;
|
||||
let now = unix_epoch_timestamp();
|
||||
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
|
|
|
@ -33,7 +33,7 @@ impl Community {
|
|||
pub fn new(title: String, owner: usize) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
title: title.clone(),
|
||||
context: CommunityContext {
|
||||
display_name: title,
|
||||
|
@ -157,7 +157,7 @@ impl CommunityMembership {
|
|||
pub fn new(owner: usize, community: usize, role: CommunityPermission) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
owner,
|
||||
community,
|
||||
role,
|
||||
|
@ -273,7 +273,7 @@ impl Post {
|
|||
) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
content,
|
||||
owner,
|
||||
community,
|
||||
|
@ -353,7 +353,7 @@ impl Question {
|
|||
) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
owner,
|
||||
receiver,
|
||||
content,
|
||||
|
@ -387,7 +387,7 @@ impl PostDraft {
|
|||
pub fn new(content: String, owner: usize) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
content,
|
||||
owner,
|
||||
}
|
||||
|
@ -426,7 +426,7 @@ impl Poll {
|
|||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
owner,
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
expires,
|
||||
// options
|
||||
option_a,
|
||||
|
@ -491,7 +491,7 @@ impl PollVote {
|
|||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
owner,
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
poll_id,
|
||||
vote,
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use serde::{
|
|||
};
|
||||
|
||||
bitflags! {
|
||||
/// Fine-grained journal permissions built using bitwise operations.
|
||||
/// Fine-grained community permissions built using bitwise operations.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct CommunityPermission: u32 {
|
||||
const DEFAULT = 1 << 0;
|
||||
|
|
|
@ -16,7 +16,7 @@ impl AuditLogEntry {
|
|||
pub fn new(moderator: usize, content: String) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
moderator,
|
||||
content,
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ impl Report {
|
|||
pub fn new(owner: usize, content: String, asset: usize, asset_type: AssetType) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
owner,
|
||||
content,
|
||||
asset,
|
||||
|
|
|
@ -5,7 +5,6 @@ use super::{Result, Error};
|
|||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AuthGrant {
|
||||
pub id: usize,
|
||||
/// The ID of the application associated with this grant.
|
||||
pub app: usize,
|
||||
/// The code challenge for PKCE verifiers associated with this grant.
|
||||
|
@ -22,6 +21,9 @@ pub struct AuthGrant {
|
|||
/// The access token associated with the account. This is **not** the same as
|
||||
/// regular account access tokens, as the token can only be used with the requested `scopes`.
|
||||
pub token: String,
|
||||
/// The time in which the token was last refreshed. Tokens should stop being
|
||||
/// accepted after a week has passed since this time.
|
||||
pub last_updated: usize,
|
||||
/// Scopes define what the grant's token is actually allowed to do.
|
||||
///
|
||||
/// No scope shall ever be allowed to change scopes or manage grants on behalf of the user.
|
||||
|
|
|
@ -29,7 +29,7 @@ impl Reaction {
|
|||
pub fn new(owner: usize, asset: usize, asset_type: AssetType, is_like: bool) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
owner,
|
||||
asset,
|
||||
asset_type,
|
||||
|
|
|
@ -33,7 +33,7 @@ impl ActionRequest {
|
|||
pub fn new(owner: usize, action_type: ActionType, linked_asset: usize) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
owner,
|
||||
action_type,
|
||||
linked_asset,
|
||||
|
@ -44,7 +44,7 @@ impl ActionRequest {
|
|||
pub fn with_id(id: usize, owner: usize, action_type: ActionType, linked_asset: usize) -> Self {
|
||||
Self {
|
||||
id,
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
owner,
|
||||
action_type,
|
||||
linked_asset,
|
||||
|
|
|
@ -60,7 +60,7 @@ impl UserStack {
|
|||
pub fn new(name: String, owner: usize, users: Vec<usize>) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
owner,
|
||||
name,
|
||||
users,
|
||||
|
|
|
@ -48,7 +48,7 @@ impl MediaUpload {
|
|||
pub fn new(what: MediaType, owner: usize) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
owner,
|
||||
what,
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ impl CustomEmoji {
|
|||
) -> Self {
|
||||
Self {
|
||||
id: Snowflake::new().to_string().parse::<usize>().unwrap(),
|
||||
created: unix_epoch_timestamp() as usize,
|
||||
created: unix_epoch_timestamp(),
|
||||
owner,
|
||||
community,
|
||||
upload_id,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue