From cf5c6c2e8e6df4693ede59ec6342de4bcd2b8770 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 05:14:56 +0000 Subject: [PATCH 1/5] Initial plan From 773363544222a316b9a0e9991ef86da6a6ac7753 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 05:23:35 +0000 Subject: [PATCH 2/5] Add devices_sessions table and auth guard integration Co-authored-by: gemcoder21 <104884878+gemcoder21@users.noreply.github.com> --- apps/api/src/auth/guard.rs | 12 +++++++++- .../storage/src/database/devices_sessions.rs | 16 ++++++++++++++ crates/storage/src/database/mod.rs | 1 + .../down.sql | 4 ++++ .../2026-01-28-052000_devices_sessions/up.sql | 11 ++++++++++ crates/storage/src/models/device_session.rs | 22 +++++++++++++++++++ crates/storage/src/models/mod.rs | 2 ++ crates/storage/src/schema.rs | 14 ++++++++++++ 8 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 crates/storage/src/database/devices_sessions.rs create mode 100644 crates/storage/src/migrations/2026-01-28-052000_devices_sessions/down.sql create mode 100644 crates/storage/src/migrations/2026-01-28-052000_devices_sessions/up.sql create mode 100644 crates/storage/src/models/device_session.rs diff --git a/apps/api/src/auth/guard.rs b/apps/api/src/auth/guard.rs index 64f6e28d5..1c94499b1 100644 --- a/apps/api/src/auth/guard.rs +++ b/apps/api/src/auth/guard.rs @@ -9,7 +9,8 @@ use serde::de::DeserializeOwned; use std::sync::Arc; use storage::Database; use storage::database::devices::DevicesStore; -use storage::models::DeviceRow; +use storage::database::devices_sessions::DeviceSessionsStore; +use storage::models::{DeviceRow, NewDeviceSessionRow}; fn error_outcome<'r, T>(req: &'r Request<'_>, status: Status, message: &str) -> Outcome<'r, T, String> { req.local_cache(|| ErrorContext(message.to_string())); @@ -73,6 +74,15 @@ impl<'r, T: DeserializeOwned + Send> FromData<'r> for Authenticated { return error_outcome(req, Status::InternalServerError, "Failed to invalidate nonce"); } + let session = NewDeviceSessionRow { + device_id: device.id, + address: body.auth.address.clone(), + signature: body.auth.signature.clone(), + }; + if DeviceSessionsStore::add_device_session(&mut db_client, session).is_err() { + return error_outcome(req, Status::InternalServerError, "Failed to store session"); + } + Success(Authenticated { auth: VerifiedAuth { device, diff --git a/crates/storage/src/database/devices_sessions.rs b/crates/storage/src/database/devices_sessions.rs new file mode 100644 index 000000000..734686ba6 --- /dev/null +++ b/crates/storage/src/database/devices_sessions.rs @@ -0,0 +1,16 @@ +use crate::{DatabaseClient, models::*}; +use diesel::prelude::*; + +pub trait DeviceSessionsStore { + fn add_device_session(&mut self, session: NewDeviceSessionRow) -> Result; +} + +impl DeviceSessionsStore for DatabaseClient { + fn add_device_session(&mut self, session: NewDeviceSessionRow) -> Result { + use crate::schema::devices_sessions::dsl::*; + diesel::insert_into(devices_sessions) + .values(&session) + .returning(DeviceSessionRow::as_returning()) + .get_result(&mut self.connection) + } +} diff --git a/crates/storage/src/database/mod.rs b/crates/storage/src/database/mod.rs index 10520e4c8..7a4f5f869 100644 --- a/crates/storage/src/database/mod.rs +++ b/crates/storage/src/database/mod.rs @@ -7,6 +7,7 @@ pub mod chains; pub mod charts; pub mod config; pub mod devices; +pub mod devices_sessions; pub mod fiat; pub mod migrations; pub mod nft; diff --git a/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/down.sql b/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/down.sql new file mode 100644 index 000000000..3c5b580de --- /dev/null +++ b/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/down.sql @@ -0,0 +1,4 @@ +DROP INDEX IF EXISTS idx_devices_sessions_created_at; +DROP INDEX IF EXISTS idx_devices_sessions_address; +DROP INDEX IF EXISTS idx_devices_sessions_device_id; +DROP TABLE IF EXISTS devices_sessions; diff --git a/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/up.sql b/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/up.sql new file mode 100644 index 000000000..33b61f96f --- /dev/null +++ b/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/up.sql @@ -0,0 +1,11 @@ +CREATE TABLE devices_sessions ( + id SERIAL PRIMARY KEY, + device_id INT NOT NULL REFERENCES devices(id) ON DELETE CASCADE, + address VARCHAR(256) NOT NULL, + signature VARCHAR(256) NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT current_timestamp +); + +CREATE INDEX idx_devices_sessions_device_id ON devices_sessions (device_id); +CREATE INDEX idx_devices_sessions_address ON devices_sessions (address); +CREATE INDEX idx_devices_sessions_created_at ON devices_sessions (created_at DESC); diff --git a/crates/storage/src/models/device_session.rs b/crates/storage/src/models/device_session.rs new file mode 100644 index 000000000..691b5e225 --- /dev/null +++ b/crates/storage/src/models/device_session.rs @@ -0,0 +1,22 @@ +use chrono::NaiveDateTime; +use diesel::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Queryable, Selectable, Serialize, Deserialize, Insertable, Clone)] +#[diesel(table_name = crate::schema::devices_sessions)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct DeviceSessionRow { + pub id: i32, + pub device_id: i32, + pub address: String, + pub signature: String, + pub created_at: NaiveDateTime, +} + +#[derive(Debug, Insertable, Clone)] +#[diesel(table_name = crate::schema::devices_sessions)] +pub struct NewDeviceSessionRow { + pub device_id: i32, + pub address: String, + pub signature: String, +} diff --git a/crates/storage/src/models/mod.rs b/crates/storage/src/models/mod.rs index 9f1044d94..b6a2211b2 100644 --- a/crates/storage/src/models/mod.rs +++ b/crates/storage/src/models/mod.rs @@ -5,6 +5,7 @@ pub mod chain; pub mod chart; pub mod config; pub mod device; +pub mod device_session; pub mod fiat; pub mod nft_asset; pub mod nft_collection; @@ -34,6 +35,7 @@ pub use self::chain::ChainRow; pub use self::chart::{ChartRow, DailyChartRow, HourlyChartRow}; pub use self::config::ConfigRow; pub use self::device::{DeviceRow, UpdateDeviceRow}; +pub use self::device_session::{DeviceSessionRow, NewDeviceSessionRow}; pub use self::fiat::{ FiatAssetRow, FiatProviderCountryRow, FiatProviderRow, FiatQuoteRequestRow, FiatQuoteRow, FiatRateRow, FiatTransactionRow, FiatTransactionUpdateRow, NewFiatWebhookRow, }; diff --git a/crates/storage/src/schema.rs b/crates/storage/src/schema.rs index cee0aaef2..7373be8f2 100644 --- a/crates/storage/src/schema.rs +++ b/crates/storage/src/schema.rs @@ -234,6 +234,18 @@ diesel::table! { } } +diesel::table! { + devices_sessions (id) { + id -> Int4, + device_id -> Int4, + #[max_length = 256] + address -> Varchar, + #[max_length = 256] + signature -> Varchar, + created_at -> Timestamp, + } +} + diesel::table! { fiat_assets (id) { #[max_length = 128] @@ -952,6 +964,7 @@ diesel::joinable!(charts -> prices (coin_id)); diesel::joinable!(charts_daily -> prices (coin_id)); diesel::joinable!(charts_hourly -> prices (coin_id)); diesel::joinable!(devices -> fiat_rates (currency)); +diesel::joinable!(devices_sessions -> devices (device_id)); diesel::joinable!(fiat_assets -> assets (asset_id)); diesel::joinable!(fiat_assets -> fiat_providers (provider)); diesel::joinable!(fiat_providers_countries -> fiat_providers (provider)); @@ -1025,6 +1038,7 @@ diesel::allow_tables_to_appear_in_same_query!( charts_hourly, config, devices, + devices_sessions, fiat_assets, fiat_providers, fiat_providers_countries, From a0c6e9c1ea2549d3efe7060839f07ad905c9d2bb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 17:01:33 +0000 Subject: [PATCH 3/5] Change devices_sessions to use wallet_id FK instead of address Co-authored-by: gemcoder21 <104884878+gemcoder21@users.noreply.github.com> --- apps/api/src/auth/guard.rs | 19 +++++++++++++++---- .../down.sql | 2 +- .../2026-01-28-052000_devices_sessions/up.sql | 4 ++-- crates/storage/src/models/device_session.rs | 4 ++-- crates/storage/src/schema.rs | 4 ++-- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/apps/api/src/auth/guard.rs b/apps/api/src/auth/guard.rs index 1c94499b1..e83da598b 100644 --- a/apps/api/src/auth/guard.rs +++ b/apps/api/src/auth/guard.rs @@ -1,16 +1,17 @@ use crate::responders::ErrorContext; use gem_auth::{AuthClient, verify_auth_signature}; -use primitives::{AuthMessage, AuthenticatedRequest}; +use primitives::{AuthMessage, AuthenticatedRequest, WalletId}; use rocket::data::{FromData, Outcome, ToByteUnit}; use rocket::http::Status; use rocket::outcome::Outcome::{Error, Success}; use rocket::{Data, Request, State}; use serde::de::DeserializeOwned; use std::sync::Arc; -use storage::Database; use storage::database::devices::DevicesStore; use storage::database::devices_sessions::DeviceSessionsStore; -use storage::models::{DeviceRow, NewDeviceSessionRow}; +use storage::models::{DeviceRow, NewDeviceSessionRow, NewWalletRow}; +use storage::repositories::wallets_repository::WalletsRepository; +use storage::{Database, WalletSource, WalletType}; fn error_outcome<'r, T>(req: &'r Request<'_>, status: Status, message: &str) -> Outcome<'r, T, String> { req.local_cache(|| ErrorContext(message.to_string())); @@ -74,9 +75,19 @@ impl<'r, T: DeserializeOwned + Send> FromData<'r> for Authenticated { return error_outcome(req, Status::InternalServerError, "Failed to invalidate nonce"); } + let wallet_identifier = WalletId::Multicoin(body.auth.address.clone()).id(); + let wallet = match db_client.get_or_create_wallet(NewWalletRow { + identifier: wallet_identifier, + wallet_type: WalletType(primitives::WalletType::Multicoin), + source: WalletSource(primitives::WalletSource::Import), + }) { + Ok(w) => w, + Err(_) => return error_outcome(req, Status::InternalServerError, "Failed to get or create wallet"), + }; + let session = NewDeviceSessionRow { device_id: device.id, - address: body.auth.address.clone(), + wallet_id: wallet.id, signature: body.auth.signature.clone(), }; if DeviceSessionsStore::add_device_session(&mut db_client, session).is_err() { diff --git a/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/down.sql b/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/down.sql index 3c5b580de..230cca8d3 100644 --- a/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/down.sql +++ b/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/down.sql @@ -1,4 +1,4 @@ DROP INDEX IF EXISTS idx_devices_sessions_created_at; -DROP INDEX IF EXISTS idx_devices_sessions_address; +DROP INDEX IF EXISTS idx_devices_sessions_wallet_id; DROP INDEX IF EXISTS idx_devices_sessions_device_id; DROP TABLE IF EXISTS devices_sessions; diff --git a/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/up.sql b/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/up.sql index 33b61f96f..eb60d9b93 100644 --- a/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/up.sql +++ b/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/up.sql @@ -1,11 +1,11 @@ CREATE TABLE devices_sessions ( id SERIAL PRIMARY KEY, device_id INT NOT NULL REFERENCES devices(id) ON DELETE CASCADE, - address VARCHAR(256) NOT NULL, + wallet_id INT NOT NULL REFERENCES wallets(id) ON DELETE CASCADE, signature VARCHAR(256) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT current_timestamp ); CREATE INDEX idx_devices_sessions_device_id ON devices_sessions (device_id); -CREATE INDEX idx_devices_sessions_address ON devices_sessions (address); +CREATE INDEX idx_devices_sessions_wallet_id ON devices_sessions (wallet_id); CREATE INDEX idx_devices_sessions_created_at ON devices_sessions (created_at DESC); diff --git a/crates/storage/src/models/device_session.rs b/crates/storage/src/models/device_session.rs index 691b5e225..1cfd460a9 100644 --- a/crates/storage/src/models/device_session.rs +++ b/crates/storage/src/models/device_session.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; pub struct DeviceSessionRow { pub id: i32, pub device_id: i32, - pub address: String, + pub wallet_id: i32, pub signature: String, pub created_at: NaiveDateTime, } @@ -17,6 +17,6 @@ pub struct DeviceSessionRow { #[diesel(table_name = crate::schema::devices_sessions)] pub struct NewDeviceSessionRow { pub device_id: i32, - pub address: String, + pub wallet_id: i32, pub signature: String, } diff --git a/crates/storage/src/schema.rs b/crates/storage/src/schema.rs index 7373be8f2..572212dea 100644 --- a/crates/storage/src/schema.rs +++ b/crates/storage/src/schema.rs @@ -238,8 +238,7 @@ diesel::table! { devices_sessions (id) { id -> Int4, device_id -> Int4, - #[max_length = 256] - address -> Varchar, + wallet_id -> Int4, #[max_length = 256] signature -> Varchar, created_at -> Timestamp, @@ -965,6 +964,7 @@ diesel::joinable!(charts_daily -> prices (coin_id)); diesel::joinable!(charts_hourly -> prices (coin_id)); diesel::joinable!(devices -> fiat_rates (currency)); diesel::joinable!(devices_sessions -> devices (device_id)); +diesel::joinable!(devices_sessions -> wallets (wallet_id)); diesel::joinable!(fiat_assets -> assets (asset_id)); diesel::joinable!(fiat_assets -> fiat_providers (provider)); diesel::joinable!(fiat_providers_countries -> fiat_providers (provider)); From 23b757e7f0deb356fa1bc689760ee2784bc73440 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 17:08:31 +0000 Subject: [PATCH 4/5] Plan comprehensive refactor for reusability and completeness Co-authored-by: gemcoder21 <104884878+gemcoder21@users.noreply.github.com> --- apps/api/src/auth/guard.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/api/src/auth/guard.rs b/apps/api/src/auth/guard.rs index e83da598b..7aa714fa8 100644 --- a/apps/api/src/auth/guard.rs +++ b/apps/api/src/auth/guard.rs @@ -1,5 +1,7 @@ use crate::responders::ErrorContext; use gem_auth::{AuthClient, verify_auth_signature}; +use primitives::WalletSource as PrimitiveWalletSource; +use primitives::WalletType as PrimitiveWalletType; use primitives::{AuthMessage, AuthenticatedRequest, WalletId}; use rocket::data::{FromData, Outcome, ToByteUnit}; use rocket::http::Status; @@ -78,8 +80,8 @@ impl<'r, T: DeserializeOwned + Send> FromData<'r> for Authenticated { let wallet_identifier = WalletId::Multicoin(body.auth.address.clone()).id(); let wallet = match db_client.get_or_create_wallet(NewWalletRow { identifier: wallet_identifier, - wallet_type: WalletType(primitives::WalletType::Multicoin), - source: WalletSource(primitives::WalletSource::Import), + wallet_type: WalletType(PrimitiveWalletType::Multicoin), + source: WalletSource(PrimitiveWalletSource::Import), }) { Ok(w) => w, Err(_) => return error_outcome(req, Status::InternalServerError, "Failed to get or create wallet"), From 59f96a6374bb9b486e5d9ed0a178356f33a2a3f5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 17:11:53 +0000 Subject: [PATCH 5/5] Refactor for reusability: add wallet to auth, store nonce, fix imports Co-authored-by: gemcoder21 <104884878+gemcoder21@users.noreply.github.com> --- apps/api/src/auth/guard.rs | 7 ++++++- apps/api/src/referral/client.rs | 14 +++----------- apps/api/src/referral/mod.rs | 8 +++----- .../2026-01-28-052000_devices_sessions/up.sql | 1 + crates/storage/src/models/device_session.rs | 2 ++ crates/storage/src/schema.rs | 2 ++ 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/api/src/auth/guard.rs b/apps/api/src/auth/guard.rs index 7aa714fa8..60e81510f 100644 --- a/apps/api/src/auth/guard.rs +++ b/apps/api/src/auth/guard.rs @@ -23,6 +23,8 @@ fn error_outcome<'r, T>(req: &'r Request<'_>, status: Status, message: &str) -> pub struct VerifiedAuth { pub device: DeviceRow, pub address: String, + pub wallet_id: i32, + pub wallet_identifier: String, } pub struct Authenticated { @@ -79,7 +81,7 @@ impl<'r, T: DeserializeOwned + Send> FromData<'r> for Authenticated { let wallet_identifier = WalletId::Multicoin(body.auth.address.clone()).id(); let wallet = match db_client.get_or_create_wallet(NewWalletRow { - identifier: wallet_identifier, + identifier: wallet_identifier.clone(), wallet_type: WalletType(PrimitiveWalletType::Multicoin), source: WalletSource(PrimitiveWalletSource::Import), }) { @@ -90,6 +92,7 @@ impl<'r, T: DeserializeOwned + Send> FromData<'r> for Authenticated { let session = NewDeviceSessionRow { device_id: device.id, wallet_id: wallet.id, + nonce: body.auth.nonce.clone(), signature: body.auth.signature.clone(), }; if DeviceSessionsStore::add_device_session(&mut db_client, session).is_err() { @@ -100,6 +103,8 @@ impl<'r, T: DeserializeOwned + Send> FromData<'r> for Authenticated { auth: VerifiedAuth { device, address: body.auth.address, + wallet_id: wallet.id, + wallet_identifier, }, data: body.data, }) diff --git a/apps/api/src/referral/client.rs b/apps/api/src/referral/client.rs index 0dc2bbaec..33453347d 100644 --- a/apps/api/src/referral/client.rs +++ b/apps/api/src/referral/client.rs @@ -3,11 +3,8 @@ use std::error::Error; use api_connector::PusherClient; use gem_rewards::{IpSecurityClient, ReferralError, RewardsError, RiskScoreConfig, RiskScoringInput, UsernameError, evaluate_risk}; use primitives::rewards::{RewardRedemptionOption, RewardStatus}; -use primitives::{ConfigKey, IpUsageType, Localize, NaiveDateTimeExt, Platform, ReferralAllowance, ReferralLeaderboard, ReferralQuota, RewardEvent, Rewards, WalletId, now}; -use storage::{ - ConfigCacher, Database, NewWalletRow, ReferralValidationError, RewardsRedemptionsRepository, RewardsRepository, RiskSignalsRepository, WalletSource, WalletType, - WalletsRepository, -}; +use primitives::{ConfigKey, IpUsageType, Localize, NaiveDateTimeExt, Platform, ReferralAllowance, ReferralLeaderboard, ReferralQuota, RewardEvent, Rewards, now}; +use storage::{ConfigCacher, Database, ReferralValidationError, RewardsRedemptionsRepository, RewardsRepository, RiskSignalsRepository, WalletsRepository}; use streamer::{RewardsNotificationPayload, StreamProducer, StreamProducerQueue}; use crate::auth::VerifiedAuth; @@ -171,12 +168,7 @@ impl RewardsClient { pub async fn use_referral_code(&self, auth: &VerifiedAuth, code: &str, ip_address: &str) -> Result, Box> { let locale = auth.device.locale.as_str(); - let wallet_identifier = WalletId::Multicoin(auth.address.clone()).id(); - let wallet = self.db.wallets()?.get_or_create_wallet(NewWalletRow { - identifier: wallet_identifier, - wallet_type: WalletType::Multicoin, - source: WalletSource::Import, - })?; + let wallet = self.db.wallets()?.get_wallet_by_id(auth.wallet_id)?; let referrer_username = self.db.rewards()?.get_referral_code(code)?.ok_or_else(|| { let error = ReferralError::from(ReferralValidationError::CodeDoesNotExist); diff --git a/apps/api/src/referral/mod.rs b/apps/api/src/referral/mod.rs index d0dd1b0c7..60156358d 100644 --- a/apps/api/src/referral/mod.rs +++ b/apps/api/src/referral/mod.rs @@ -8,7 +8,7 @@ use crate::auth::Authenticated; use crate::params::MulticoinParam; use crate::responders::{ApiError, ApiResponse}; use primitives::rewards::{RedemptionRequest, RedemptionResult, RewardRedemptionOption}; -use primitives::{ReferralCode, ReferralLeaderboard, RewardEvent, Rewards, WalletId}; +use primitives::{ReferralCode, ReferralLeaderboard, RewardEvent, Rewards}; use rocket::{State, get, post}; use tokio::sync::Mutex; @@ -34,12 +34,11 @@ pub async fn get_rewards(wallet: MulticoinParam, client: &State, ip: std::net::IpAddr, client: &State>) -> Result, ApiError> { - let wallet_identifier = WalletId::Multicoin(request.auth.address.clone()).id(); Ok(client .lock() .await .create_username( - &wallet_identifier, + &request.auth.wallet_identifier, &request.data.code, request.auth.device.id, &ip.to_string(), @@ -52,8 +51,7 @@ pub async fn create_referral(request: Authenticated, ip: std::net: #[allow(dead_code)] #[post("/rewards/referrals/update", format = "json", data = "")] pub async fn update_referral(request: Authenticated, client: &State>) -> Result, ApiError> { - let wallet_identifier = WalletId::Multicoin(request.auth.address.clone()).id(); - Ok(client.lock().await.change_username(&wallet_identifier, &request.data.code)?.into()) + Ok(client.lock().await.change_username(&request.auth.wallet_identifier, &request.data.code)?.into()) } #[post("/rewards/referrals/use", format = "json", data = "")] diff --git a/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/up.sql b/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/up.sql index eb60d9b93..93c34625a 100644 --- a/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/up.sql +++ b/crates/storage/src/migrations/2026-01-28-052000_devices_sessions/up.sql @@ -2,6 +2,7 @@ CREATE TABLE devices_sessions ( id SERIAL PRIMARY KEY, device_id INT NOT NULL REFERENCES devices(id) ON DELETE CASCADE, wallet_id INT NOT NULL REFERENCES wallets(id) ON DELETE CASCADE, + nonce VARCHAR(256) NOT NULL, signature VARCHAR(256) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT current_timestamp ); diff --git a/crates/storage/src/models/device_session.rs b/crates/storage/src/models/device_session.rs index 1cfd460a9..481f6028d 100644 --- a/crates/storage/src/models/device_session.rs +++ b/crates/storage/src/models/device_session.rs @@ -9,6 +9,7 @@ pub struct DeviceSessionRow { pub id: i32, pub device_id: i32, pub wallet_id: i32, + pub nonce: String, pub signature: String, pub created_at: NaiveDateTime, } @@ -18,5 +19,6 @@ pub struct DeviceSessionRow { pub struct NewDeviceSessionRow { pub device_id: i32, pub wallet_id: i32, + pub nonce: String, pub signature: String, } diff --git a/crates/storage/src/schema.rs b/crates/storage/src/schema.rs index 572212dea..01e779194 100644 --- a/crates/storage/src/schema.rs +++ b/crates/storage/src/schema.rs @@ -240,6 +240,8 @@ diesel::table! { device_id -> Int4, wallet_id -> Int4, #[max_length = 256] + nonce -> Varchar, + #[max_length = 256] signature -> Varchar, created_at -> Timestamp, }