feat(add enterprise real name auth) (#5347)

* feat(add enterprise real name auth

* chore

* ok

* chore

* chore

* chore
This commit is contained in:
limbo
2025-01-20 11:03:28 +08:00
committed by GitHub
parent 922a610d1d
commit f0bfe7ecad
23 changed files with 1463 additions and 762 deletions
+1
View File
@@ -42,5 +42,6 @@ yalc.lock
config.yaml
.env
.env.local
data/config.local.yaml
#/prisma/region/generated/
-2
View File
@@ -42,7 +42,6 @@
"decimal.js": "^10.4.3",
"eslint": "8.38.0",
"eslint-config-next": "13.3.0",
"formidable": "^3.5.1",
"framer-motion": "^10.16.4",
"i18next": "^23.11.5",
"immer": "^10.0.2",
@@ -81,7 +80,6 @@
"devDependencies": {
"@testing-library/jest-dom": "^6.1.3",
"@testing-library/react": "^14.0.0",
"@types/formidable": "^3.4.5",
"@types/jest": "^29.5.10",
"@types/js-cookie": "^3.0.4",
"@types/js-yaml": "^4.0.6",
+45 -15
View File
@@ -3,6 +3,9 @@
"accept": "Accept",
"accept_invitation": "Accept Invitation",
"access": "Access",
"account_bank_required": "Please enter the correct bank name of the enterprise",
"account_number": "Bank Account",
"account_number_required": "Please enter the correct recipient bank account of the enterprise",
"account_settings": "Account Settings",
"added": "Added",
"agree_policy": "I have read and agree to the",
@@ -19,6 +22,7 @@
"attachment": "appendix",
"avatar": "Avatar",
"balance": "Balance",
"bank_name": "Bank",
"bind": "Link",
"bind_success": "Binding successful",
"bonus": "Bonus",
@@ -39,6 +43,9 @@
"confirm": "Confirm",
"confirm_again": "confirm again",
"confirmnewpassword": "Confirm New Password",
"contact_info": "Phone Number",
"contact_info_must_be_numeric": "It must be a numeric string",
"contact_info_required": "Please enter the correct contact information",
"core": "Core",
"cost_center": "Cost Center",
"create_team": "Create Workspace",
@@ -67,9 +74,22 @@
"emailchangesuccess": "Email modified successfully",
"enter": "Enter",
"enter_confirm": "Please enter {{value}} to confirm",
"enterpriseKey": "Enterprise Name (Bank Account Name)",
"enterpriseKeyPlaceholder": "Enter the name of your enterprise",
"enterprise_auth_tips": "We will deposit a small amount into your enterprise bank account.\nConfirm the amount to complete verification. ",
"enterprise_key": "Unified Social Credit Code",
"enterprise_key_required": "Please enter the correct Unified Social Credit Code (USCC) of the enterprise",
"enterprise_keyname": "Enterprise Name (Bank Account Name) ",
"enterprise_keyname_placeholder": "Enter the name of your enterprise",
"enterprise_name": "Company name",
"enterprise_name_required": "Please enter the correct company name",
"enterprise_verification": "Enterprise real name",
"enterprise_name_required": "Please enter the correct enterprise name",
"enterprise_realname_cancel_failed": "Cancellation failed.",
"enterprise_realname_cancel_success": "Cancellation successful.",
"enterprise_realname_payment_failed": "Verify that the payment amount failed to be transferred.",
"enterprise_realname_payment_success": "Verify that the amount has been transferred to your company's bank account.",
"enterprise_realname_verify_failed": "Enterprise real-name verification failed.",
"enterprise_realname_verify_success": "Enterprise real-name verification successful.",
"enterprise_verification": "Enterprise",
"expected_to_use_next_month": "Usage for the next 30 days",
"expected_used": "Estimated Runaway",
"face_recognition_failed": "Personal real name failed",
@@ -83,6 +103,7 @@
"generate_invitation_link": "Generate invitation link",
"get_code": "verification",
"get_code_failed": "Get code failed",
"get_verification_amount": "Request",
"gift_amount": "Reward {{amount}} balance.",
"github": "Github",
"google": "Google",
@@ -109,6 +130,7 @@
"invalid_phone_number": "Invalid phone number",
"invalid_user_id": "Invalid User ID",
"invalid_username_or_password": "Invalid username or password",
"invalid_verification_amount": "The verification amount format is invalid",
"invalid_verification_code": "Invalid verification code",
"invitation_reminder": "Invitation reminder",
"invite_member": "Invite Member",
@@ -118,8 +140,10 @@
"laf_on_sealos": "Laf on Sealos",
"language": "Language",
"launch_various_third-party_applications_with_one_click": "Launch various third-party applications with one click",
"legal_person": "Legal Representative",
"license_buy": "License Buy",
"link": "link",
"link_to_workorder": "Submit a Ticket",
"loading": "Loading",
"log_in": "Log In",
"log_out": "Log Out",
@@ -149,7 +173,7 @@
"next_time": "Next",
"nickname": "Nickname",
"no_apps_found": "No Apps Found",
"no_realname_auth": "NO REALNAME AUTH",
"no_realname_auth": "Identity Not Verified",
"notification": "Notification",
"noworkspacecreated": "You haven't created a workspace yet",
"official_account_login": "Official account login",
@@ -168,17 +192,18 @@
"payment_result": "Payment Result",
"payment_status": "Payment Status",
"payment_successful": "Payment Successful",
"personal_verification": "Personal real name",
"personal_verification": "Individual",
"phone": "Phone",
"phone_number_tips": "Phone Number",
"phonechangesuccess": "Mobile phone number modified successfully",
"please_enter": "Please enter",
"please_enter_account_number": "Enter the bank account number",
"please_enter_bank_name": "Enter a bank name",
"please_enter_contact_info": "Enter the phone number",
"please_enter_enterprise_key": "Enter the Unified Social Credit Code",
"please_enter_legal_person": "Enter the name of the legal representative",
"please_enter_username": "Please enter your username",
"please_enter_your_enterprise_name": "Please enter your business name",
"please_fill_all_fields": "File cannot be empty",
"please_read_and_agree_to_the_agreement": "Please read and agree to the agreement",
"please_upload_the_business_license": "Please upload a photo of your business license",
"please_upload_the_supporting_materials": "Please sign and stamp the downloaded attachment and upload a photo",
"please_enter_verification_amount": "Enter the verification amount (in cents).",
"privacy_policy": "Privacy Policy",
"private_team_id_of_user": "User's ID",
"purchase_history": "Purchase History",
@@ -190,12 +215,11 @@
"read_all": "Read All",
"read_and_agree": "Please read and agree to the agreement below",
"realNameVerification": "Real Name Verification",
"realName_verification": "Real Name Verification",
"realName_verification": "Identity Verification",
"realname_auth_now": "Click to verify your name",
"realname_auth_reminder": "Real-name authentication reminder",
"realname_auth_reminder_desc": "Real-name verification is required for regions in China. Without real-name verification, top-up will be restricted. Successful real-name verification will be rewarded with a {{reward}} Sealos balance.",
"realname_auth_tips_a": "1. Please ensure that the name, ID number and mobile phone number filled in are consistent.",
"realname_auth_tips_b": "2. The number segments provided by some virtual operators may not pass verification. Please apply for a work order and pass manual verification.",
"realname_auth_reminder_desc_no_reward": "Real-name verification is required for regions in China. Without real-name verification, top-up will be restricted.",
"realname_info": "RealName",
"receive_tips": "{{managerName}} invite you join in {{teamName}} as {{role}}",
"recharge_amount": "Recharge Amount",
@@ -208,6 +232,7 @@
"remain_other_region_resource_tips": "There are still associated resources that have not been deleted in your account. To help you successfully complete the account cancellation process, please clean up all region resources to ensure that nothing is missing.",
"remain_template_tips": "There are still undeleted template resources in your account. To help you smoothly complete the account cancellation process, please manually delete all template resources to avoid data loss",
"remain_workspace_tips": "There are still undeleted associated resources in your account. To help you successfully complete the account cancellation process, please clean up or transfer your workspace to avoid data loss.",
"remaining_attempts": "{{count}} times left",
"remaining_time": "Remaining Time: ",
"remove": "Remove",
"remove_member_tips": "Determine that you want to remove the member?",
@@ -229,22 +254,23 @@
"status": "Status",
"storage": "Storage",
"submit_error": "Submit Error",
"supporting_materials": "Proof material",
"submit_verification": "Submit ",
"switching_disc": "Switching Disc",
"team": "Workspace",
"terminal": "Terminal",
"the_invited_user_must_be_others": "The invited user must be others",
"toggle_app_bar": "Toggle App Bar",
"total_amount": "Total Amount",
"transAmt_not_match": "The verification amount does not match. Please note that the verification amount is in cents. For example, if the received amount is 0.23 yuan, enter 23.",
"unbind": "Unbind",
"unbind_success": "Unbinding successfully",
"unbound": "Not Linked",
"under_active_development": "Under active development 🚧",
"unread": "Unread",
"upload_success": "Upload successful",
"used_last_month": "Usage for the last 30 days",
"used_resources": "Resources Used",
"user_name": "User Name",
"user_name_required": "Please enter the correct name of the enterprise's legal representative",
"username": "Username",
"username_tips": "Username must be 3-16 characters, including letters, numbers",
"usertask": {
@@ -255,6 +281,10 @@
"task_launchpad_desc": "Create a container cluster with one click, automatically deploy container applications, and provide intranet/extranet access addresses",
"task_launchpad_title": "Deploy App"
},
"verification_amount": "Verification Amount",
"verification_amount_required": "The verification amount cannot be empty",
"verification_amount_tips": "Shanghai UnionPay will deposit a random amount into your bank account for\nverification, typically arriving in real-time. If not received in 3 business day, please ",
"verification_amount_tips2": "Please confirm the deposited verification amount with your finance team. It usually arrives in real-time.",
"verification_code_login": "with Phone",
"verify_code_tips": "6-digit Verification Code",
"verify_password": "Verify password",
@@ -272,4 +302,4 @@
"you_can_view_fees_through_the_fee_center": "You can view fees through the fee center",
"you_have_not_purchased_the_license": "You have not purchased the License",
"yuan": "Yuan"
}
}
+37 -9
View File
@@ -3,6 +3,9 @@
"accept": "接受",
"accept_invitation": "接受邀请",
"access": "权限",
"account_bank_required": "请输入正确的企业开户行",
"account_number": "银行账号",
"account_number_required": "请输入正确的企业开户行收款银行账号",
"account_settings": "账户设置",
"added": "已加入",
"agree_policy": "我已阅读并同意",
@@ -18,6 +21,7 @@
"attachment": "附件",
"avatar": "头像",
"balance": "余额",
"bank_name": "开户银行",
"bind": "绑定",
"bind_success": "绑定成功",
"bonus": "赠",
@@ -38,6 +42,9 @@
"confirm": "确认",
"confirm_again": "再次确认",
"confirmnewpassword": "确认新密码",
"contact_info": "联系方式 (手机号码)",
"contact_info_must_be_numeric": "必须是数字字符串",
"contact_info_required": "请输入正确的联系方式",
"core": "核",
"create_team": "创建工作空间",
"created_time": "创建时间",
@@ -64,8 +71,19 @@
"emailchangesuccess": "电子邮箱修改成功",
"enter": "输入",
"enter_confirm": "请输入 {{value}} 确认",
"enterprise_auth_tips": "我们会向你提交的对公账户进行小额打款, 请输入收到的金额完成验证。",
"enterprise_key": "统一社会信用代码",
"enterprise_key_required": "请输入正确的企业统一社会信用代码",
"enterprise_keyname": "企业名称 (需与银行开户名一致)",
"enterprise_keyname_placeholder": "请输入企业名称 (需与银行开户名一致)",
"enterprise_name": "企业名称",
"enterprise_name_required": "请输入正确的企业名字",
"enterprise_realname_cancel_failed": "取消失败",
"enterprise_realname_cancel_success": "取消成功",
"enterprise_realname_payment_failed": "验证金额打款失败",
"enterprise_realname_payment_success": "验证金额已经打款到您的企业开户银行",
"enterprise_realname_verify_failed": "企业实名失败",
"enterprise_realname_verify_success": "企业实名成功",
"enterprise_verification": "企业实名",
"expected_to_use_next_month": "未来30天预计使用",
"expected_used": "预计还能使用",
@@ -80,6 +98,7 @@
"generate_invitation_link": "生成邀请链接",
"get_code": "获取验证码",
"get_code_failed": "获取验证码失败",
"get_verification_amount": "获取验证金额",
"gift_amount": "赠送 {{amount}} 余额.",
"github": "Github",
"google": "Google",
@@ -106,6 +125,7 @@
"invalid_phone_number": "无效的手机号",
"invalid_user_id": "用户的 ID 不合法",
"invalid_username_or_password": "用户名或密码错误",
"invalid_verification_amount": "验证金额格式不合法",
"invalid_verification_code": "无效的验证码",
"invitation_reminder": "受邀提醒",
"invite_member": "邀请成员",
@@ -114,8 +134,10 @@
"jump_over": "跳过",
"language": "语言",
"launch_various_third-party_applications_with_one_click": "一键启动各种第三方应用",
"legal_person": "法定代表人",
"license_buy": "License 购买",
"link": "链接",
"link_to_workorder": "提交工单",
"loading": "加载中",
"log_in": "登录",
"log_out": "登出",
@@ -169,12 +191,13 @@
"phone_number_tips": "手机号",
"phonechangesuccess": "手机号修改成功",
"please_enter": "请输入",
"please_enter_account_number": "请输入银行账号",
"please_enter_bank_name": "请输入开户行名",
"please_enter_contact_info": "请输入联系方式",
"please_enter_enterprise_key": "请输入统一社会信用代码",
"please_enter_legal_person": "请输入法人姓名",
"please_enter_username": "请输入您的用户名",
"please_enter_your_enterprise_name": "请输入您的企业名称",
"please_fill_all_fields": "文件不能为空",
"please_read_and_agree_to_the_agreement": "请阅读并同意协议",
"please_upload_the_business_license": "请上传企业的营业执照照片",
"please_upload_the_supporting_materials": "请在下载的附件上签名并盖好公章,上传照片",
"please_enter_verification_amount": "请输入验证金额(单位分)",
"privacy_policy": "隐私政策",
"private_team_id_of_user": "用户ID",
"purchase_history": "购买记录",
@@ -190,8 +213,7 @@
"realname_auth_now": "点击进行实名",
"realname_auth_reminder": "实名认证提醒",
"realname_auth_reminder_desc": "国内可用区需要实名认证,未实名认证将会被限制充值,实名认证成功奖励 Sealos 余额 {{reward}} 元。",
"realname_auth_tips_a": "1、请确保所填写的姓名、身份证号码和手机号码信息一致。",
"realname_auth_tips_b": "2、部分虚拟运营商提供的号段可能无法验证通过,请申请工单通过人工协助认证。",
"realname_auth_reminder_desc_no_reward": "国内可用区需要实名认证,未实名认证将会被限制充值。",
"realname_info": "实名信息",
"receive_tips": "{{managerName}} 邀请你到 {{teamName}} 成为 {{role}}",
"recharge_amount": "充值金额",
@@ -204,6 +226,7 @@
"remain_other_region_resource_tips": "您好,您的账户中仍有未删除的关联资源,为了帮助您顺利完成账户注销流程,请您清理所有可用区资源,确保无遗漏。",
"remain_template_tips": "您的账户中仍有未删除的模板资源,为了帮助您顺利完成账户注销流程,请您手动删除所有模板资源,以避免数据丢失",
"remain_workspace_tips": "您的账户中仍有未删除的关联资源,为了帮助您顺利完成账户注销流程,请您清理或转移您的工作空间,以避免数据丢失",
"remaining_attempts": "剩余 {{count}} 次",
"remaining_time": "剩余激活时间: ",
"remove": "移除",
"remove_member_tips": "确认要移除该成员?",
@@ -224,20 +247,21 @@
"status": "状态",
"storage": "存储",
"submit_error": "提交错误",
"supporting_materials": "证明材料",
"submit_verification": "提交认证 ",
"switching_disc": "切换圆盘",
"team": "工作空间",
"the_invited_user_must_be_others": "只能邀请其他人",
"toggle_app_bar": "切换应用栏",
"transAmt_not_match": "验证金额不匹配,注意验证金额单位是分,例如收到的打款金额为 0.23 元 则输入23。",
"unbind": "解绑",
"unbind_success": "解绑成功",
"unbound": "未绑定",
"under_active_development": "正在积极开发中 🚧",
"unread": "未读",
"upload_success": "上传成功",
"used_last_month": "过去30天已使用",
"used_resources": "已用资源",
"user_name": "用户名",
"user_name_required": "请输入正确的企业法人姓名",
"username": "用户名",
"username_tips": "用户名为3-16位的英文或数字的字符",
"usertask": {
@@ -248,6 +272,10 @@
"task_launchpad_desc": "一键创建容器集群,自动化 部署容器应用,并提供内 网/外网访问地址",
"task_launchpad_title": "部署应用"
},
"verification_amount": "验证金额",
"verification_amount_required": "验证金额不能为空",
"verification_amount_tips": "验证金额将由上海银联打入你提交的对公账号, 金额随机, 一般实时到账。若三个工作日内未收到, 请",
"verification_amount_tips2": "请联系公司财务确认企业银行账户收到的验证金额, 一般实时到账, 长期有效。",
"verification_code_login": "手机号登录",
"verify_code_tips": "6位验证码",
"verify_password": "确认密码",
+37 -11
View File
@@ -6,6 +6,7 @@ import { ApiResp, Region } from '@/types';
import { BIND_STATUS } from '@/types/response/bind';
import { RESOURCE_STATUS } from '@/types/response/checkResource';
import { DELETE_USER_STATUS } from '@/types/response/deleteUser';
import { EnterpriseAuthInfo, PAYMENTSTATUS } from '@/types/response/enterpriseRealName';
import { USER_MERGE_STATUS } from '@/types/response/merge';
import { UNBIND_STATUS } from '@/types/response/unbind';
import { SemData } from '@/types/sem';
@@ -58,7 +59,6 @@ export const _UserInfo = (request: AxiosInstance) => () =>
ApiResp<{
info: {
realName?: string;
enterpriseVerificationStatus?: string;
enterpriseRealName?: string;
userRestrictedLevel?: number;
uid: string;
@@ -172,15 +172,37 @@ export const _getFaceAuthStatusRequest = (request: AxiosInstance) => (data: { bi
data
);
export const _enterpriseRealNameAuthRequest = (request: AxiosInstance) => (data: FormData) => {
return request.post<any, ApiResp<{ status: string }>>(
'/api/account/enterpriseRealNameAuth',
data,
{
headers: {
'Content-Type': 'multipart/form-data'
}
}
export const _enterpriseRealNameAuthPaymentRequest =
(request: AxiosInstance) =>
(data: {
key: string;
accountBank: string;
accountNo: string;
keyName: string;
usrName: string;
contactInfo: string;
}) => {
return request.post<typeof data, ApiResp<{ paymentStatus: PAYMENTSTATUS }>>(
'/api/account/enterpriseRealName',
data
);
};
export const _enterpriseRealNameAuthVerifyRequest =
(request: AxiosInstance) => (data: { transAmt: string }) => {
return request.post<
typeof data,
ApiResp<{ authState: 'success' | 'failed'; enterpriseRealName: string }>
>('/api/account/enterpriseRealNameVerify', data);
};
export const _enterpriseRealNameAuthInfoRequest = (request: AxiosInstance) => () => {
return request.get<any, ApiResp<EnterpriseAuthInfo>>('/api/account/enterpriseRealName');
};
export const _enterpriseRealNameAuthCancelRequest = (request: AxiosInstance) => () => {
return request.patch<any, ApiResp<{ paymentStatus: PAYMENTSTATUS }>>(
'/api/account/enterpriseRealName'
);
};
@@ -211,7 +233,11 @@ export const deleteUserRequest = _deleteUser(request);
export const checkRemainResource = _checkRemainResource(request);
export const forceDeleteUser = _forceDeleteUser(request);
export const enterpriseRealNameAuthRequest = _enterpriseRealNameAuthRequest(request);
export const enterpriseRealNameAuthPaymentRequest = _enterpriseRealNameAuthPaymentRequest(request);
export const enterpriseRealNameAuthVerifyRequest = _enterpriseRealNameAuthVerifyRequest(request);
export const enterpriseRealNameAuthInfoRequest = _enterpriseRealNameAuthInfoRequest(request);
export const enterpriseRealNameAuthCancelRequest = _enterpriseRealNameAuthCancelRequest(request);
export const faceAuthGenerateQRcodeUriRequest = _faceAuthGenerateQRcodeUriRequest(request);
export const getFaceAuthStatusRequest = _getFaceAuthStatusRequest(request);
@@ -222,14 +222,34 @@ export default function Index(props: Omit<IconButtonProps, 'aria-label'>) {
<ConfigItem
LeftElement={<Text>{t('common:realname_info')}</Text>}
RightElement={
infoData.data.enterpriseVerificationStatus === 'Success' ||
infoData.data.realName ? (
<Flex flex={1}>
infoData.data.enterpriseRealName || infoData.data.realName ? (
<Flex flex={1} alignItems="center" gap="4px">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="17"
viewBox="0 0 16 17"
fill="none"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M12.6667 4.43778L8.41778 2.98243C8.13698 2.88625 7.83213 2.88651 7.55151 2.98317L3.33333 4.43606V9.42245C3.33333 11.9998 5.42267 14.0891 8 14.0891C10.5773 14.0891 12.6667 11.9998 12.6667 9.42245V4.43778ZM2.31306 3.37727C2.12574 3.44179 2 3.61808 2 3.81621V9.42245C2 12.7362 4.68629 15.4225 8 15.4225C11.3137 15.4225 14 12.7362 14 9.42245V3.81679C14 3.61838 13.8739 3.44191 13.6862 3.37761L8.84983 1.72104C8.28825 1.52868 7.67854 1.5292 7.11729 1.72252L2.31306 3.37727ZM5.10471 7.85479C5.36506 7.59444 5.78717 7.59444 6.04752 7.85479L7.58137 9.38864L10.4987 6.47126C10.7591 6.21091 11.1812 6.21091 11.4416 6.47126C11.7019 6.73161 11.7019 7.15372 11.4416 7.41407L8.05518 10.8005C8.04844 10.8072 8.0416 10.8137 8.03465 10.8201C7.7732 11.063 7.3643 11.0572 7.10987 10.8028L5.10471 8.7976C4.84436 8.53725 4.84436 8.11514 5.10471 7.85479Z"
fill="#039855"
/>
</svg>
<Text
maxWidth="200px"
whiteSpace="nowrap"
overflow="hidden"
textOverflow="ellipsis"
color="var(--light-general-on-surface-lowest, var(--Gray-Modern-500, #667085))"
fontFamily="PingFang SC"
fontSize="14px"
fontStyle="normal"
fontWeight={500}
lineHeight="20px"
letterSpacing="0.1px"
>
{infoData?.data.enterpriseRealName || infoData?.data.realName}
</Text>
@@ -240,8 +260,37 @@ export default function Index(props: Omit<IconButtonProps, 'aria-label'>) {
_active={{ transform: 'scale(0.95)' }}
colorScheme="red"
onClick={() => setPageState(PageState.REALNAME_AUTH)}
display="flex"
padding="4px 4px 4px 8px"
justifyContent="center"
alignItems="center"
gap="2px"
borderRadius="6px"
bg="var(--Red-50, #FEF3F2)"
color="var(--Red-500, #F04438)"
fontFamily="PingFang SC"
fontSize="14px"
fontStyle="normal"
fontWeight="500"
lineHeight="20px"
letterSpacing="0.1px"
textTransform="none"
>
{t('common:no_realname_auth')} <CloseIcon boxSize={3} ml={1} />
{t('common:no_realname_auth')}
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="17"
viewBox="0 0 16 17"
fill="none"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.52876 4.02876C5.26841 4.28911 5.26841 4.71122 5.52876 4.97157L9.05735 8.50016L5.52876 12.0288C5.26841 12.2891 5.26841 12.7112 5.52876 12.9716C5.78911 13.2319 6.21122 13.2319 6.47157 12.9716L10.4716 8.97157C10.7319 8.71122 10.7319 8.28911 10.4716 8.02876L6.47157 4.02876C6.21122 3.76841 5.78911 3.76841 5.52876 4.02876Z"
fill="#F04438"
/>
</svg>
</Badge>
)
}
File diff suppressed because it is too large Load Diff
@@ -127,7 +127,7 @@ export default function Desktop(props: any) {
useEffect(() => {
if (infoData.isSuccess && commonConfig?.realNameAuthEnabled) {
if (!infoData?.data?.realName && infoData?.data?.enterpriseVerificationStatus !== 'Success') {
if (!infoData?.data?.realName && !infoData?.data?.enterpriseRealName) {
realNameAuthNotificationIdRef.current = realNameAuthNotification({
duration: null,
isClosable: true
@@ -95,8 +95,6 @@ export default function usePassword({
userId: payload.userId,
userUid: payload.userUid,
realName: infoData.data?.info.realName || undefined,
enterpriseVerificationStatus:
infoData.data?.info.enterpriseVerificationStatus || undefined,
enterpriseRealName: infoData.data?.info.enterpriseRealName || undefined,
userRestrictedLevel: infoData.data?.info.userRestrictedLevel || undefined
},
@@ -54,8 +54,6 @@ export default function useWechat() {
userId: payload.userId,
realName: infoData.data?.info.realName || undefined,
userRestrictedLevel: infoData.data?.info.userRestrictedLevel || undefined,
enterpriseVerificationStatus:
infoData.data?.info.enterpriseVerificationStatus || undefined,
enterpriseRealName: infoData.data?.info.enterpriseRealName || undefined
},
// @ts-ignore
@@ -0,0 +1,320 @@
import { jsonRes } from '@/services/backend/response';
import { enableEnterpriseRealNameAuth } from '@/services/enable';
import type { NextApiRequest, NextApiResponse } from 'next';
import { generateAuthenticationToken, verifyAccessToken } from '@/services/backend/auth';
import { globalPrisma } from '@/services/backend/db/init';
import { z } from 'zod';
import { PAYMENTSTATUS } from '@/types/response/enterpriseRealName';
import { EnterpriseAuthInfo } from '@/types/response/enterpriseRealName';
import { AdditionalInfo } from '@/types/response/enterpriseRealName';
import { AccessTokenPayload } from '@/types/token';
type JsonValue = string | number | boolean | object | null;
type RealNameAuthProvider = {
id: string;
backend: string;
authType: string;
maxFailedTimes: number;
config: JsonValue;
createdAt: Date;
updatedAt: Date;
};
type UnionPay3060Config = {
api: string;
};
interface ApiError {
detail: any;
errorId: string;
message: string;
timestamp: number;
code: string;
}
interface EnterpriseAuthResponse {
subBank: string;
transAmt: string;
orderId: string;
isCharged: boolean;
legalPersonName: string;
isTransactionSuccess: boolean;
key: string;
enterpriseName: string;
accountCity: string;
respCode: string;
respMsg: string;
accountProv: string;
accountBank: string;
accountNo: string;
}
interface ApiResponse {
error?: ApiError;
data?: EnterpriseAuthResponse;
success: boolean;
}
const schema = z.object({
key: z.string().min(1),
accountBank: z.string().min(1),
accountNo: z.string().min(1),
keyName: z.string().min(1),
usrName: z.string().min(1),
contactInfo: z.string().min(1).regex(/^\d+$/, 'Contact info must contain only numbers')
});
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (!enableEnterpriseRealNameAuth) {
console.error('enterpriseRealNameAuth: enterprise real name authentication not enabled');
return jsonRes(res, { code: 503, message: 'Enterprise real name authentication not enabled' });
}
const payload = await verifyAccessToken(req.headers);
if (!payload) return jsonRes(res, { code: 401, message: 'Token is invalid' });
switch (req.method) {
case 'GET':
return handleGet(req, res, payload.userUid);
case 'POST':
return handlePost(req, res, payload.userUid, payload);
case 'PATCH':
return handlePatch(req, res, payload.userUid);
default:
console.error('enterpriseRealNameAuth: Method not allowed');
return jsonRes(res, { code: 405, message: 'Method not allowed' });
}
}
async function handleGet(req: NextApiRequest, res: NextApiResponse, userUid: string) {
try {
const realNameAuthProvider: RealNameAuthProvider | null =
await globalPrisma.realNameAuthProvider.findFirst({
where: {
backend: 'UNIONPAY',
authType: '3060'
}
});
if (!realNameAuthProvider) {
throw new Error('enterpriseRealNameAuth: Real name authentication provider not found');
}
const info = await globalPrisma.enterpriseRealNameInfo.findUnique({
where: { userUid }
});
if (!info || !info.additionalInfo) {
return jsonRes(res, { code: 200, data: { authTimes: realNameAuthProvider.maxFailedTimes } });
}
const additionalInfo = info.additionalInfo as unknown as AdditionalInfo;
const response: EnterpriseAuthInfo = {
paymentStatus: additionalInfo.paymentStatus,
key: additionalInfo.key,
accountBank: additionalInfo.accountBank,
accountNo: additionalInfo.accountNo,
keyName: additionalInfo.keyName,
usrName: additionalInfo.usrName,
contactInfo: additionalInfo.contactInfo,
remainingAttempts: realNameAuthProvider.maxFailedTimes - (additionalInfo.authTimes || 0)
};
return jsonRes(res, { code: 200, data: response });
} catch (error) {
console.error('Error fetching enterprise auth info:', error);
return jsonRes(res, { code: 500, message: 'Internal server error' });
}
}
async function handlePost(
req: NextApiRequest,
res: NextApiResponse,
userUid: string,
payload: AccessTokenPayload
) {
try {
const realNameAuthProvider: RealNameAuthProvider | null =
await globalPrisma.realNameAuthProvider.findFirst({
where: {
backend: 'UNIONPAY',
authType: '3060'
}
});
if (!realNameAuthProvider) {
throw new Error('enterpriseRealNameAuth: Real name authentication provider not found');
}
const config: UnionPay3060Config = realNameAuthProvider.config as UnionPay3060Config;
if (!config) {
throw new Error('enterpriseRealNameAuth: Real name authentication configuration not found');
}
const enterpriseRealNameAuthApi = config.api;
const enterpriseRealName = await globalPrisma.enterpriseRealNameInfo.findUnique({
where: { userUid }
});
if (enterpriseRealName && enterpriseRealName.isVerified) {
return jsonRes(res, {
code: 400,
message: 'Enterprise real name authentication has been completed'
});
}
if (
enterpriseRealName &&
enterpriseRealName.additionalInfo &&
(enterpriseRealName.additionalInfo as unknown as AdditionalInfo).authTimes >=
realNameAuthProvider.maxFailedTimes
) {
return jsonRes(res, {
code: 400,
message: 'Enterprise real name authentication has reached the maximum number of attempts'
});
}
const validationResult = schema.safeParse(req.body);
if (!validationResult.success) {
return jsonRes(res, {
code: 400,
message: 'Invalid request body',
data: validationResult.error.issues
});
}
const data = validationResult.data;
const globalToken = generateAuthenticationToken({
userUid: payload.userUid,
userId: payload.userId,
regionUid: payload.regionUid
});
const response = await fetch(enterpriseRealNameAuthApi, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${globalToken}`
},
cache: 'no-store',
body: JSON.stringify({
key: data.key,
accountBank: data.accountBank,
accountNo: data.accountNo,
keyName: data.keyName,
usrName: data.usrName
})
});
const apiResponse: ApiResponse = await response.json();
if (!apiResponse.success) {
return jsonRes(res, {
code: 400,
message: apiResponse?.error?.message || 'API request failed'
});
}
if (!apiResponse.data?.isTransactionSuccess || !apiResponse.data?.transAmt) {
return jsonRes(res, {
code: 400,
message: `request failed, code: ${apiResponse.data?.respCode}, message: ${apiResponse.data?.respMsg}`
});
}
if (!response.ok) {
throw new Error(`API request failed with status ${response.status}`);
}
await globalPrisma.enterpriseRealNameInfo.upsert({
where: { userUid },
update: {
enterpriseName: apiResponse.data.enterpriseName,
isVerified: false,
additionalInfo: {
paymentStatus: PAYMENTSTATUS.PROCESSING,
key: apiResponse.data.key,
accountBank: apiResponse.data.accountBank,
accountNo: apiResponse.data.accountNo,
keyName: apiResponse.data.enterpriseName,
usrName: apiResponse.data.legalPersonName,
contactInfo: data.contactInfo,
transAmt: apiResponse.data.transAmt,
authTimes: (enterpriseRealName?.additionalInfo as unknown as AdditionalInfo)?.authTimes
? (enterpriseRealName?.additionalInfo as unknown as AdditionalInfo).authTimes + 1
: 1
}
},
create: {
userUid,
enterpriseName: apiResponse.data.enterpriseName,
isVerified: false,
additionalInfo: {
paymentStatus: PAYMENTSTATUS.PROCESSING,
key: apiResponse.data.key,
accountBank: apiResponse.data.accountBank,
accountNo: apiResponse.data.accountNo,
keyName: apiResponse.data.enterpriseName,
usrName: apiResponse.data.legalPersonName,
contactInfo: data.contactInfo,
transAmt: apiResponse.data.transAmt,
authTimes: 1
}
}
});
return jsonRes(res, {
code: 200,
message: 'Enterprise auth request processed successfully',
data: {
paymentStatus: PAYMENTSTATUS.PROCESSING
}
});
} catch (error) {
console.error('Error processing enterprise auth request:', error);
return jsonRes(res, { code: 500, message: 'Internal server error' });
}
}
async function handlePatch(req: NextApiRequest, res: NextApiResponse, userUid: string) {
try {
const info = await globalPrisma.enterpriseRealNameInfo.findUnique({
where: { userUid }
});
if (!info) {
return jsonRes(res, { code: 404, message: 'Enterprise auth info not found' });
}
if (info.isVerified) {
return jsonRes(res, { code: 400, message: 'Enterprise auth has been completed' });
}
await globalPrisma.enterpriseRealNameInfo.update({
where: { userUid },
data: {
additionalInfo: {
...(info.additionalInfo as object),
paymentStatus: PAYMENTSTATUS.CANCEL
}
}
});
return jsonRes(res, {
code: 200,
message: 'Payment status updated successfully',
data: {
paymentStatus: PAYMENTSTATUS.CANCEL
}
});
} catch (error) {
console.error('Error updating payment status:', error);
return jsonRes(res, { code: 500, message: 'Internal server error' });
}
}
@@ -1,245 +0,0 @@
import { jsonRes } from '@/services/backend/response';
import { enableEnterpriseRealNameAuth } from '@/services/enable';
import type { NextApiRequest, NextApiResponse } from 'next';
import { verifyAccessToken } from '@/services/backend/auth';
import { globalPrisma } from '@/services/backend/db/init';
import { RealNameOSSConfigType } from '@/types';
import * as Minio from 'minio';
import formidable, { Fields, Files, File, Part } from 'formidable';
import path from 'path';
import Formidable from 'formidable/Formidable';
import fs from 'fs/promises';
export const config = {
api: {
bodyParser: false
}
};
const realNameOSS: RealNameOSSConfigType = global.AppConfig.realNameOSS;
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
const ALLOWED_FILE_TYPES = ['image/jpeg', 'image/png', 'application/pdf'];
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (!enableEnterpriseRealNameAuth) {
console.error('enterpriseRealNameAuth: enterprise real name authentication not enabled');
return jsonRes(res, { code: 503, message: 'Enterprise real name authentication not enabled' });
}
if (req.method !== 'POST') {
console.error('enterpriseRealNameAuth: Method not allowed');
return jsonRes(res, { code: 405, message: 'Method not allowed' });
}
const payload = await verifyAccessToken(req.headers);
if (!payload) return jsonRes(res, { code: 401, message: 'Token is invalid' });
if (!realNameOSS) {
return jsonRes(res, {
code: 500,
message: 'Real name authentication oss configuration not found'
});
}
try {
const userUid = payload.userUid;
const form = formidable({
multiples: false,
keepExtensions: true,
maxFileSize: MAX_FILE_SIZE,
filter: function (part: Part): boolean {
return part.mimetype !== null && ALLOWED_FILE_TYPES.includes(part.mimetype);
},
filename: function (name: string, ext: string, part: Part, form: Formidable): string {
const sanitizedName = sanitizeFilename(part.originalFilename || 'unnamed');
return sanitizedName;
}
});
const formData = await parseFormData(req, form);
const { fields, files } = formData;
const enterpriseName = fields.enterpriseName?.[0];
if ((enterpriseName && enterpriseName.length < 1) || enterpriseName.length > 20) {
return jsonRes(res, {
code: 400,
message: 'Enterprise name must be between 1 and 20 characters'
});
}
if (!files.enterpriseQualification?.[0] || !files.supportingMaterials?.[0]) {
return jsonRes(res, {
code: 400,
message: 'Enterprise qualification and supporting materials are required'
});
}
if (
files &&
files.enterpriseQualification?.[0] &&
files.enterpriseQualification?.[0].size > MAX_FILE_SIZE
) {
return jsonRes(res, {
code: 400,
message: 'Enterprise qualification file size exceeds the maximum limit'
});
}
if (
files &&
files.supportingMaterials?.[0] &&
files.supportingMaterials?.[0].size > MAX_FILE_SIZE
) {
return jsonRes(res, {
code: 400,
message: 'Supporting materials file size exceeds the maximum limit'
});
}
// Check if EnterpriseRealNameInfo exists
const existingInfo = await globalPrisma.enterpriseRealNameInfo.findUnique({
where: { userUid }
});
if (!existingInfo) {
// Create new EnterpriseRealNameInfo
const ossPaths = await uploadFiles(userUid, files);
await createEnterpriseRealNameInfo(userUid, enterpriseName, ossPaths);
return jsonRes(res, {
code: 200,
message: 'Enterprise real name authentication submitted successfully',
data: { status: 'Pending' }
});
}
// Handle existing EnterpriseRealNameInfo cases
switch (existingInfo.verificationStatus) {
case 'Pending':
return jsonRes(res, { code: 400, message: 'Authentication is under review' });
case 'Success':
return jsonRes(res, { code: 400, message: 'Cannot authenticate multiple times' });
case 'Failed':
// Re-upload files and update EnterpriseRealNameInfo
const newOssPaths = await uploadFiles(userUid, files);
await updateEnterpriseRealNameInfo(existingInfo.id, enterpriseName, newOssPaths);
return jsonRes(res, {
code: 200,
data: { status: 'Pending' },
message: 'Enterprise real name authentication resubmitted successfully'
});
default:
return jsonRes(res, { code: 500, message: 'Invalid verification status' });
}
} catch (error) {
console.error('enterpriseRealNameAuth: Internal error', error);
return jsonRes(res, { code: 500, message: 'The server has encountered an error' });
}
}
// Helper functions
async function parseFormData(req: NextApiRequest, form: Formidable): Promise<any> {
return new Promise((resolve, reject) => {
form.parse(req, (err: Error, fields: Fields, files: Files) => {
if (err) {
reject(err);
} else {
resolve({ fields, files });
}
});
});
}
function sanitizeFilename(filename: string): string {
// Remove any path components
const basename = path.basename(filename);
// Define a blacklist of malicious characters
const blacklist = /[<>:"/\\|?*\x00-\x1F]/g;
// Replace blacklisted characters with underscores
return basename.replace(blacklist, '_');
}
async function uploadFiles(userUid: string, files: Files): Promise<string[]> {
const minioConfig: Minio.ClientOptions = {
endPoint: realNameOSS.endpoint,
accessKey: realNameOSS.accessKey,
secretKey: realNameOSS.accessKeySecret,
useSSL: realNameOSS.ssl
};
const minioClient = new Minio.Client(minioConfig);
const filesToUpload = [
{ file: files.enterpriseQualification?.[0], name: 'enterpriseQualification' },
{ file: files.supportingMaterials?.[0], name: 'supportingMaterials' }
].filter((item) => item.file !== null);
const uploadPromises = filesToUpload.map((item) =>
uploadFile(minioClient, userUid, item.file!, item.name)
);
return await Promise.all(uploadPromises);
}
async function uploadFile(
minioClient: Minio.Client,
userUid: string,
file: File,
fileType: string
): Promise<string> {
const timestamp = Date.now();
const fileName = `${timestamp}_${fileType}_${file.newFilename}`;
const filePath = `/${userUid}/${fileName}`;
try {
await minioClient.fPutObject(realNameOSS.enterpriseRealNameBucket, filePath, file.filepath, {
'Content-Type': file.mimetype || 'application/octet-stream'
});
// Check if the file exists before attempting to delete it
try {
await fs.access(file.filepath);
// If no error is thrown, the file exists, so we can delete it
await fs.unlink(file.filepath);
console.debug(`File ${file.filepath} has been deleted.`);
} catch (accessError) {
// If an error is thrown, the file doesn't exist
console.debug(`File ${file.filepath} does not exist or is not accessible.`);
}
} catch (error) {
console.error('EnterpriseRealNameAuth uploadFile: Error uploading file', error);
throw error;
}
return filePath;
}
async function createEnterpriseRealNameInfo(
userUid: string,
enterpriseName: string,
ossPaths: string[]
) {
await globalPrisma.enterpriseRealNameInfo.create({
data: {
userUid,
enterpriseName: enterpriseName,
supportingMaterials: { ossPaths: ossPaths }, // Remaining paths for supportingMaterials
verificationStatus: 'Pending'
}
});
}
async function updateEnterpriseRealNameInfo(
id: string,
enterpriseName: string,
ossPaths: string[]
) {
await globalPrisma.enterpriseRealNameInfo.update({
where: { id },
data: {
enterpriseName: enterpriseName,
supportingMaterials: { ossPaths: ossPaths },
verificationStatus: 'Pending'
}
});
}
@@ -0,0 +1,95 @@
import { jsonRes } from '@/services/backend/response';
import { enableEnterpriseRealNameAuth } from '@/services/enable';
import type { NextApiRequest, NextApiResponse } from 'next';
import { verifyAccessToken } from '@/services/backend/auth';
import { globalPrisma } from '@/services/backend/db/init';
import { z } from 'zod';
import { PAYMENTSTATUS } from '@/types/response/enterpriseRealName';
import { AdditionalInfo } from '@/types/response/enterpriseRealName';
const schema = z.object({
transAmt: z.string().min(1)
});
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (!enableEnterpriseRealNameAuth) {
console.error('enterpriseRealNameVerify: enterprise real name authentication not enabled');
return jsonRes(res, { code: 503, message: 'Enterprise real name authentication not enabled' });
}
if (req.method !== 'POST') {
console.error('enterpriseRealNameVerify: Method not allowed');
return jsonRes(res, { code: 405, message: 'Method not allowed' });
}
const payload = await verifyAccessToken(req.headers);
if (!payload) return jsonRes(res, { code: 401, message: 'Token is invalid' });
try {
const validationResult = schema.safeParse(req.body);
if (!validationResult.success) {
return jsonRes(res, {
code: 400,
message: 'Invalid request body',
data: validationResult.error.issues
});
}
const { transAmt } = validationResult.data;
const info = await globalPrisma.enterpriseRealNameInfo.findUnique({
where: { userUid: payload.userUid }
});
if (!info || !info.additionalInfo) {
return jsonRes(res, {
code: 404,
data: {
authState: 'failed'
},
message: 'Enterprise auth info not found'
});
}
if (info.isVerified) {
return jsonRes(res, {
code: 400,
message: 'Enterprise real name authentication already verified'
});
}
const additionalInfo = info.additionalInfo as unknown as AdditionalInfo;
if (additionalInfo.transAmt === transAmt) {
await globalPrisma.enterpriseRealNameInfo.update({
where: { userUid: payload.userUid },
data: {
isVerified: true,
additionalInfo: {
...additionalInfo,
paymentStatus: PAYMENTSTATUS.SUCCESS
}
}
});
return jsonRes(res, {
code: 200,
data: {
authState: 'success',
enterpriseRealName: additionalInfo.keyName
}
});
}
return jsonRes(res, {
code: 200,
message: 'transAmt_not_match',
data: {
authState: 'failed'
}
});
} catch (error) {
console.error('Error processing verify request:', error);
return jsonRes(res, { code: 500, message: 'Internal server error' });
}
}
@@ -106,6 +106,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
return jsonRes(res, { code: 400, message: 'User real name info not found' });
}
if (userRealNameInfo.isVerified) {
return jsonRes(res, { code: 400, message: 'User real name info already verified' });
}
let additionalInfo: AdditionalInfo = userRealNameInfo.additionalInfo;
additionalInfo.faceRecognition.callback.isUsed = true;
@@ -351,16 +355,16 @@ async function getUserRealNameInfo(
credential: {
secretId: config.secretId,
secretKey: config.secretKey
},
region: '',
profile: {
signMethod: 'HmacSHA256',
httpProfile: {
endpoint: 'faceid.tencentcloudapi.com',
reqMethod: 'POST',
reqTimeout: 30 // Request timeout, default 60s
}
}
// region: '',
// profile: {
// signMethod: 'HmacSHA256',
// httpProfile: {
// endpoint: 'faceid.tencentcloudapi.com',
// reqMethod: 'POST',
// reqTimeout: 30 // Request timeout, default 60s
// }
// }
});
const params = {
@@ -179,16 +179,16 @@ async function generateRealNameQRcodeUri(
credential: {
secretId: config.secretId,
secretKey: config.secretKey
},
region: '',
profile: {
signMethod: 'HmacSHA256',
httpProfile: {
endpoint: 'faceid.tencentcloudapi.com',
reqMethod: 'POST',
reqTimeout: 30 // Request timeout, default 60s
}
}
// region: '',
// profile: {
// signMethod: 'HmacSHA256',
// httpProfile: {
// endpoint: 'faceid.tencentcloudapi.com',
// reqMethod: 'POST',
// reqTimeout: 30 // Request timeout, default 60s
// }
// }
});
const params = {
+8 -6
View File
@@ -73,7 +73,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
id: string;
name: string;
realName?: string;
enterpriseVerificationStatus?: string;
enterpriseRealName?: string;
userRestrictedLevel?: number;
} = {
@@ -105,13 +104,16 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
}))
};
if (realNameInfo && realNameInfo.isVerified) {
info.realName = realNameInfo.realName || undefined;
if (realNameInfo && realNameInfo.isVerified && realNameInfo.realName) {
info.realName = realNameInfo.realName;
}
if (enterpriseRealNameInfo) {
info.enterpriseVerificationStatus = enterpriseRealNameInfo.verificationStatus || undefined;
info.enterpriseRealName = enterpriseRealNameInfo.enterpriseName || undefined;
if (
enterpriseRealNameInfo &&
enterpriseRealNameInfo.isVerified &&
enterpriseRealNameInfo.enterpriseName
) {
info.enterpriseRealName = enterpriseRealNameInfo.enterpriseName;
}
if (restrictedUser) {
@@ -23,8 +23,7 @@ function genResCommonClientConfig(common: CommonConfigType): CommonClientConfigT
realNameReward: common.realNameReward || 0,
guideEnabled: !!common.guideEnabled,
rechargeEnabled: !!common.rechargeEnabled,
cfSiteKey: common.cfSiteKey || '',
enterpriseSupportingMaterials: common.enterpriseSupportingMaterials || ''
cfSiteKey: common.cfSiteKey || ''
};
}
export async function getCommonClientConfig(): Promise<CommonClientConfigType> {
@@ -0,0 +1,29 @@
export enum PAYMENTSTATUS {
PROCESSING = 'PROCESSING',
FAILED = 'FAILED',
SUCCESS = 'SUCCESS',
CANCEL = 'USER_CANCEL'
}
export interface EnterpriseAuthInfo {
paymentStatus: PAYMENTSTATUS;
key: string;
accountBank: string;
accountNo: string;
keyName: string;
usrName: string;
contactInfo: string;
remainingAttempts: number;
}
export interface AdditionalInfo {
paymentStatus: PAYMENTSTATUS;
key: string;
accountBank: string;
accountNo: string;
keyName: string;
usrName: string;
contactInfo: string;
transAmt: string;
authTimes: number;
}
-1
View File
@@ -8,7 +8,6 @@ export type OAuthToken = {
export type UserInfo = {
readonly userRestrictedLevel?: number;
readonly realName?: string;
readonly enterpriseVerificationStatus?: string;
readonly enterpriseRealName?: string;
readonly k8s_username: string;
readonly name: string;
-2
View File
@@ -9,7 +9,6 @@ export type CloudConfigType = {
export type CommonConfigType = {
enterpriseRealNameAuthEnabled: boolean;
enterpriseSupportingMaterials: string;
realNameAuthEnabled: boolean;
realNameReward: number;
guideEnabled: boolean;
@@ -220,7 +219,6 @@ export type AppClientConfigType = {
export const DefaultCommonClientConfig: CommonClientConfigType = {
enterpriseRealNameAuthEnabled: false,
enterpriseSupportingMaterials: '',
realNameAuthEnabled: false,
realNameReward: 0,
guideEnabled: false,
+1
View File
@@ -1,6 +1,7 @@
export type AuthenticationTokenPayload = {
userUid: string;
userId: string;
regionUid?: string;
};
export type AccessTokenPayload = {
regionUid: string;
@@ -22,7 +22,6 @@ export const sessionConfig = async ({
user: {
userRestrictedLevel: infoData.data?.info.userRestrictedLevel || undefined,
realName: infoData.data?.info.realName || undefined,
enterpriseVerificationStatus: infoData.data?.info.enterpriseVerificationStatus || undefined,
enterpriseRealName: infoData.data?.info.enterpriseRealName || undefined,
k8s_username: payload.userCrName,
name: infoData.data?.info.nickname || '',
-6
View File
@@ -135,9 +135,6 @@ importers:
eslint-config-next:
specifier: 13.3.0
version: 13.3.0(eslint@8.38.0)(typescript@5.2.2)
formidable:
specifier: ^3.5.1
version: 3.5.1
framer-motion:
specifier: ^10.16.4
version: 10.16.5(react-dom@18.2.0)(react@18.2.0)
@@ -247,9 +244,6 @@ importers:
'@testing-library/react':
specifier: ^14.0.0
version: 14.1.2(react-dom@18.2.0)(react@18.2.0)
'@types/formidable':
specifier: ^3.4.5
version: 3.4.5
'@types/jest':
specifier: ^29.5.10
version: 29.5.10