mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
fix payment methods.
This commit is contained in:
@@ -42,7 +42,8 @@ export default class URL extends DatabaseProperty {
|
||||
public constructor(
|
||||
protocol: Protocol,
|
||||
hostname: Hostname | string,
|
||||
route?: Route
|
||||
route?: Route,
|
||||
queryString?: string
|
||||
) {
|
||||
super();
|
||||
if (hostname instanceof Hostname) {
|
||||
@@ -56,6 +57,20 @@ export default class URL extends DatabaseProperty {
|
||||
if (route) {
|
||||
this.route = route;
|
||||
}
|
||||
|
||||
if (queryString) {
|
||||
const keyValues = queryString.split("&");
|
||||
for (const keyValue of keyValues) {
|
||||
if (keyValue.split("=")[0] && keyValue.split("=")[1]) {
|
||||
const key = keyValue.split("=")[0];
|
||||
const value = keyValue.split("=")[1];
|
||||
if (key && value) {
|
||||
this._params[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public isHttps(): boolean {
|
||||
@@ -118,14 +133,22 @@ export default class URL extends DatabaseProperty {
|
||||
const hostname: Hostname = new Hostname(url.split('/')[0] || '');
|
||||
|
||||
let route: Route | undefined;
|
||||
let queryString: string | undefined;
|
||||
|
||||
if (url.split('/').length > 1) {
|
||||
const paths: Array<string> = url.split('/');
|
||||
paths.shift();
|
||||
route = new Route(paths.join('/'));
|
||||
route = new Route(paths.join('/').split("?")[0]);
|
||||
|
||||
}
|
||||
|
||||
return new URL(protocol, hostname, route);
|
||||
queryString = url.split("?")[1] || '';
|
||||
|
||||
return new URL(protocol, hostname, route, queryString);
|
||||
}
|
||||
|
||||
public removeQueryString(): URL {
|
||||
return URL.fromString(this.toString().split("?")[0] || '');
|
||||
}
|
||||
|
||||
public addRoute(route: Route | string): URL {
|
||||
|
||||
@@ -16,4 +16,5 @@ export default interface DatabaseCommonInteractionProps {
|
||||
tenantId?: ObjectID | undefined;
|
||||
isRoot?: boolean | undefined;
|
||||
isMultiTenantRequest?: boolean | undefined;
|
||||
ignoreHooks?: boolean | undefined;
|
||||
}
|
||||
|
||||
@@ -27,12 +27,12 @@ export default class BaseAPI<
|
||||
TBaseModel extends BaseModel,
|
||||
TBaseService extends DatabaseService<BaseModel>
|
||||
> {
|
||||
public entityType: { new (): TBaseModel };
|
||||
public entityType: { new(): TBaseModel };
|
||||
|
||||
public router: ExpressRouter;
|
||||
public service: TBaseService;
|
||||
|
||||
public constructor(type: { new (): TBaseModel }, service: TBaseService) {
|
||||
public constructor(type: { new(): TBaseModel }, service: TBaseService) {
|
||||
this.entityType = type;
|
||||
const router: ExpressRouter = Express.getRouter();
|
||||
|
||||
@@ -144,8 +144,8 @@ export default class BaseAPI<
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
public getPermissionsForTenant(req:ExpressRequest): Array<UserPermission> {
|
||||
|
||||
public getPermissionsForTenant(req: ExpressRequest): Array<UserPermission> {
|
||||
|
||||
const permissions: Array<UserPermission> = [];
|
||||
|
||||
const props = this.getDatabaseCommonInteractionProps(req);
|
||||
@@ -156,7 +156,7 @@ export default class BaseAPI<
|
||||
return props.userTenantAccessPermission[props.tenantId?.toString() || '']?.permissions || [];
|
||||
}
|
||||
|
||||
return permissions;
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public getDatabaseCommonInteractionProps(
|
||||
@@ -206,7 +206,6 @@ export default class BaseAPI<
|
||||
res: ExpressResponse
|
||||
): Promise<void> {
|
||||
|
||||
console.log("LIST")
|
||||
await this.onBeforeList(req, res);
|
||||
|
||||
const skip: PositiveNumber = req.query['skip']
|
||||
@@ -281,6 +280,8 @@ export default class BaseAPI<
|
||||
): Promise<void> {
|
||||
let query: Query<BaseModel> = {};
|
||||
|
||||
await this.onBeforeCount(req, res);
|
||||
|
||||
if (req.body) {
|
||||
query = JSONFunctions.deserialize(
|
||||
req.body['query']
|
||||
@@ -305,7 +306,7 @@ export default class BaseAPI<
|
||||
res: ExpressResponse
|
||||
): Promise<void> {
|
||||
const objectId: ObjectID = new ObjectID(req.params['id'] as string);
|
||||
|
||||
await this.onBeforeGet(req, res);
|
||||
let select: Select<BaseModel> = {};
|
||||
let populate: Populate<BaseModel> = {};
|
||||
|
||||
@@ -335,6 +336,7 @@ export default class BaseAPI<
|
||||
req: ExpressRequest,
|
||||
res: ExpressResponse
|
||||
): Promise<void> {
|
||||
await this.onBeforeDelete(req, res);
|
||||
const objectId: ObjectID = new ObjectID(req.params['id'] as string);
|
||||
|
||||
await this.service.deleteBy({
|
||||
@@ -351,6 +353,7 @@ export default class BaseAPI<
|
||||
req: ExpressRequest,
|
||||
res: ExpressResponse
|
||||
): Promise<void> {
|
||||
await this.onBeforeUpdate(req, res);
|
||||
const objectId: ObjectID = new ObjectID(req.params['id'] as string);
|
||||
const objectIdString: string = objectId.toString();
|
||||
const body: JSONObject = req.body;
|
||||
@@ -378,6 +381,7 @@ export default class BaseAPI<
|
||||
req: ExpressRequest,
|
||||
res: ExpressResponse
|
||||
): Promise<void> {
|
||||
await this.onBeforeCreate(req, res);
|
||||
const body: JSONObject = req.body;
|
||||
|
||||
const item: TBaseModel = BaseModel.fromJSON<TBaseModel>(
|
||||
@@ -418,4 +422,38 @@ export default class BaseAPI<
|
||||
): Promise<any> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
|
||||
protected async onBeforeCreate(
|
||||
_req: ExpressRequest, _res: ExpressResponse
|
||||
): Promise<any> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
protected async onBeforeGet(
|
||||
_req: ExpressRequest, _res: ExpressResponse
|
||||
): Promise<any> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
protected async onBeforeUpdate(
|
||||
_req: ExpressRequest, _res: ExpressResponse
|
||||
): Promise<any> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
|
||||
protected async onBeforeDelete(
|
||||
_req: ExpressRequest, _res: ExpressResponse
|
||||
): Promise<any> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
protected async onBeforeCount(
|
||||
_req: ExpressRequest, _res: ExpressResponse
|
||||
): Promise<any> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import Project from 'Model/Models/Project';
|
||||
import BillingService from './BillingService';
|
||||
import DeleteBy from '../Types/Database/DeleteBy';
|
||||
import LIMIT_MAX from 'Common/Types/Database/LimitMax';
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor(postgresDatabase?: PostgresDatabase) {
|
||||
@@ -15,7 +16,6 @@ export class Service extends DatabaseService<Model> {
|
||||
|
||||
protected override async onBeforeFind(findBy: FindBy<Model>): Promise<OnFind<Model>> {
|
||||
|
||||
console.log(findBy.props);
|
||||
|
||||
if (!findBy.props.tenantId) {
|
||||
throw new BadDataException("ProjectID not found.")
|
||||
@@ -25,7 +25,8 @@ export class Service extends DatabaseService<Model> {
|
||||
id: findBy.props.tenantId!,
|
||||
props: {
|
||||
...findBy.props,
|
||||
isRoot: true
|
||||
isRoot: true,
|
||||
ignoreHooks: true
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
@@ -62,7 +63,8 @@ export class Service extends DatabaseService<Model> {
|
||||
billingPaymentMethod.last4Digits = paymentMethod.last4Digits;
|
||||
billingPaymentMethod.isDefault = paymentMethod.isDefault;
|
||||
billingPaymentMethod.paymentProviderPaymentMethodId = paymentMethod.id;
|
||||
|
||||
billingPaymentMethod.paymentProviderCustomerId = project.paymentProviderCustomerId;
|
||||
|
||||
await this.create({
|
||||
data: billingPaymentMethod,
|
||||
props: {
|
||||
@@ -75,11 +77,29 @@ export class Service extends DatabaseService<Model> {
|
||||
return { findBy, carryForward: paymentMethods };
|
||||
}
|
||||
|
||||
protected override onBeforeDelete(deleteBy: DeleteBy<Model>): Promise<OnDelete<Model>> {
|
||||
protected override async onBeforeDelete(deleteBy: DeleteBy<Model>): Promise<OnDelete<Model>> {
|
||||
const items = await this.findBy({
|
||||
query: deleteBy.query,
|
||||
|
||||
})
|
||||
query: deleteBy.query,
|
||||
select: {
|
||||
_id: true,
|
||||
paymentProviderPaymentMethodId: true,
|
||||
paymentProviderCustomerId: true,
|
||||
},
|
||||
skip: 0,
|
||||
limit: LIMIT_MAX,
|
||||
props: {
|
||||
isRoot: true,
|
||||
ignoreHooks: true
|
||||
}
|
||||
});
|
||||
|
||||
for (const item of items) {
|
||||
if (item.paymentProviderPaymentMethodId && item.paymentProviderCustomerId) {
|
||||
await BillingService.deletePaymentMethod(item.paymentProviderCustomerId, item.paymentProviderPaymentMethodId);
|
||||
}
|
||||
}
|
||||
|
||||
return { deleteBy, carryForward: null };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ export class BillingService {
|
||||
|
||||
const paymenMethods = await this.getPaymentMethods(customerId);
|
||||
if (paymenMethods.length === 1) {
|
||||
throw new BadDataException("There's only one poayment method associated with this account. It cannot be deleted. To delete this payment method please add more payment methods to your account.");
|
||||
throw new BadDataException("There's only one payment method associated with this account. It cannot be deleted. To delete this payment method please add more payment methods to your account.");
|
||||
}
|
||||
|
||||
await this.stripe.paymentMethods.detach(paymentMethodId);
|
||||
|
||||
@@ -465,7 +465,7 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
}
|
||||
|
||||
public async create(createBy: CreateBy<TBaseModel>): Promise<TBaseModel> {
|
||||
const onCreate: OnCreate<TBaseModel> = await this._onBeforeCreate(
|
||||
const onCreate: OnCreate<TBaseModel> = createBy.props.ignoreHooks ? { createBy, carryForward: [] } : await this._onBeforeCreate(
|
||||
createBy
|
||||
);
|
||||
|
||||
@@ -519,13 +519,15 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
|
||||
try {
|
||||
createBy.data = await this.getRepository().save(createBy.data);
|
||||
createBy.data = await this.onCreateSuccess(
|
||||
{
|
||||
createBy,
|
||||
carryForward,
|
||||
},
|
||||
createBy.data
|
||||
);
|
||||
if (!createBy.props.ignoreHooks) {
|
||||
createBy.data = await this.onCreateSuccess(
|
||||
{
|
||||
createBy,
|
||||
carryForward,
|
||||
},
|
||||
createBy.data
|
||||
);
|
||||
}
|
||||
return createBy.data;
|
||||
} catch (error) {
|
||||
await this.onCreateError(error as Exception);
|
||||
@@ -653,7 +655,7 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
);
|
||||
|
||||
findBy.query = checkReadPermissionType.query;
|
||||
let count: number = 0;
|
||||
let count: number = 0;
|
||||
|
||||
if (distinctOn) {
|
||||
const queryBuilder: SelectQueryBuilder<TBaseModel> = this.getQueryBuilder(this.modelName)
|
||||
@@ -668,14 +670,14 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
count = await queryBuilder.getCount();
|
||||
|
||||
} else {
|
||||
count = await this.getRepository().count({
|
||||
count = await this.getRepository().count({
|
||||
where: findBy.query as any,
|
||||
skip: (findBy.skip as PositiveNumber).toNumber(),
|
||||
take: (findBy.limit as PositiveNumber).toNumber(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
let countPositive: PositiveNumber = new PositiveNumber(count);
|
||||
countPositive = await this.onCountSuccess(countPositive);
|
||||
return countPositive;
|
||||
@@ -697,7 +699,7 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
|
||||
private async _deleteBy(deleteBy: DeleteBy<TBaseModel>): Promise<number> {
|
||||
try {
|
||||
const onDelete: OnDelete<TBaseModel> = await this.onBeforeDelete(
|
||||
const onDelete: OnDelete<TBaseModel> = deleteBy.props.ignoreHooks ? { deleteBy, carryForward: [] } : await this.onBeforeDelete(
|
||||
deleteBy
|
||||
);
|
||||
const beforeDeleteBy: DeleteBy<TBaseModel> = onDelete.deleteBy;
|
||||
@@ -716,7 +718,7 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
limit: LIMIT_MAX,
|
||||
populate: {},
|
||||
select: {},
|
||||
props: beforeDeleteBy.props,
|
||||
props: { ...beforeDeleteBy.props, ignoreHooks: true },
|
||||
});
|
||||
|
||||
await this._updateBy({
|
||||
@@ -726,19 +728,24 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
} as any,
|
||||
props: {
|
||||
isRoot: true,
|
||||
ignoreHooks: true
|
||||
},
|
||||
});
|
||||
|
||||
const numberOfDocsAffected: number =
|
||||
(await this.getRepository().delete(beforeDeleteBy.query as any))
|
||||
.affected || 0;
|
||||
|
||||
|
||||
if (!deleteBy.props.ignoreHooks) {
|
||||
|
||||
await this.onDeleteSuccess(
|
||||
{ deleteBy, carryForward },
|
||||
items.map((i: TBaseModel) => {
|
||||
return new ObjectID(i._id!);
|
||||
})
|
||||
);
|
||||
await this.onDeleteSuccess(
|
||||
{ deleteBy, carryForward },
|
||||
items.map((i: TBaseModel) => {
|
||||
return new ObjectID(i._id!);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return numberOfDocsAffected;
|
||||
} catch (error) {
|
||||
@@ -762,7 +769,7 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
createdAt: SortOrder.Descending,
|
||||
};
|
||||
}
|
||||
const onFind: OnFind<TBaseModel> = await this.onBeforeFind(findBy);
|
||||
const onFind: OnFind<TBaseModel> = findBy.props.ignoreHooks ? { findBy, carryForward: [] } : await this.onBeforeFind(findBy);
|
||||
const onBeforeFind: FindBy<TBaseModel> = onFind.findBy;
|
||||
const carryForward: any = onFind.carryForward;
|
||||
|
||||
@@ -824,13 +831,14 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
decryptedItems,
|
||||
onBeforeFind
|
||||
);
|
||||
|
||||
decryptedItems = await (
|
||||
await this.onFindSuccess(
|
||||
{ findBy, carryForward },
|
||||
decryptedItems
|
||||
)
|
||||
).carryForward;
|
||||
if (!findBy.props.ignoreHooks) {
|
||||
decryptedItems = await (
|
||||
await this.onFindSuccess(
|
||||
{ findBy, carryForward },
|
||||
decryptedItems
|
||||
)
|
||||
).carryForward;
|
||||
}
|
||||
|
||||
return decryptedItems;
|
||||
} catch (error) {
|
||||
@@ -934,7 +942,7 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
|
||||
private async _updateBy(updateBy: UpdateBy<TBaseModel>): Promise<number> {
|
||||
try {
|
||||
const onUpdate: OnUpdate<TBaseModel> = await this.onBeforeUpdate(
|
||||
const onUpdate: OnUpdate<TBaseModel> = updateBy.props.ignoreHooks ? { updateBy, carryForward: [] } : await this.onBeforeUpdate(
|
||||
updateBy
|
||||
);
|
||||
|
||||
@@ -961,7 +969,7 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
limit: LIMIT_MAX,
|
||||
populate: {},
|
||||
select: {},
|
||||
props: beforeUpdateBy.props,
|
||||
props: { ...beforeUpdateBy.props, ignoreHooks: true },
|
||||
});
|
||||
|
||||
for (let item of items) {
|
||||
@@ -984,12 +992,14 @@ class DatabaseService<TBaseModel extends BaseModel> {
|
||||
// )
|
||||
// ).affected || 0;
|
||||
|
||||
await this.onUpdateSuccess(
|
||||
{ updateBy, carryForward },
|
||||
items.map((i: TBaseModel) => {
|
||||
return new ObjectID(i._id!);
|
||||
})
|
||||
);
|
||||
if (!updateBy.props.ignoreHooks) {
|
||||
await this.onUpdateSuccess(
|
||||
{ updateBy, carryForward },
|
||||
items.map((i: TBaseModel) => {
|
||||
return new ObjectID(i._id!);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return items.length;
|
||||
} catch (error) {
|
||||
|
||||
@@ -24,12 +24,14 @@ const CheckoutForm = (props: ComponentProps) => {
|
||||
// Make sure to disable form submission until Stripe.js has loaded.
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(Navigation.getCurrentURL().removeQueryString().toString());
|
||||
|
||||
const { error } = await stripe.confirmSetup({
|
||||
//`Elements` instance that was used to create the Payment Element
|
||||
elements,
|
||||
confirmParams: {
|
||||
return_url: Navigation.getCurrentURL().toString(),
|
||||
return_url: Navigation.getCurrentURL().removeQueryString().toString(),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -175,6 +175,21 @@ export default class BillingPaymentMethod extends BaseModel {
|
||||
public paymentProviderPaymentMethodId?: string = undefined;
|
||||
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [Permission.ProjectOwner],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({ type: TableColumnType.ShortText })
|
||||
@Column({
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
nullable: false,
|
||||
unique: false,
|
||||
})
|
||||
public paymentProviderCustomerId?: string = undefined;
|
||||
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.ProjectOwner],
|
||||
read: [Permission.ProjectOwner],
|
||||
|
||||
Reference in New Issue
Block a user