mirror of
https://github.com/twentyhq/twenty.git
synced 2024-11-22 03:17:40 +03:00
add pr comment changes
This commit is contained in:
parent
e701d1ac2e
commit
73bcb18e18
@ -10,7 +10,11 @@ import {
|
|||||||
|
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
|
|
||||||
import { WebhookEvent } from 'src/engine/core-modules/billing/enums/webhook-events.enum';
|
import {
|
||||||
|
BillingException,
|
||||||
|
BillingExceptionCode,
|
||||||
|
} from 'src/engine/core-modules/billing/billing.exception';
|
||||||
|
import { WebhookEvent } from 'src/engine/core-modules/billing/enums/billing-webhook-events.enum';
|
||||||
import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service';
|
import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service';
|
||||||
import { BillingWebhookService } from 'src/engine/core-modules/billing/services/billing-webhook.service';
|
import { BillingWebhookService } from 'src/engine/core-modules/billing/services/billing-webhook.service';
|
||||||
import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service';
|
import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service';
|
||||||
@ -62,15 +66,20 @@ export class BillingController {
|
|||||||
event.data,
|
event.data,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (event.type === WebhookEvent.CUSTOMER_ACTIVE_ENTITLEMENT) {
|
if (
|
||||||
|
event.type === WebhookEvent.CUSTOMER_ACTIVE_ENTITLEMENT_SUMMARY_UPDATED
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
await this.billingWehbookService.processCustomerActiveEntitlement(
|
await this.billingWehbookService.processCustomerActiveEntitlement(
|
||||||
event.data,
|
event.data,
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
res.status(500).end();
|
if (
|
||||||
|
error instanceof BillingException &&
|
||||||
return;
|
error.code === BillingExceptionCode.BILLING_CUSTOMER_NOT_FOUND
|
||||||
|
) {
|
||||||
|
res.status(404).end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.status(200).end();
|
res.status(200).end();
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
/* @license Enterprise */
|
||||||
|
|
||||||
|
import { CustomException } from 'src/utils/custom-exception';
|
||||||
|
|
||||||
|
export class BillingException extends CustomException {
|
||||||
|
code: BillingExceptionCode;
|
||||||
|
constructor(message: string, code: BillingExceptionCode) {
|
||||||
|
super(message, code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum BillingExceptionCode {
|
||||||
|
BILLING_CUSTOMER_NOT_FOUND = 'BILLING_CUSTOMER_NOT_FOUND',
|
||||||
|
}
|
@ -7,7 +7,7 @@ import { ProductPricesEntity } from 'src/engine/core-modules/billing/dto/product
|
|||||||
import { ProductInput } from 'src/engine/core-modules/billing/dto/product.input';
|
import { ProductInput } from 'src/engine/core-modules/billing/dto/product.input';
|
||||||
import { SessionEntity } from 'src/engine/core-modules/billing/dto/session.entity';
|
import { SessionEntity } from 'src/engine/core-modules/billing/dto/session.entity';
|
||||||
import { UpdateBillingEntity } from 'src/engine/core-modules/billing/dto/update-billing.entity';
|
import { UpdateBillingEntity } from 'src/engine/core-modules/billing/dto/update-billing.entity';
|
||||||
import { AvailableProduct } from 'src/engine/core-modules/billing/enums/available-product.enum';
|
import { AvailableProduct } from 'src/engine/core-modules/billing/enums/billing-available-product.enum';
|
||||||
import { BillingPortalWorkspaceService } from 'src/engine/core-modules/billing/services/billing-portal.workspace-service';
|
import { BillingPortalWorkspaceService } from 'src/engine/core-modules/billing/services/billing-portal.workspace-service';
|
||||||
import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service';
|
import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service';
|
||||||
import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service';
|
import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service';
|
||||||
|
@ -3,7 +3,7 @@ import { ArgsType, Field } from '@nestjs/graphql';
|
|||||||
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
||||||
import Stripe from 'stripe';
|
import Stripe from 'stripe';
|
||||||
|
|
||||||
import { SubscriptionInterval } from 'src/engine/core-modules/billing/enums/subcription-interval.enum';
|
import { SubscriptionInterval } from 'src/engine/core-modules/billing/enums/billing-subscription-interval.enum';
|
||||||
|
|
||||||
@ArgsType()
|
@ArgsType()
|
||||||
export class CheckoutSessionInput {
|
export class CheckoutSessionInput {
|
||||||
|
@ -2,7 +2,7 @@ import { Field, ObjectType } from '@nestjs/graphql';
|
|||||||
|
|
||||||
import Stripe from 'stripe';
|
import Stripe from 'stripe';
|
||||||
|
|
||||||
import { SubscriptionInterval } from 'src/engine/core-modules/billing/enums/subcription-interval.enum';
|
import { SubscriptionInterval } from 'src/engine/core-modules/billing/enums/billing-subscription-interval.enum';
|
||||||
@ObjectType()
|
@ObjectType()
|
||||||
export class ProductPriceEntity {
|
export class ProductPriceEntity {
|
||||||
@Field(() => SubscriptionInterval)
|
@Field(() => SubscriptionInterval)
|
||||||
|
@ -2,7 +2,7 @@ import { ArgsType, Field } from '@nestjs/graphql';
|
|||||||
|
|
||||||
import { IsNotEmpty, IsString } from 'class-validator';
|
import { IsNotEmpty, IsString } from 'class-validator';
|
||||||
|
|
||||||
import { AvailableProduct } from 'src/engine/core-modules/billing/enums/available-product.enum';
|
import { AvailableProduct } from 'src/engine/core-modules/billing/enums/billing-available-product.enum';
|
||||||
|
|
||||||
@ArgsType()
|
@ArgsType()
|
||||||
export class ProductInput {
|
export class ProductInput {
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
|
|
||||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||||
import { FeatureStripeLookupKey } from 'src/engine/core-modules/billing/enums/feature-stripe-lookup-key.enum';
|
import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum';
|
||||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
@Entity({ name: 'billingEntitlement', schema: 'core' })
|
@Entity({ name: 'billingEntitlement', schema: 'core' })
|
||||||
@ObjectType('billingEntitlement')
|
@ObjectType('billingEntitlement')
|
||||||
@ -26,7 +26,7 @@ export class BillingEntitlement {
|
|||||||
|
|
||||||
@Field(() => String)
|
@Field(() => String)
|
||||||
@Column({ nullable: false, type: 'text' })
|
@Column({ nullable: false, type: 'text' })
|
||||||
key: FeatureStripeLookupKey;
|
key: BillingEntitlementKey;
|
||||||
|
|
||||||
@Field()
|
@Field()
|
||||||
@Column({ nullable: false, type: 'uuid' })
|
@Column({ nullable: false, type: 'uuid' })
|
||||||
|
@ -16,8 +16,8 @@ import {
|
|||||||
|
|
||||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||||
import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity';
|
import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity';
|
||||||
import { SubscriptionInterval } from 'src/engine/core-modules/billing/enums/subcription-interval.enum';
|
import { SubscriptionInterval } from 'src/engine/core-modules/billing/enums/billing-subscription-interval.enum';
|
||||||
import { SubscriptionStatus } from 'src/engine/core-modules/billing/enums/subcription-status.enum';
|
import { SubscriptionStatus } from 'src/engine/core-modules/billing/enums/billing-subscription-status.enum';
|
||||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
|
|
||||||
registerEnumType(SubscriptionStatus, { name: 'SubscriptionStatus' });
|
registerEnumType(SubscriptionStatus, { name: 'SubscriptionStatus' });
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
export enum BillingEntitlementKey {
|
||||||
|
SSO = 'sso_feat',
|
||||||
|
}
|
@ -3,5 +3,5 @@ export enum WebhookEvent {
|
|||||||
CUSTOMER_SUBSCRIPTION_UPDATED = 'customer.subscription.updated',
|
CUSTOMER_SUBSCRIPTION_UPDATED = 'customer.subscription.updated',
|
||||||
CUSTOMER_SUBSCRIPTION_DELETED = 'customer.subscription.deleted',
|
CUSTOMER_SUBSCRIPTION_DELETED = 'customer.subscription.deleted',
|
||||||
SETUP_INTENT_SUCCEEDED = 'setup_intent.succeeded',
|
SETUP_INTENT_SUCCEEDED = 'setup_intent.succeeded',
|
||||||
CUSTOMER_ACTIVE_ENTITLEMENT = 'entitlements.active_entitlement_summary.updated',
|
CUSTOMER_ACTIVE_ENTITLEMENT_SUMMARY_UPDATED = 'entitlements.active_entitlement_summary.updated',
|
||||||
}
|
}
|
@ -1,3 +0,0 @@
|
|||||||
export enum FeatureStripeLookupKey {
|
|
||||||
SSO = 'sso_feat',
|
|
||||||
}
|
|
@ -9,10 +9,10 @@ import { Not, Repository } from 'typeorm';
|
|||||||
|
|
||||||
import { BillingEntitlement } from 'src/engine/core-modules/billing/entities/billing-entitlement.entity';
|
import { BillingEntitlement } from 'src/engine/core-modules/billing/entities/billing-entitlement.entity';
|
||||||
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
|
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
|
||||||
import { AvailableProduct } from 'src/engine/core-modules/billing/enums/available-product.enum';
|
import { AvailableProduct } from 'src/engine/core-modules/billing/enums/billing-available-product.enum';
|
||||||
import { FeatureStripeLookupKey } from 'src/engine/core-modules/billing/enums/feature-stripe-lookup-key.enum';
|
import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum';
|
||||||
import { SubscriptionInterval } from 'src/engine/core-modules/billing/enums/subcription-interval.enum';
|
import { SubscriptionInterval } from 'src/engine/core-modules/billing/enums/billing-subscription-interval.enum';
|
||||||
import { SubscriptionStatus } from 'src/engine/core-modules/billing/enums/subcription-status.enum';
|
import { SubscriptionStatus } from 'src/engine/core-modules/billing/enums/billing-subscription-status.enum';
|
||||||
import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service';
|
import { StripeService } from 'src/engine/core-modules/billing/stripe/stripe.service';
|
||||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||||
|
|
||||||
@ -99,19 +99,19 @@ export class BillingSubscriptionService {
|
|||||||
|
|
||||||
async getWorkspaceEntitlementByKey(
|
async getWorkspaceEntitlementByKey(
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
lookupKey: FeatureStripeLookupKey,
|
key: BillingEntitlementKey,
|
||||||
) {
|
) {
|
||||||
const entitlement = await this.billingEntitlementRepository.findOneBy({
|
const entitlement = await this.billingEntitlementRepository.findOneBy({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
key: lookupKey,
|
key,
|
||||||
value: true,
|
value: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!entitlement?.value) {
|
if (!entitlement) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return entitlement.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
async applyBillingSubscription(user: User) {
|
async applyBillingSubscription(user: User) {
|
||||||
|
@ -4,11 +4,15 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||||||
import Stripe from 'stripe';
|
import Stripe from 'stripe';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BillingException,
|
||||||
|
BillingExceptionCode,
|
||||||
|
} from 'src/engine/core-modules/billing/billing.exception';
|
||||||
import { BillingEntitlement } from 'src/engine/core-modules/billing/entities/billing-entitlement.entity';
|
import { BillingEntitlement } from 'src/engine/core-modules/billing/entities/billing-entitlement.entity';
|
||||||
import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity';
|
import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity';
|
||||||
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
|
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
|
||||||
import { FeatureStripeLookupKey } from 'src/engine/core-modules/billing/enums/feature-stripe-lookup-key.enum';
|
import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum';
|
||||||
import { SubscriptionStatus } from 'src/engine/core-modules/billing/enums/subcription-status.enum';
|
import { SubscriptionStatus } from 'src/engine/core-modules/billing/enums/billing-subscription-status.enum';
|
||||||
import {
|
import {
|
||||||
Workspace,
|
Workspace,
|
||||||
WorkspaceActivationStatus,
|
WorkspaceActivationStatus,
|
||||||
@ -103,22 +107,30 @@ export class BillingWebhookService {
|
|||||||
data: Stripe.EntitlementsActiveEntitlementSummaryUpdatedEvent.Data,
|
data: Stripe.EntitlementsActiveEntitlementSummaryUpdatedEvent.Data,
|
||||||
) {
|
) {
|
||||||
const billingSubscription =
|
const billingSubscription =
|
||||||
await this.billingSubscriptionRepository.findOneOrFail({
|
await this.billingSubscriptionRepository.findOne({
|
||||||
where: { stripeCustomerId: data.object.customer },
|
where: { stripeCustomerId: data.object.customer },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!billingSubscription) {
|
||||||
|
throw new BillingException(
|
||||||
|
'Billing customer not found',
|
||||||
|
BillingExceptionCode.BILLING_CUSTOMER_NOT_FOUND,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const workspaceId = billingSubscription.workspaceId;
|
const workspaceId = billingSubscription.workspaceId;
|
||||||
const stripeCustomerId = data.object.customer;
|
const stripeCustomerId = data.object.customer;
|
||||||
|
|
||||||
const currentEntitlements = data.object.entitlements.data.map(
|
const activeEntitlementsKeys = data.object.entitlements.data.map(
|
||||||
(item) => item.lookup_key,
|
(entitlement) => entitlement.lookup_key,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.billingEntitlementRepository.upsert(
|
await this.billingEntitlementRepository.upsert(
|
||||||
Object.values(FeatureStripeLookupKey).map((key) => {
|
Object.values(BillingEntitlementKey).map((key) => {
|
||||||
return {
|
return {
|
||||||
workspaceId,
|
workspaceId,
|
||||||
key,
|
key,
|
||||||
value: currentEntitlements.includes(key),
|
value: activeEntitlementsKeys.includes(key),
|
||||||
stripeCustomerId,
|
stripeCustomerId,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
@ -2,8 +2,8 @@ import { Injectable, Logger } from '@nestjs/common';
|
|||||||
|
|
||||||
import { isDefined } from 'class-validator';
|
import { isDefined } from 'class-validator';
|
||||||
|
|
||||||
import { FeatureStripeLookupKey } from 'src/engine/core-modules/billing/enums/feature-stripe-lookup-key.enum';
|
import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum';
|
||||||
import { SubscriptionStatus } from 'src/engine/core-modules/billing/enums/subcription-status.enum';
|
import { SubscriptionStatus } from 'src/engine/core-modules/billing/enums/billing-subscription-status.enum';
|
||||||
import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service';
|
import { BillingSubscriptionService } from 'src/engine/core-modules/billing/services/billing-subscription.service';
|
||||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||||
@ -56,7 +56,7 @@ export class BillingService {
|
|||||||
|
|
||||||
async verifyWorkspaceEntitlement(
|
async verifyWorkspaceEntitlement(
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
entitlementKey: FeatureStripeLookupKey,
|
entitlementKey: BillingEntitlementKey,
|
||||||
) {
|
) {
|
||||||
const isBillingEnabled = this.isBillingEnabled();
|
const isBillingEnabled = this.isBillingEnabled();
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import Stripe from 'stripe';
|
|||||||
|
|
||||||
import { ProductPriceEntity } from 'src/engine/core-modules/billing/dto/product-price.entity';
|
import { ProductPriceEntity } from 'src/engine/core-modules/billing/dto/product-price.entity';
|
||||||
import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity';
|
import { BillingSubscriptionItem } from 'src/engine/core-modules/billing/entities/billing-subscription-item.entity';
|
||||||
import { AvailableProduct } from 'src/engine/core-modules/billing/enums/available-product.enum';
|
import { AvailableProduct } from 'src/engine/core-modules/billing/enums/billing-available-product.enum';
|
||||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||||
import { User } from 'src/engine/core-modules/user/user.entity';
|
import { User } from 'src/engine/core-modules/user/user.entity';
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|||||||
import { Issuer } from 'openid-client';
|
import { Issuer } from 'openid-client';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
import { FeatureStripeLookupKey } from 'src/engine/core-modules/billing/enums/feature-stripe-lookup-key.enum';
|
import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum';
|
||||||
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
|
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
|
||||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||||
@ -30,7 +30,7 @@ import { User } from 'src/engine/core-modules/user/user.entity';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SSOService {
|
export class SSOService {
|
||||||
private readonly featureLookUpKey = 'sso_feat' as FeatureStripeLookupKey;
|
private readonly featureLookUpKey = 'sso_feat' as BillingEntitlementKey;
|
||||||
constructor(
|
constructor(
|
||||||
@InjectRepository(FeatureFlagEntity, 'core')
|
@InjectRepository(FeatureFlagEntity, 'core')
|
||||||
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
private readonly featureFlagRepository: Repository<FeatureFlagEntity>,
|
||||||
|
Loading…
Reference in New Issue
Block a user