Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ CORS_ORIGINS=https://plus-admin.polyfrost.org,http://localhost:3000,https://stor

OIDC_ISSUER=https://plus-local.lun.re
SPECIAL_CHAT_TARGETS=
SPECIAL_CHAT_AUTO_REPLY=
SPECIAL_CHAT_AUTO_REPLY=
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
DISCORD_REDIRECT_URI=http://localhost:8080/account/links/discord/callback
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ sea-orm-migration = { version = "1.1.14", features = ["sqlx-postgres", "runtime-
[workspace.dependencies.reqwest]
version = "0.13.1"
default-features = false
features = ["charset", "gzip", "deflate", "brotli", "zstd", "json", "query", "rustls-no-provider"]
features = ["charset", "gzip", "deflate", "brotli", "zstd", "json", "query", "form", "rustls-no-provider"]

[workspace.dependencies.rustls]
version = "0.23.35"
Expand Down
38 changes: 38 additions & 0 deletions database/entities/src/entities/linked_account.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions database/entities/src/entities/mod.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions database/entities/src/entities/prelude.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions database/entities/src/entities/sea_orm_active_enums.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions database/migrations/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ mod m20260928_000000_create_player_mods;
mod m20260929_000000_product_for_sale;
mod m20261014_000000_create_dm_delegates;
mod m20261015_000000_create_outfits_and_skins;
mod m20261017_000000_create_linked_accounts;

pub struct Migrator;

Expand Down Expand Up @@ -151,6 +152,7 @@ impl MigratorTrait for Migrator {
Box::new(m20260929_000000_product_for_sale::Migration),
Box::new(m20261014_000000_create_dm_delegates::Migration),
Box::new(m20261015_000000_create_outfits_and_skins::Migration),
Box::new(m20261017_000000_create_linked_accounts::Migration),
]
}
}
100 changes: 100 additions & 0 deletions database/migrations/src/m20261017_000000_create_linked_accounts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use sea_orm_migration::{
prelude::{extension::postgres::Type, *},
sea_orm::{EnumIter, Iterable as _},
};

use crate::m20250917_163702_create_users_table::User;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[derive(DeriveIden)]
pub struct LinkProvider;

#[derive(DeriveIden, EnumIter)]
pub enum LinkProviderVariants {
Discord,
}

/// An external account linked to a player, at most one per provider.
#[derive(DeriveIden)]
pub enum LinkedAccount {
Table,
UserId,
Provider,
ProviderUserId,
/// The provider-side display name as of linking.
Username,
LinkedAt,
}

const PROVIDER_USER_IDX: &str = "linked_account_provider_user_idx";

#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_type(
Type::create()
.as_enum(LinkProvider)
.values(LinkProviderVariants::iter())
.to_owned(),
)
.await?;

manager
.create_table(
Table::create()
.table(LinkedAccount::Table)
.if_not_exists()
.col(ColumnDef::new(LinkedAccount::UserId).integer().not_null())
.col(
ColumnDef::new(LinkedAccount::Provider)
.custom(LinkProvider)
.not_null(),
)
.col(ColumnDef::new(LinkedAccount::ProviderUserId).text().not_null())
.col(ColumnDef::new(LinkedAccount::Username).text())
.col(
ColumnDef::new(LinkedAccount::LinkedAt)
.timestamp_with_time_zone()
.not_null()
.default(Expr::current_timestamp()),
)
.primary_key(
Index::create()
.col(LinkedAccount::UserId)
.col(LinkedAccount::Provider),
)
.foreign_key(
ForeignKey::create()
.from(LinkedAccount::Table, LinkedAccount::UserId)
.to(User::Table, User::Id)
.on_delete(ForeignKeyAction::Cascade),
)
.to_owned(),
)
.await?;

manager
.create_index(
Index::create()
.name(PROVIDER_USER_IDX)
.table(LinkedAccount::Table)
.col(LinkedAccount::Provider)
.col(LinkedAccount::ProviderUserId)
.unique()
.to_owned(),
)
.await
}

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(LinkedAccount::Table).to_owned())
.await?;
manager
.drop_type(Type::drop().name(LinkProvider).to_owned())
.await
}
}
5 changes: 5 additions & 0 deletions src/api/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use crate::{
api_tokens::ApiTokens,
rate_limit::{RateLimiter, RequestLimits},
v0::{
account::links::{self, DiscordOAuth},
cosmetics::CachedAssetInfo,
oidc::{self, AuthorizationCode, OidcSigningKey},
},
Expand Down Expand Up @@ -88,6 +89,8 @@ pub(super) struct ApiState {
pub(super) oidc_codes: Cache<String, AuthorizationCode>,
pub(super) special_chat_targets: Vec<Uuid>,
pub(super) special_chat_auto_reply: Option<String>,
pub(super) discord: Option<DiscordOAuth>,
pub(super) link_states: Cache<String, i32>,
pub(super) instrumentation: Instrumentation,
}

Expand Down Expand Up @@ -156,6 +159,8 @@ impl ApiState {
oidc_codes: oidc::new_authorization_code_cache(),
special_chat_targets: args.special_chat_targets.clone(),
special_chat_auto_reply: args.special_chat_auto_reply.clone(),
discord: DiscordOAuth::from_args(args),
link_states: links::new_link_state_cache(),
instrumentation,
s3_public_url: args.s3_public_url.trim_end_matches('/').into(),
s3_bucket,
Expand Down
Loading
Loading