This commit is contained in:
+64
@@ -17,6 +17,7 @@ pub struct User {
|
||||
email: Option<String>,
|
||||
display_name: Option<String>,
|
||||
avatar_url: Option<String>,
|
||||
telegram_id: Option<String>,
|
||||
role: LimitedString<32>,
|
||||
is_active: bool,
|
||||
}
|
||||
@@ -53,6 +54,7 @@ impl User {
|
||||
email: email.map(str::to_owned),
|
||||
display_name: display_name.map(str::to_owned),
|
||||
avatar_url: None,
|
||||
telegram_id: None,
|
||||
role: LimitedString::new(role).unwrap(),
|
||||
is_active: true,
|
||||
};
|
||||
@@ -75,6 +77,7 @@ impl User {
|
||||
email: email.map(str::to_owned),
|
||||
display_name: display_name.map(str::to_owned),
|
||||
avatar_url: None,
|
||||
telegram_id: None,
|
||||
role: LimitedString::new(role).unwrap(),
|
||||
is_active: true,
|
||||
};
|
||||
@@ -117,6 +120,21 @@ impl User {
|
||||
cot::db::query!(User, $email == Some(email)).get(db).await
|
||||
}
|
||||
|
||||
/// Find a user linked to a non-empty Telegram ID.
|
||||
pub async fn get_by_telegram_id(
|
||||
db: &Database,
|
||||
telegram_id: &str,
|
||||
) -> cot::db::Result<Option<Self>> {
|
||||
let telegram_id = telegram_id.trim();
|
||||
if telegram_id.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
let telegram_id = telegram_id.to_owned();
|
||||
cot::db::query!(User, $telegram_id == Some(telegram_id))
|
||||
.get(db)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Count all users in the database.
|
||||
pub async fn count_all(db: &Database) -> cot::db::Result<u64> {
|
||||
Self::objects().count(db).await
|
||||
@@ -140,6 +158,16 @@ impl User {
|
||||
self.save(db).await
|
||||
}
|
||||
|
||||
/// Store a Telegram link state. `Some("")` means the user declined linking.
|
||||
pub async fn set_telegram_id(
|
||||
&mut self,
|
||||
db: &Database,
|
||||
telegram_id: Option<&str>,
|
||||
) -> cot::db::Result<()> {
|
||||
self.telegram_id = telegram_id.map(str::to_owned);
|
||||
self.save(db).await
|
||||
}
|
||||
|
||||
/// Delete this user by primary key.
|
||||
pub async fn delete_by_id(db: &Database, user_id: i64) -> cot::db::Result<()> {
|
||||
cot::db::query!(User, $id == Auto::Fixed(user_id))
|
||||
@@ -165,6 +193,10 @@ impl User {
|
||||
self.display_name.clone().unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn telegram_id(&self) -> Option<&str> {
|
||||
self.telegram_id.as_deref()
|
||||
}
|
||||
|
||||
pub fn role_str(&self) -> &str {
|
||||
&self.role
|
||||
}
|
||||
@@ -391,9 +423,41 @@ pub mod db_migrations {
|
||||
&[Operation::custom(create_oidc_link_indexes).build()];
|
||||
}
|
||||
|
||||
// -- M0007: Telegram link state on amnezia_fellow__user ----------------
|
||||
|
||||
#[cot::db::migrations::migration_op]
|
||||
async fn add_user_telegram_id(ctx: migrations::MigrationContext<'_>) -> cot::db::Result<()> {
|
||||
ctx.db
|
||||
.raw("ALTER TABLE amnezia_fellow__user ADD COLUMN telegram_id TEXT")
|
||||
.await?;
|
||||
ctx.db
|
||||
.raw(
|
||||
"CREATE UNIQUE INDEX idx_amnezia_fellow_user_telegram_id \
|
||||
ON amnezia_fellow__user (telegram_id) \
|
||||
WHERE telegram_id IS NOT NULL AND telegram_id != ''",
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct M0007UserTelegramId;
|
||||
|
||||
impl migrations::Migration for M0007UserTelegramId {
|
||||
const APP_NAME: &'static str = "amnezia_fellow";
|
||||
const MIGRATION_NAME: &'static str = "m_0007_user_telegram_id";
|
||||
const DEPENDENCIES: &'static [migrations::MigrationDependency] =
|
||||
&[migrations::MigrationDependency::migration(
|
||||
"amnezia_fellow",
|
||||
"m_0004_oidc_link_indexes",
|
||||
)];
|
||||
const OPERATIONS: &'static [Operation] = &[Operation::custom(add_user_telegram_id).build()];
|
||||
}
|
||||
|
||||
pub const MIGRATIONS: &[&SyncDynMigration] = &[
|
||||
&M0002CreateUser,
|
||||
&M0003CreateOidcLink,
|
||||
&M0004OidcLinkIndexes,
|
||||
&M0007UserTelegramId,
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user