Skip to content
Draft
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
34 changes: 31 additions & 3 deletions apps/api/src/auth/guard.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
use crate::responders::ErrorContext;
use gem_auth::{AuthClient, verify_auth_signature};
use primitives::{AuthMessage, AuthenticatedRequest};
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;
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::models::DeviceRow;
use storage::database::devices_sessions::DeviceSessionsStore;
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()));
Expand All @@ -19,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<T> {
Expand Down Expand Up @@ -73,10 +79,32 @@ impl<'r, T: DeserializeOwned + Send> FromData<'r> for Authenticated<T> {
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.clone(),
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"),
};

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() {
return error_outcome(req, Status::InternalServerError, "Failed to store session");
}

Success(Authenticated {
auth: VerifiedAuth {
device,
address: body.auth.address,
wallet_id: wallet.id,
wallet_identifier,
},
data: body.data,
})
Expand Down
14 changes: 3 additions & 11 deletions apps/api/src/referral/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -171,12 +168,7 @@ impl RewardsClient {

pub async fn use_referral_code(&self, auth: &VerifiedAuth, code: &str, ip_address: &str) -> Result<Vec<RewardEvent>, Box<dyn Error + Send + Sync>> {
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);
Expand Down
8 changes: 3 additions & 5 deletions apps/api/src/referral/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -34,12 +34,11 @@ pub async fn get_rewards(wallet: MulticoinParam, client: &State<Mutex<RewardsCli

#[post("/rewards/referrals/create", format = "json", data = "<request>")]
pub async fn create_referral(request: Authenticated<ReferralCode>, ip: std::net::IpAddr, client: &State<Mutex<RewardsClient>>) -> Result<ApiResponse<Rewards>, 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(),
Expand All @@ -52,8 +51,7 @@ pub async fn create_referral(request: Authenticated<ReferralCode>, ip: std::net:
#[allow(dead_code)]
#[post("/rewards/referrals/update", format = "json", data = "<request>")]
pub async fn update_referral(request: Authenticated<ReferralCode>, client: &State<Mutex<RewardsClient>>) -> Result<ApiResponse<Rewards>, 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 = "<request>")]
Expand Down
16 changes: 16 additions & 0 deletions crates/storage/src/database/devices_sessions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::{DatabaseClient, models::*};
use diesel::prelude::*;

pub trait DeviceSessionsStore {
fn add_device_session(&mut self, session: NewDeviceSessionRow) -> Result<DeviceSessionRow, diesel::result::Error>;
}

impl DeviceSessionsStore for DatabaseClient {
fn add_device_session(&mut self, session: NewDeviceSessionRow) -> Result<DeviceSessionRow, diesel::result::Error> {
use crate::schema::devices_sessions::dsl::*;
diesel::insert_into(devices_sessions)
.values(&session)
.returning(DeviceSessionRow::as_returning())
.get_result(&mut self.connection)
}
}
1 change: 1 addition & 0 deletions crates/storage/src/database/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
DROP INDEX IF EXISTS idx_devices_sessions_created_at;
DROP INDEX IF EXISTS idx_devices_sessions_wallet_id;
DROP INDEX IF EXISTS idx_devices_sessions_device_id;
DROP TABLE IF EXISTS devices_sessions;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
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
);

CREATE INDEX idx_devices_sessions_device_id ON devices_sessions (device_id);
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);
24 changes: 24 additions & 0 deletions crates/storage/src/models/device_session.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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 wallet_id: i32,
pub nonce: 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 wallet_id: i32,
pub nonce: String,
pub signature: String,
}
2 changes: 2 additions & 0 deletions crates/storage/src/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
};
Expand Down
16 changes: 16 additions & 0 deletions crates/storage/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,19 @@ diesel::table! {
}
}

diesel::table! {
devices_sessions (id) {
id -> Int4,
device_id -> Int4,
wallet_id -> Int4,
#[max_length = 256]
nonce -> Varchar,
#[max_length = 256]
signature -> Varchar,
created_at -> Timestamp,
}
}

diesel::table! {
fiat_assets (id) {
#[max_length = 128]
Expand Down Expand Up @@ -952,6 +965,8 @@ 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!(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));
Expand Down Expand Up @@ -1025,6 +1040,7 @@ diesel::allow_tables_to_appear_in_same_query!(
charts_hourly,
config,
devices,
devices_sessions,
fiat_assets,
fiat_providers,
fiat_providers_countries,
Expand Down