collab: Add endpoint for initiating a billing subscription (#15452)

This PR adds a new `POST /billing/subscriptions` endpoint that can be
used to initiate a billing subscription.

The endpoint will use the provided `github_user_id` to look up a user,
generate a Stripe Checkout session, and then return the URL.

The caller would then redirect the user to the URL to initiate the
checkout flow.

Here's an example of how to call it:

```sh
curl -X POST "http://localhost:8080/billing/subscriptions" \
     -H "Authorization: <ADMIN_TOKEN>" \
     -H "Content-Type: application/json" \
     -d '{"github_user_id": 12345}'
```

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-07-29 17:31:36 -04:00 committed by GitHub
parent 8bb34fd93e
commit e15d59c445
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 258 additions and 0 deletions

View file

@ -32,6 +32,26 @@ impl Database {
.await
}
/// Returns all of the billing subscriptions for the user with the specified ID.
///
/// Note that this returns the subscriptions regardless of their status.
/// If you're wanting to check if a use has an active billing subscription,
/// use `get_active_billing_subscriptions` instead.
pub async fn get_billing_subscriptions(
&self,
user_id: UserId,
) -> Result<Vec<billing_subscription::Model>> {
self.transaction(|tx| async move {
let subscriptions = billing_subscription::Entity::find()
.filter(billing_subscription::Column::UserId.eq(user_id))
.all(&*tx)
.await?;
Ok(subscriptions)
})
.await
}
/// Returns all of the active billing subscriptions for the user with the specified ID.
pub async fn get_active_billing_subscriptions(
&self,

View file

@ -61,6 +61,17 @@ impl Database {
.await
}
/// Returns a user by GitHub user ID. There are no access checks here, so this should only be used internally.
pub async fn get_user_by_github_user_id(&self, github_user_id: i32) -> Result<Option<User>> {
self.transaction(|tx| async move {
Ok(user::Entity::find()
.filter(user::Column::GithubUserId.eq(github_user_id))
.one(&*tx)
.await?)
})
.await
}
/// Returns a user by GitHub login. There are no access checks here, so this should only be used internally.
pub async fn get_user_by_github_login(&self, github_login: &str) -> Result<Option<User>> {
self.transaction(|tx| async move {