mirror of
https://forgejo.ellis.link/continuwuation/continuwuity/
synced 2026-07-16 10:19:32 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d50e0f53d2 | |||
| 57e82f1783 | |||
| 1d311073b9 |
@@ -6,18 +6,24 @@
|
|||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn issue_token(&self, expires: super::TokenExpires) -> Result {
|
pub(super) async fn issue_token(&self, expires: super::TokenExpires) -> Result {
|
||||||
let expires = {
|
let expires = {
|
||||||
if expires.immortal {
|
let max_uses = expires.max_uses;
|
||||||
None
|
let max_age = expires
|
||||||
} else if let Some(max_uses) = expires.max_uses {
|
|
||||||
Some(TokenExpires::AfterUses(max_uses))
|
|
||||||
} else if expires.once {
|
|
||||||
Some(TokenExpires::AfterUses(1))
|
|
||||||
} else if let Some(max_age) = expires
|
|
||||||
.max_age
|
.max_age
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(|max_age| utils::time::timepoint_from_now(utils::time::parse_duration(max_age)?))
|
.map(|max_age| utils::time::timepoint_from_now(utils::time::parse_duration(max_age)?))
|
||||||
.transpose()?
|
.transpose()?;
|
||||||
|
|
||||||
|
if expires.immortal {
|
||||||
|
None
|
||||||
|
} else if let Some(max_uses) = max_uses
|
||||||
|
&& let Some(max_age) = max_age
|
||||||
{
|
{
|
||||||
|
Some(TokenExpires::AfterTimeOrUses { max_uses, max_age })
|
||||||
|
} else if let Some(max_uses) = max_uses {
|
||||||
|
Some(TokenExpires::AfterUses(max_uses))
|
||||||
|
} else if expires.once {
|
||||||
|
Some(TokenExpires::AfterUses(1))
|
||||||
|
} else if let Some(max_age) = max_age {
|
||||||
Some(TokenExpires::AfterTime(max_age))
|
Some(TokenExpires::AfterTime(max_age))
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
|
|||||||
@@ -29,23 +29,23 @@ pub enum TokenCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Args)]
|
#[derive(Debug, Args)]
|
||||||
#[group(required = true, multiple = false)]
|
#[group(required = true, multiple = true)]
|
||||||
pub struct TokenExpires {
|
pub struct TokenExpires {
|
||||||
/// The maximum number of times this token is allowed to be used before it
|
/// The maximum number of times this token is allowed to be used before it
|
||||||
/// expires.
|
/// expires.
|
||||||
#[arg(long)]
|
#[arg(long, conflicts_with_all = ["immortal", "once"])]
|
||||||
max_uses: Option<u64>,
|
max_uses: Option<u64>,
|
||||||
|
|
||||||
/// The maximum age of this token (e.g. 30s, 5m, 7d). It will expire after
|
/// The maximum age of this token (e.g. 30s, 5m, 7d). It will expire after
|
||||||
/// this much time has passed.
|
/// this much time has passed.
|
||||||
#[arg(long)]
|
#[arg(long, conflicts_with_all = ["immortal", "once"])]
|
||||||
max_age: Option<String>,
|
max_age: Option<String>,
|
||||||
|
|
||||||
/// This token will never expire.
|
/// This token will never expire.
|
||||||
#[arg(long)]
|
#[arg(long, conflicts_with_all = ["once", "max_uses", "max_age"])]
|
||||||
immortal: bool,
|
immortal: bool,
|
||||||
|
|
||||||
/// A shortcut for `--max-uses 1`.
|
/// A shortcut for `--max-uses 1`.
|
||||||
#[arg(long)]
|
#[arg(long, conflicts_with_all = ["immortal", "max_uses", "max_age"])]
|
||||||
once: bool,
|
once: bool,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ pub fn is_valid(&self) -> bool {
|
|||||||
|
|
||||||
expiry_time >= now
|
expiry_time >= now
|
||||||
},
|
},
|
||||||
|
| Some(TokenExpires::AfterTimeOrUses { max_uses, max_age }) =>
|
||||||
|
self.uses < max_uses && max_age >= SystemTime::now(),
|
||||||
| None => true,
|
| None => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,12 +65,16 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|||||||
pub enum TokenExpires {
|
pub enum TokenExpires {
|
||||||
AfterUses(u64),
|
AfterUses(u64),
|
||||||
AfterTime(SystemTime),
|
AfterTime(SystemTime),
|
||||||
|
AfterTimeOrUses {
|
||||||
|
max_uses: u64,
|
||||||
|
max_age: SystemTime,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for TokenExpires {
|
impl std::fmt::Display for TokenExpires {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
| Self::AfterUses(max_uses) => write!(f, "Expires after {max_uses} uses"),
|
| Self::AfterUses(max_uses) => write!(f, "Expires after {max_uses} use(s)"),
|
||||||
| Self::AfterTime(max_age) => {
|
| Self::AfterTime(max_age) => {
|
||||||
let now = SystemTime::now();
|
let now = SystemTime::now();
|
||||||
let formatted_expiry = utils::time::format(*max_age, "%+");
|
let formatted_expiry = utils::time::format(*max_age, "%+");
|
||||||
@@ -82,6 +88,23 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|||||||
| Err(_) => write!(f, "Expired at {formatted_expiry}"),
|
| Err(_) => write!(f, "Expired at {formatted_expiry}"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
| Self::AfterTimeOrUses { max_uses, max_age } => {
|
||||||
|
if *max_uses == 0 {
|
||||||
|
return write!(f, "Already expired (uses exhausted)");
|
||||||
|
}
|
||||||
|
|
||||||
|
let now = SystemTime::now();
|
||||||
|
let formatted_expiry = utils::time::format(*max_age, "%+");
|
||||||
|
|
||||||
|
match max_age.duration_since(now) {
|
||||||
|
| Ok(duration) => write!(
|
||||||
|
f,
|
||||||
|
"Expires after {max_uses} use(s) or in {} ({formatted_expiry})",
|
||||||
|
utils::time::pretty(duration)
|
||||||
|
),
|
||||||
|
| Err(_) => write!(f, "Expired at {formatted_expiry}"),
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user