add: developer pass
This commit is contained in:
parent
636ecce9f4
commit
02f3d08926
14 changed files with 355 additions and 101 deletions
|
@ -194,22 +194,30 @@ pub struct StripeConfig {
|
|||
///
|
||||
/// <https://docs.stripe.com/no-code/customer-portal>
|
||||
pub billing_portal_url: String,
|
||||
/// The text representation of the price of supporter. (like `$4 USD`)
|
||||
pub supporter_price_text: String,
|
||||
/// The text representation of prices. (like `$4 USD`)
|
||||
pub price_texts: StripePriceTexts,
|
||||
/// Product IDs from the Stripe dashboard.
|
||||
///
|
||||
/// These are checked when we receive a webhook to ensure we provide the correct product.
|
||||
pub product_ids: StripeProductIds,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, Default)]
|
||||
pub struct StripePriceTexts {
|
||||
pub supporter: String,
|
||||
pub dev_pass: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, Default)]
|
||||
pub struct StripePaymentLinks {
|
||||
pub supporter: String,
|
||||
pub dev_pass: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, Default)]
|
||||
pub struct StripeProductIds {
|
||||
pub supporter: String,
|
||||
pub dev_pass: String,
|
||||
}
|
||||
|
||||
/// Manuals config (search help, etc)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use oiseau::cache::Cache;
|
||||
use crate::model::apps::{AppDataQuery, AppDataQueryResult, AppDataSelectMode, AppDataSelectQuery};
|
||||
use crate::model::apps::{AppDataQuery, AppDataQueryResult, AppDataSelectMode};
|
||||
use crate::model::{apps::AppData, permissions::FinePermission, Error, Result};
|
||||
use crate::{auto_method, DataManager};
|
||||
use oiseau::{PostgresRow, execute, get, query_row, query_rows, params};
|
||||
|
@ -51,13 +51,7 @@ impl DataManager {
|
|||
Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
|
||||
};
|
||||
|
||||
let query_str = query.to_string().replace(
|
||||
"%q%",
|
||||
&match query.query {
|
||||
AppDataSelectQuery::KeyIs(_) => format!("k = $1"),
|
||||
AppDataSelectQuery::LikeJson(_, _) => format!("v LIKE $1"),
|
||||
},
|
||||
);
|
||||
let query_str = query.to_string().replace("%q%", &query.query.selector());
|
||||
|
||||
let res = match query.mode {
|
||||
AppDataSelectMode::One(_) => AppDataQueryResult::One(
|
||||
|
@ -98,13 +92,7 @@ impl DataManager {
|
|||
|
||||
let query_str = query
|
||||
.to_string()
|
||||
.replace(
|
||||
"%q%",
|
||||
&match query.query {
|
||||
AppDataSelectQuery::KeyIs(_) => format!("k = $1"),
|
||||
AppDataSelectQuery::LikeJson(_, _) => format!("v LIKE $1"),
|
||||
},
|
||||
)
|
||||
.replace("%q%", &query.query.selector())
|
||||
.replace("SELECT * FROM", "SELECT id FROM");
|
||||
|
||||
if let Err(e) = execute!(
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::model::{
|
|||
apps::{AppQuota, ThirdPartyApp},
|
||||
auth::User,
|
||||
oauth::AppScope,
|
||||
permissions::FinePermission,
|
||||
permissions::{FinePermission, SecondaryPermission},
|
||||
Error, Result,
|
||||
};
|
||||
use crate::{auto_method, DataManager};
|
||||
|
@ -72,10 +72,15 @@ impl DataManager {
|
|||
// check number of apps
|
||||
let owner = self.get_user_by_id(data.owner).await?;
|
||||
|
||||
if !owner.permissions.check(FinePermission::SUPPORTER) {
|
||||
let apps = self.get_apps_by_owner(data.owner).await?;
|
||||
if !owner
|
||||
.secondary_permissions
|
||||
.check(SecondaryPermission::DEVELOPER_PASS)
|
||||
{
|
||||
let apps = self
|
||||
.get_table_row_count_where("apps", &format!("owner = {}", owner.id))
|
||||
.await? as usize;
|
||||
|
||||
if apps.len() >= Self::MAXIMUM_FREE_APPS {
|
||||
if apps >= Self::MAXIMUM_FREE_APPS {
|
||||
return Err(Error::MiscError(
|
||||
"You already have the maximum number of apps you can have".to_string(),
|
||||
));
|
||||
|
|
|
@ -85,7 +85,7 @@ impl DataManager {
|
|||
|
||||
let res = query_row!(
|
||||
&conn,
|
||||
&format!("SELECT COUNT(*)::int FROM {} {}", table, r#where),
|
||||
&format!("SELECT COUNT(*)::int FROM {} WHERE {}", table, r#where),
|
||||
params![],
|
||||
|x| Ok(x.get::<usize, i32>(0))
|
||||
);
|
||||
|
|
|
@ -3,6 +3,7 @@ use super::common::NAME_REGEX;
|
|||
use oiseau::cache::Cache;
|
||||
use crate::model::communities::{CommunityContext, CommunityJoinAccess, CommunityMembership};
|
||||
use crate::model::communities_permissions::CommunityPermission;
|
||||
use crate::model::permissions::SecondaryPermission;
|
||||
use crate::model::{
|
||||
Error, Result,
|
||||
auth::User,
|
||||
|
@ -255,7 +256,11 @@ impl DataManager {
|
|||
|
||||
// check is_forge
|
||||
// only supporters can CREATE forge communities... anybody can contribute to them
|
||||
if data.is_forge && !owner.permissions.check(FinePermission::SUPPORTER) {
|
||||
if data.is_forge
|
||||
&& !owner
|
||||
.secondary_permissions
|
||||
.check(SecondaryPermission::DEVELOPER_PASS)
|
||||
{
|
||||
return Err(Error::RequiresSupporter);
|
||||
}
|
||||
|
||||
|
|
|
@ -147,6 +147,8 @@ impl AppData {
|
|||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum AppDataSelectQuery {
|
||||
KeyIs(String),
|
||||
KeyLike(String),
|
||||
ValueLike(String),
|
||||
LikeJson(String, String),
|
||||
}
|
||||
|
||||
|
@ -154,11 +156,24 @@ impl Display for AppDataSelectQuery {
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(&match self {
|
||||
Self::KeyIs(k) => k.to_owned(),
|
||||
Self::KeyLike(k) => k.to_owned(),
|
||||
Self::ValueLike(v) => v.to_owned(),
|
||||
Self::LikeJson(k, v) => format!("%\"{k}\":\"{v}\"%"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AppDataSelectQuery {
|
||||
pub fn selector(&self) -> String {
|
||||
match self {
|
||||
AppDataSelectQuery::KeyIs(_) => format!("k = $1"),
|
||||
AppDataSelectQuery::KeyLike(_) => format!("k LIKE $1"),
|
||||
AppDataSelectQuery::ValueLike(_) => format!("v LIKE $1"),
|
||||
AppDataSelectQuery::LikeJson(_, _) => format!("v LIKE $1"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum AppDataSelectMode {
|
||||
/// Select a single row (with offset).
|
||||
|
@ -179,14 +194,14 @@ impl Display for AppDataSelectMode {
|
|||
Self::One(offset) => format!("LIMIT 1 OFFSET {offset}"),
|
||||
Self::Many(limit, offset) => {
|
||||
format!(
|
||||
"LIMIT {} OFFSET {offset}",
|
||||
if *limit > 1024 { 1024 } else { *limit }
|
||||
"ORDER BY k DESC LIMIT {} OFFSET {offset}",
|
||||
if *limit > 24 { 24 } else { *limit }
|
||||
)
|
||||
}
|
||||
Self::ManyJson(order_by_top_level_key, limit, offset) => {
|
||||
format!(
|
||||
"ORDER BY v::jsonb->>'{order_by_top_level_key}' DESC LIMIT {} OFFSET {offset}",
|
||||
if *limit > 1024 { 1024 } else { *limit }
|
||||
if *limit > 24 { 24 } else { *limit }
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue