Skip to content

Commit

Permalink
feat(costcenter): add recharge limit for non real name user (#5174)
Browse files Browse the repository at this point in the history
* feat(costcenter): add recharge limit for non real name user

* ok
  • Loading branch information
HUAHUAI23 authored Oct 29, 2024
1 parent 3c33459 commit 2ca25f5
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 3 deletions.
1 change: 1 addition & 0 deletions frontend/providers/costcenter/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const App = ({ Component, pageProps }: AppProps) => {
(async () => {
try {
const { data } = await request<any, ApiResp<initDataRes>>('/api/platform/getAppConfig');
state.setEnv('realNameRechargeLimit', !!data?.REALNAME_RECHARGE_LIMIT);
state.setEnv('invoiceEnabled', !!data?.INVOICE_ENABLED);
state.setEnv('transferEnabled', !!data?.TRANSFER_ENABLED);
state.setEnv('rechargeEnabled', !!data?.RECHARGE_ENABLED);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { makeAPIClientByHeader } from '@/service/backend/region';
import { jsonRes } from '@/service/backend/response';
import { checkSealosUserIsRealName } from '@/utils/tools';
import type { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, resp: NextApiResponse) {
Expand Down Expand Up @@ -28,6 +29,14 @@ export default async function handler(req: NextApiRequest, resp: NextApiResponse
const client = await makeAPIClientByHeader(req, resp);
if (!client) return;

const isRealName = await checkSealosUserIsRealName(client);
if (!isRealName) {
return jsonRes(resp, {
code: 403,
message: 'recharge is not allowed for non-real-name user'
});
}

const response = await client.post('/account/v1alpha1/gift-code/use', body);
const responseData = await response.data;
if (response.status !== 200) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { generatePaymentCrd, PaymentForm } from '@/constants/payment';
import { authSession } from '@/service/backend/auth';
import { ApplyYaml, GetUserDefaultNameSpace } from '@/service/backend/kubernetes';
import { makeAPIClientByHeader } from '@/service/backend/region';
import { jsonRes } from '@/service/backend/response';
import { deFormatMoney } from '@/utils/format';
import { checkSealosUserIsRealName } from '@/utils/tools';
import crypto from 'crypto';
import type { NextApiRequest, NextApiResponse } from 'next';

Expand Down Expand Up @@ -38,6 +40,17 @@ export default async function handler(req: NextApiRequest, resp: NextApiResponse
return jsonRes(resp, { code: 401, message: 'user not found' });
}

const client = await makeAPIClientByHeader(req, resp);
if (!client) return;

const isRealName = await checkSealosUserIsRealName(client);
if (!isRealName) {
return jsonRes(resp, {
code: 403,
message: 'recharge is not allowed for non-real-name user'
});
}

// do payment
const paymentName = crypto.randomUUID();
const namespace = GetUserDefaultNameSpace(kubeUser.name);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { generatePaymentCrd, PaymentForm } from '@/constants/payment';
import { authSession } from '@/service/backend/auth';
import { ApplyYaml, GetUserDefaultNameSpace } from '@/service/backend/kubernetes';
import { makeAPIClientByHeader } from '@/service/backend/region';
import { jsonRes } from '@/service/backend/response';
import { checkSealosUserIsRealName } from '@/utils/tools';
import crypto from 'crypto';
import type { NextApiRequest, NextApiResponse } from 'next';

Expand All @@ -23,6 +25,17 @@ export default async function handler(req: NextApiRequest, resp: NextApiResponse
});
}

const client = await makeAPIClientByHeader(req, resp);
if (!client) return;

const isRealName = await checkSealosUserIsRealName(client);
if (!isRealName) {
return jsonRes(resp, {
code: 403,
message: 'recharge is not allowed for non-real-name user'
});
}

const k8s_username = kc.getUsers()[0].name;
// do payment
const paymentName = crypto.randomUUID();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { jsonRes } from '@/service/backend/response';
import { AppConfigType, DefaultAppConfig } from '@/types/config';

export type Response = {
REALNAME_RECHARGE_LIMIT: boolean;
RECHARGE_ENABLED: boolean;
TRANSFER_ENABLED: boolean;
STRIPE_ENABLED: boolean;
Expand Down Expand Up @@ -45,6 +46,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
initAppConfig();
jsonRes<Response>(res, {
data: {
REALNAME_RECHARGE_LIMIT: global.AppConfig.costCenter.realNameRechargeLimit,
RECHARGE_ENABLED: global.AppConfig.costCenter.recharge.enabled,
TRANSFER_ENABLED: global.AppConfig.costCenter.transferEnabled,
STRIPE_ENABLED: global.AppConfig.costCenter.recharge.payMethods.stripe.enabled,
Expand Down
7 changes: 5 additions & 2 deletions frontend/providers/costcenter/src/service/backend/region.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Region } from '@/types/region';
import axios from 'axios';
import axios, { AxiosInstance } from 'axios';
import { NextApiRequest, NextApiResponse } from 'next';
import { AccessTokenPayload, generateBillingToken, verifyInternalToken } from '../auth';
import { jsonRes } from './response';
Expand Down Expand Up @@ -53,7 +53,10 @@ export async function makeRegionListAPIClientByHeader(req: NextApiRequest, res:
});
return clientList;
}
export function makeAPIClient(region: Region | undefined | null, payload?: AccessTokenPayload) {
export function makeAPIClient(
region: Region | undefined | null,
payload?: AccessTokenPayload
): AxiosInstance {
const baseURL = region?.accountSvc
? `http://${region?.accountSvc}`
: global.AppConfig.costCenter.components.accountService.url;
Expand Down
2 changes: 2 additions & 0 deletions frontend/providers/costcenter/src/stores/env.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { loadStripe } from '@stripe/stripe-js';
import { create } from 'zustand';
type EnvState = {
realNameRechargeLimit: boolean;
rechargeEnabled: boolean;
transferEnabled: boolean;
invoiceEnabled: boolean;
Expand All @@ -18,6 +19,7 @@ type EnvState = {
};

const useEnvStore = create<EnvState>((set, get) => ({
realNameRechargeLimit: false,
rechargeEnabled: false,
transferEnabled: false,
invoiceEnabled: false,
Expand Down
2 changes: 2 additions & 0 deletions frontend/providers/costcenter/src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export type AppConfigType = {
domain: string;
};
costCenter: {
realNameRechargeLimit: boolean;
transferEnabled: boolean;
giftCodeEnabled: boolean;
currencyType: string;
Expand All @@ -75,6 +76,7 @@ export type AppConfigType = {

export var DefaultAppConfig: AppConfigType = {
costCenter: {
realNameRechargeLimit: false,
giftCodeEnabled: true,
transferEnabled: true,
currencyType: 'shellCoin',
Expand Down
33 changes: 32 additions & 1 deletion frontend/providers/costcenter/src/utils/tools.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { NextApiRequest } from 'next';
import { AxiosInstance } from 'axios';
import crypto from 'crypto';

export const retrySerially = <T>(fn: () => Promise<T>, times: number) =>
new Promise((res, rej) => {
Expand All @@ -16,7 +18,6 @@ export const retrySerially = <T>(fn: () => Promise<T>, times: number) =>
};
attempt();
});
import crypto from 'crypto';
export function genSign(secret: string, timestamp: number | string) {
const stringToSign = `${timestamp}\n${secret}`;
const hmac = crypto.createHmac('sha256', stringToSign);
Expand Down Expand Up @@ -54,3 +55,33 @@ export function getClientIPFromRequest(req: NextApiRequest) {

return undefined;
}

type RealNameInfoResponse = {
data: {
userID: string;
isRealName: boolean;
};
error?: string;
message: string;
};

export const checkSealosUserIsRealName = async (client: AxiosInstance): Promise<boolean> => {
try {
if (!global.AppConfig.costCenter.realNameRechargeLimit) {
return true;
}

const response = await client.post('/account/v1alpha1/real-name-info');
const realNameInfoData: RealNameInfoResponse = await response.data;

if (realNameInfoData.error) {
console.error(realNameInfoData.error);
return false;
}

return realNameInfoData.data.isRealName;
} catch (error) {
console.error(error);
return false;
}
};

0 comments on commit 2ca25f5

Please sign in to comment.