Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(auth, gateway): use user_id over account_name #1674

Merged
merged 27 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
76273d3
feat(auth): user_id not null, remove migration insertions
jonaro00 Mar 8, 2024
28e82d4
fix(auth): insert user_id on command inserts
jonaro00 Mar 8, 2024
877930f
feat: rename account_name to user_id in most places
jonaro00 Mar 8, 2024
e1c20ba
nits
jonaro00 Mar 8, 2024
a816e73
nit2
jonaro00 Mar 8, 2024
5445696
fix: auth tests almost working
jonaro00 Mar 8, 2024
bcde733
yeet: auth/refresh
jonaro00 Mar 8, 2024
3e205d1
fix: span
jonaro00 Mar 8, 2024
00c3162
fix: auth tests
jonaro00 Mar 8, 2024
8caf01b
feat: set old account name header for tracing in old deployers
jonaro00 Mar 8, 2024
617d9c6
nit: clarify start_last_deploy
jonaro00 Mar 8, 2024
c8fe94b
fix: sql comment
jonaro00 Mar 11, 2024
2900c3d
fix: userid comment
jonaro00 Mar 11, 2024
1edf407
feat(deployer): use claim instead of user id header for tracing
jonaro00 Mar 12, 2024
0be50c3
nit: remove request.path tracing field
jonaro00 Mar 12, 2024
0931bf3
Revert "nit: remove request.path tracing field"
jonaro00 Mar 13, 2024
3c27279
less clone
jonaro00 Mar 13, 2024
30a966d
feat(auth): keep get account by name endpoint
jonaro00 Mar 13, 2024
9f0be65
fmt
jonaro00 Mar 13, 2024
f33f9da
ci: unstable
jonaro00 Mar 13, 2024
443cdc8
clippy
jonaro00 Mar 13, 2024
fa81d18
fix: migration drift fixes
jonaro00 Mar 13, 2024
d702495
fix: migration drift fixes 2
jonaro00 Mar 13, 2024
0e8e6ef
revert: migration drift fixes
jonaro00 Mar 14, 2024
51b1c0c
fix: endpoint ordering
jonaro00 Mar 14, 2024
bc82a89
test: set empty field on endpoint
jonaro00 Mar 15, 2024
b312146
Revert "test: set empty field on endpoint"
jonaro00 Mar 15, 2024
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
Prev Previous commit
Next Next commit
feat(auth): keep get account by name endpoint
  • Loading branch information
jonaro00 committed Mar 13, 2024
commit 30a966dabfd1cbdbd20b102f973a35ff19c6b491
11 changes: 7 additions & 4 deletions auth/src/api/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ use crate::{
};

use super::handlers::{
convert_key, delete_subscription, get_public_key, get_user, post_subscription, post_user,
put_user_reset_key,
convert_key, delete_subscription, get_public_key, get_user, get_user_by_name, post_subscription, post_user, put_user_reset_key
};

pub type UserManagerState = Arc<Box<dyn UserManagement>>;
Expand Down Expand Up @@ -62,11 +61,15 @@ impl Default for ApiBuilder {
impl ApiBuilder {
pub fn new() -> Self {
let router = Router::new()
.route("/", get(|| async move {})) // Health check: 200 OK
// health check: 200 OK
.route("/", get(|| async move {}))
.route("/auth/key", get(convert_key))
.route("/public-key", get(get_public_key))
.route("/users/:user_id", get(get_user))
// users are created based on auth0 name by console
.route("/users/:account_name/:account_tier", post(post_user))
// used by console to get user based on auth0 name
.route("/users/name/:account_name", get(get_user_by_name))
.route("/users/:user_id", get(get_user))
.route("/users/reset-api-key", put(put_user_reset_key))
.route("/users/:user_id/subscribe", post(post_subscription))
.route(
Expand Down
12 changes: 12 additions & 0 deletions auth/src/api/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ pub(crate) async fn get_user(
Ok(Json(user.into()))
}

#[instrument(skip_all, fields(account.name = %account_name, account.user_id = field::Empty))]
pub(crate) async fn get_user_by_name(
_: Admin,
State(user_manager): State<UserManagerState>,
Path(account_name): Path<String>,
) -> Result<Json<user::Response>, Error> {
let user = user_manager.get_user_by_name(&account_name).await?;
Span::current().record("account.user_id", &user.id);

Ok(Json(user.into()))
}

#[instrument(skip_all, fields(account.name = %account_name, account.tier = %account_tier, account.user_id = field::Empty))]
pub(crate) async fn post_user(
_: Admin,
Expand Down
83 changes: 45 additions & 38 deletions auth/src/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,21 @@ use crate::{api::UserManagerState, error::Error};

#[async_trait]
pub trait UserManagement: Send + Sync {
/// Create a user with the given tier
async fn create_user(&self, name: String, tier: AccountTier) -> Result<User, Error>;
/// Create a user with the given auth0 name and tier
async fn create_user(&self, account_name: String, tier: AccountTier) -> Result<User, Error>;

/// Change the tier for a user
async fn update_tier(&self, user_id: &UserId, tier: AccountTier) -> Result<(), Error>;

/// Get a user by their user id
async fn get_user_by_name(&self, account_name: &str) -> Result<User, Error>;
async fn get_user(&self, user_id: UserId) -> Result<User, Error>;

/// Get a user by their api key
async fn get_user_by_key(&self, key: ApiKey) -> Result<User, Error>;

/// Reset the key that belongs to an account
async fn reset_key(&self, user_id: UserId) -> Result<(), Error>;

/// Insert a subscription for an account
async fn insert_subscription(
&self,
user_id: &UserId,
subscription_id: &str,
subscription_type: &models::user::SubscriptionType,
subscription_quantity: i32,
) -> Result<(), Error>;

/// Delete a subscription from an account
async fn delete_subscription(
&self,
user_id: &UserId,
Expand All @@ -58,10 +48,38 @@ pub struct UserManager {
pub stripe_client: stripe::Client,
}

impl UserManager {
/// Add subscriptions to and sync the tier of a user
async fn complete_user(&self, mut user: User) -> Result<User, Error> {
let subscriptions: Vec<Subscription> = sqlx::query_as(
"SELECT subscription_id, type, quantity, created_at, updated_at FROM subscriptions WHERE user_id = $1",
)
.bind(&user.id)
.fetch_all(&self.pool)
.await?;

if !subscriptions.is_empty() {
user.subscriptions = subscriptions;
}

// Sync the user tier based on the subscription validity, if any.
if let Err(err) = user.sync_tier(self).await {
error!(
error = &err as &dyn std::error::Error,
"failed syncing account"
);
return Err(err);
}
debug!("synced account");

Ok(user)
}
}

#[async_trait]
impl UserManagement for UserManager {
async fn create_user(&self, name: String, tier: AccountTier) -> Result<User, Error> {
let user = User::new(name, ApiKey::generate(), tier, vec![]);
async fn create_user(&self, account_name: String, tier: AccountTier) -> Result<User, Error> {
let user = User::new(account_name, ApiKey::generate(), tier, vec![]);

query(
"INSERT INTO users (account_name, key, account_tier, user_id) VALUES ($1, $2, $3, $4)",
Expand Down Expand Up @@ -92,35 +110,24 @@ impl UserManagement for UserManager {
}
}

async fn get_user(&self, user_id: UserId) -> Result<User, Error> {
let mut user: User = sqlx::query_as("SELECT * FROM users WHERE user_id = $1")
.bind(&user_id)
async fn get_user_by_name(&self, account_name: &str) -> Result<User, Error> {
let mut user: User = sqlx::query_as("SELECT * FROM users WHERE account_name = $1")
.bind(&account_name)
.fetch_optional(&self.pool)
.await?
.ok_or(Error::UserNotFound)?;

let subscriptions: Vec<Subscription> = sqlx::query_as(
"SELECT subscription_id, type, quantity, created_at, updated_at FROM subscriptions WHERE user_id = $1",
)
.bind(&user.id)
.fetch_all(&self.pool)
.await?;

if !subscriptions.is_empty() {
user.subscriptions = subscriptions;
}
self.complete_user(user).await
}

// Sync the user tier based on the subscription validity, if any.
if let Err(err) = user.sync_tier(self).await {
error!(
error = &err as &dyn std::error::Error,
"failed syncing account"
);
return Err(err);
}
debug!("synced account");
async fn get_user(&self, user_id: UserId) -> Result<User, Error> {
let user: User = sqlx::query_as("SELECT * FROM users WHERE user_id = $1")
.bind(&user_id)
.fetch_optional(&self.pool)
.await?
.ok_or(Error::UserNotFound)?;

Ok(user)
self.complete_user(user).await
}

async fn get_user_by_key(&self, key: ApiKey) -> Result<User, Error> {
Expand Down