diff --git a/deploy/cloud/etc/sealos/desktop-config.yaml b/deploy/cloud/etc/sealos/desktop-config.yaml index 12dd3f42961..6564d29b550 100644 --- a/deploy/cloud/etc/sealos/desktop-config.yaml +++ b/deploy/cloud/etc/sealos/desktop-config.yaml @@ -3,16 +3,54 @@ kind: Config metadata: name: secret spec: - path: manifests/secret.yaml - # do not modify this image, it's used by ci. - match: ghcr.io/labring/sealos-cloud-desktop-frontend:latest - strategy: merge + path: manifests/configmap.yaml + strategy: override data: | + apiVersion: v1 + kind: ConfigMap + metadata: + name: desktop-frontend-config + namespace: sealos data: - mongodb_uri: - jwt_secret: - password_salt: - jwt_secret_region: - region_database_url: - global_database_url: - region_uid: + config.yaml : | + cloud: + domain: "{{ .cloudDomain }}" + port: "{{ .cloudPort }}" + regionUID: "" + certSecretName: "{{ .certSecretName }}" + common: + guideEnabled: "false" + apiEnabled: "false" + rechargeEnabled: "false" + cfSiteKey: "" + database: + mongodbURI: "" + globalCockroachdbURI: "" + regionalCockroachdbURI: "" + desktop: + layout: + title: "Sealos Cloud" + logo: "/logo.png" + backgroundImage: "/images/bg-blue.svg" + meta: + title: "Sealos Cloud" + description: "Sealos Cloud" + keywords: "Sealos Cloud" + scripts: [] + common: + githubStarEnabled: "true" + auth: + proxyAddress: "" + callbackURL: "https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}/callback" + signUpEnabled: "true" + baiduToken: "" + invite: + enabled: "false" + jwt: + internal: "" + regional: "" + global: "" + idp: + password: + enabled: "true" + salt: "" \ No newline at end of file diff --git a/deploy/cloud/scripts/init.sh b/deploy/cloud/scripts/init.sh index eb9e4387f15..2ea6070779e 100644 --- a/deploy/cloud/scripts/init.sh +++ b/deploy/cloud/scripts/init.sh @@ -135,32 +135,33 @@ function gen_cockroachdbUri() { } function gen_saltKey() { - password_salt=$(kubectl get secret desktop-frontend-secret -n sealos -o jsonpath="{.data.password_salt}" 2>/dev/null || true) + password_salt=$(kubectl get configmap desktop-frontend-config -n sealos -o jsonpath='{.data.config\.yaml}' | grep "salt:" | awk '{print $2}' 2>/dev/null || true) if [[ -z "$password_salt" ]]; then - saltKey=$(tr -dc 'a-z0-9' /dev/null || true) + uid=$(kubectl get configmap desktop-frontend-config -n sealos -o jsonpath='{.data.config\.yaml}' | grep "regionUID:" | awk '{print $2}' 2>/dev/null || true) if [[ -z "$uid" ]]; then localRegionUID=$(uuidgen) else - localRegionUID=$(echo -n "$uid" | base64 -d) + localRegionUID=$(echo -n "$uid")`` fi } function mutate_desktop_config() { - # mutate etc/sealos/desktop-config.yaml by using mongodb uri and two random base64 string - sed -i -e "s;;$(echo -n "${mongodbUri}/sealos-auth?authSource=admin" | base64 -w 0);" etc/sealos/desktop-config.yaml - sed -i -e "s;;$(tr -cd 'a-z0-9' ;$(tr -cd 'a-z0-9' ;$saltKey;" etc/sealos/desktop-config.yaml - sed -i -e "s;;$(echo -n "${cockroachdbLocalUri}" | base64 -w 0);" etc/sealos/desktop-config.yaml - sed -i -e "s;;$(echo -n "${cockroachdbGlobalUri}" | base64 -w 0);" etc/sealos/desktop-config.yaml - sed -i -e "s;;$(echo -n "${localRegionUID}" | base64 -w 0);" etc/sealos/desktop-config.yaml + # mutate etc/sealos/desktop-config.yaml by using mongodb uri and two random string + sed -i -e "s;;$(echo -n "${mongodbUri}/sealos-auth?authSource=admin");" etc/sealos/desktop-config.yaml + sed -i -e "s;;$(tr -cd 'a-z0-9' ;$(tr -cd 'a-z0-9' ;$(tr -cd 'a-z0-9' ;$saltKey;" etc/sealos/desktop-config.yaml + sed -i -e "s;;$(echo -n "${cockroachdbLocalUri}");" etc/sealos/desktop-config.yaml + sed -i -e "s;;$(echo -n "${cockroachdbGlobalUri}");" etc/sealos/desktop-config.yaml + sed -i -e "s;;$(echo -n "${localRegionUID}");" etc/sealos/desktop-config.yaml } function create_tls_secret { @@ -223,7 +224,7 @@ function sealos_run_controller { function sealos_authorize { - sealos run tars/job-init.tar --env PASSWORD_SALT="$(echo -n "$saltKey" | base64 -d)" + sealos run tars/job-init.tar --env PASSWORD_SALT="$(echo -n "$saltKey")" sealos run tars/job-heartbeat.tar # wait for admin user create diff --git a/frontend/desktop/.gitignore b/frontend/desktop/.gitignore index 9e88043fc96..0ee16aefb7b 100644 --- a/frontend/desktop/.gitignore +++ b/frontend/desktop/.gitignore @@ -27,7 +27,7 @@ yarn-error.log* # local env files .env*.local -data/config.local.json +data/*.local # vercel .vercel diff --git a/frontend/desktop/data/config.yaml b/frontend/desktop/data/config.yaml new file mode 100644 index 00000000000..38aba08f427 --- /dev/null +++ b/frontend/desktop/data/config.yaml @@ -0,0 +1,64 @@ +cloud: + domain: "127.0.0.1.nip.io" + port: "" + regionUID: "thisiaregionuid" + certSecretName: "wildcard-cert" +common: + guideEnabled: "false" + apiEnabled: "false" + rechargeEnabled: "false" + cfSiteKey: "" +database: + mongodbURI: "thisismongodburi" + globalCockroachdbURI: "thisisglobalcockroachdburi" + regionalCockroachdbURI: "thisisregionalcockroachdburi" +desktop: + layout: + title: "Sealos Cloud" + logo: "/logo.png" + backgroundImage: "/images/bg-blue.svg" + meta: + title: "Sealos Cloud" + description: "Sealos Cloud" + keywords: "Sealos Cloud" + scripts: [] + common: + githubStarEnabled: "false" + auth: + proxyAddress: "" + callbackURL: "https://127.0.0.1.nip.io/callback" + signUpEnabled: "true" + baiduToken: "" + invite: + enabled: "false" + jwt: + internal: "thisisinternaljwt" + regional: "thisisregionaljwt" + global: "thisisglobaljwt" + idp: + password: + enabled: "true" + salt: "thisispasswordsalt" +# github: +# enabled: "{{ .githubEnabled }}" +# clientId: "{{ .githubClientID }}" +# clientSecret: "{{ .githubClientSecret }}" +# wechat: +# enabled: "{{ .wechatEnabled }}" +# clientId: "{{ .wechatClientID }}" +# clientSecret: "{{ .wechatClientSecret }}" +# sms: +# ali: +# enabled: "{{ .smsEnabled }}" +# endpoint: "{{ .aliSmsEndpoint }}" +# signName: "{{ .aliSmsSignName }}" +# accessKeyId: "{{ .aliAccessKeyID }}" +# accessKeySecret: "{{ .aliAccessKeySecret }}" +# oauth2: +# enabled: "{{ .oauth2Enabled }}" +# callbackURL: "https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}/callback" +# clientId: "{{ .oauth2ClientId }}" +# clientSecret: "{{ .oauth2ClientSecret }}" +# authURL: "{{ .oauth2AuthURL }}" +# tokenURL: "{{ .oauth2TokenURL }}" +# userInfoURL: "{{ .oauth2UserInfoURL }}" diff --git a/frontend/desktop/deploy/Kubefile b/frontend/desktop/deploy/Kubefile index dc7b99afec5..19705c8fcbe 100644 --- a/frontend/desktop/deploy/Kubefile +++ b/frontend/desktop/deploy/Kubefile @@ -8,11 +8,5 @@ COPY scripts scripts ENV cloudDomain="127.0.0.1.nip.io" ENV cloudPort="" ENV certSecretName="wildcard-cert" -ENV passWordEnabled="false" -ENV githubEnabled="false" -ENV wechatEnabled="false" -ENV smsEnabled="false" -ENV signUpEnabled="true" -ENV apiEnabled="false" CMD ["bash scripts/init.sh"] diff --git a/frontend/desktop/deploy/README.md b/frontend/desktop/deploy/README.md index 3f4712eefbc..3aed86ca256 100644 --- a/frontend/desktop/deploy/README.md +++ b/frontend/desktop/deploy/README.md @@ -6,48 +6,81 @@ sealos build -t docker.io/labring/sealos-cloud-desktop:latest -f Kubefile . ### Env -| Name | Description | Default | -|----------------------------|-----------------------------|----------------------------------------| -| `cloudDomain` | sealos cloud domain | `cloud.example.com` | -| `wildcardCertSecretName` | wildcard cert secret name | `wildcard-cert` | +| Name | Description | Default | +|----------------------------|-----------------------------|--------------------| +| `cloudDomain` | sealos cloud domain | `127.0.0.1.nip.io` | +| `wildcardCertSecretName` | wildcard cert secret name | `wildcard-cert` | ### Config -If you enable password login (which is enabled by default), you need to set the password salt by using a config file. - -And this is a command to generate a password salt: -```shell -echo -n "your-password-salt" | base64 -``` - - Here is a config file example: ```yaml # desktop-config.yaml apiVersion: apps.sealos.io/v1beta1 kind: Config metadata: - name: secret + name: configMap spec: - path: manifests/secret.yaml - match: docker.io/labring/sealos-cloud-desktop:latest - strategy: merge + path: manifests/configmap.yaml + strategy: override data: | + apiVersion: v1 + kind: ConfigMap + metadata: + name: desktop-frontend-config + namespace: sealos data: - mongodb_uri: - jwt_secret: - password_salt: + config.yaml : | + cloud: + domain: "127.0.0.1.nip.io" + port: "" + regionUID: "thisiaregionuid" + certSecretName: "wildcard-cert" + common: + guideEnabled: "false" + apiEnabled: "false" + rechargeEnabled: "false" + cfSiteKey: "" + database: + mongodbUri: "thisismongodburi" + globalCockroachdbURI: "thisisglobalcockroachdburi" + regionalCockroachdbURI: "thisisregionalcockroachdburi" + desktop: + layout: + title: "Sealos Cloud" + logo: "/logo.png" + backgroundImage: "/images/bg-blue.svg" + meta: + title: "Sealos Cloud" + description: "Sealos Cloud" + keywords: "Sealos Cloud" + scripts: [] + common: + githubStarEnabled: "false" + auth: + proxyAddress: "" + callbackURL: "https://127.0.0.1.nip.io/callback" + signUpEnabled: "true" + baiduToken: "" + invite: + enabled: "false" + jwt: + internal: "thisisinternaljwt" + regional: "thisisregionaljwt" + global: "thisisglobaljwt" + idp: + password: + enabled: "true" + salt: "thisispasswordsalt" + ``` -*Please make sure `spec.match` is the same as the image you want to run* - ### How to run ```shell sealos run \ --env cloudDomain="127.0.0.1.nip.io" \ --env wildcardCertSecretName="wildcard-cert" \ - --env passwordEnabled="true" \ docker.io/labring/sealos-cloud-desktop:latest \ --config-file desktop-config.yaml ``` diff --git a/frontend/desktop/deploy/manifests/configmap.yaml b/frontend/desktop/deploy/manifests/configmap.yaml new file mode 100644 index 00000000000..ae98deaea2d --- /dev/null +++ b/frontend/desktop/deploy/manifests/configmap.yaml @@ -0,0 +1,55 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: desktop-frontend-config + namespace: sealos +data: + config.yaml : | + apiVersion: v1 + kind: ConfigMap + metadata: + name: desktop-frontend-config + namespace: sealos + data: + config.yaml : | + cloud: + domain: "{{ .cloudDomain }}" + port: "{{ .cloudPort }}" + regionUID: "" + certSecretName: "{{ .certSecretName }}" + common: + guideEnabled: "false" + apiEnabled: "false" + rechargeEnabled: "false" + cfSiteKey: "" + database: + mongodbURI: "" + globalCockroachdbURI: "" + regionalCockroachdbURI: "" + desktop: + layout: + title: "Sealos Cloud" + logo: "/logo.png" + backgroundImage: "/images/bg-blue.svg" + meta: + title: "Sealos Cloud" + description: "Sealos Cloud" + keywords: "Sealos Cloud" + scripts: [] + common: + githubStarEnabled: "true" + auth: + proxyAddress: "" + callbackURL: "https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}/callback" + signUpEnabled: "true" + baiduToken: "" + invite: + enabled: "false" + jwt: + internal: "" + regional: "" + global: "" + idp: + password: + enabled: "true" + salt: "" \ No newline at end of file diff --git a/frontend/desktop/deploy/manifests/deploy.yaml.tmpl b/frontend/desktop/deploy/manifests/deploy.yaml.tmpl index 30c17dd63fa..fa7d94bd913 100644 --- a/frontend/desktop/deploy/manifests/deploy.yaml.tmpl +++ b/frontend/desktop/deploy/manifests/deploy.yaml.tmpl @@ -29,26 +29,6 @@ spec: selector: app: desktop-frontend --- -apiVersion: v1 -kind: ConfigMap -metadata: - name: desktop-frontend-config - namespace: sealos -data: - config.yaml: |- - addr: :3000 - config.json: |- - { - "scripts": [], - "isSystemConfigEnabled": true, - "backgroundImageUrl": '/images/bg-blue.svg', - "imageFallBackUrl": 'logo.svg', - "title": 'Sealos', - "metaTitle": 'Sealos Cloud', - "metaDescription": 'sealos cloud dashboard', - "showGithubStar": true - } ---- apiVersion: apps/v1 kind: Deployment metadata: @@ -75,155 +55,16 @@ spec: command: ["/bin/sh", "-c"] args: - | + export REGIONAL_COCKROACHDB_URI=$(cat /app/data/config.yaml | awk '/regionalCockroachdbUri:/ {print $2}' | tr -d '"') + export GLOBAL_COCKROACHDB_URI=$(cat /app/data/config.yaml | awk '/globalCockroachdbUri:/ {print $2}' | tr -d '"') prisma migrate deploy --schema /app/desktop/prisma/global/schema.prisma prisma migrate deploy --schema /app/desktop/prisma/region/schema.prisma - env: - - name: GLOBAL_DATABASE_URL - valueFrom: - secretKeyRef: - key: global_database_url - name: desktop-frontend-secret - - name: REGION_DATABASE_URL - valueFrom: - secretKeyRef: - key: region_database_url - name: desktop-frontend-secret + volumeMounts: + - mountPath: /app/data/config.yaml + name: desktop-frontend-volume + subPath: config.yaml containers: - name: desktop-frontend - env: - # callback url is used for oauth2 login, required - - name: CALLBACK_URL - value: https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}/callback - # mongodb uri, required - - name: MONGODB_URI - valueFrom: - secretKeyRef: - name: desktop-frontend-secret - key: mongodb_uri - # jwt secret, required - - name: JWT_SECRET - valueFrom: - secretKeyRef: - name: desktop-frontend-secret - key: jwt_secret - - # set to true to enable password login, modify the PASSWORD_SALT env to change the salt - - name: PASSWORD_ENABLED - value: '{{ .passwordEnabled }}' - # set to true to enable github login - - name: GITHUB_ENABLED - value: '{{ .githubEnabled }}' - # set to true to enable wechat login - - name: WECHAT_ENABLED - value: '{{ .wechatEnabled }}' - # set to true to enable sms login - - name: SMS_ENABLED - value: '{{ .smsEnabled }}' - # set to true to enable sign up - - name: SIGN_UP_ENABLED - value: '{{ .signUpEnabled }}' - # set to true to open api - - name: API_ENABLED - value: '{{ .apiEnabled }}' - # password login env - - name: PASSWORD_SALT - valueFrom: - secretKeyRef: - name: desktop-frontend-secret - key: password_salt - # github login env - - name: GITHUB_CLIENT_ID - valueFrom: - secretKeyRef: - name: desktop-frontend-secret - key: github_client_id - optional: true - - name: GITHUB_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: desktop-frontend-secret - key: github_client_secret - optional: true - # wechat login env - - name: WECHAT_CLIENT_ID - valueFrom: - secretKeyRef: - name: desktop-frontend-secret - key: wechat_client_id - optional: true - - name: WECHAT_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: desktop-frontend-secret - key: wechat_client_secret - optional: true - # sms login env - - name: ALI_ENDPOINT - valueFrom: - secretKeyRef: - name: desktop-frontend-secret - key: ali_sms_endpoint - optional: true - - name: ALI_ACCESS_KEY_ID - valueFrom: - secretKeyRef: - name: desktop-frontend-secret - key: ali_access_key_id - optional: true - - name: ALI_ACCESS_KEY_SECRET - valueFrom: - secretKeyRef: - name: desktop-frontend-secret - key: ali_access_key_secret - optional: true - - name: ALI_SIGN_NAME - valueFrom: - secretKeyRef: - name: desktop-frontend-secret - key: ali_sms_sign_name - optional: true - - name: ALI_TEMPLATE_CODE - valueFrom: - secretKeyRef: - name: desktop-frontend-secret - key: ali_sms_template_code - optional: true - - name: SEALOS_CLOUD_DOMAIN - value: {{ .cloudDomain }} - - name: INVITE_ENABLED - value: "false" - - name: GUIDE_ENABLED - value: "false" - - name: GLOBAL_DATABASE_URL - valueFrom: - secretKeyRef: - key: global_database_url - name: desktop-frontend-secret - - name: REGION_DATABASE_URL - valueFrom: - secretKeyRef: - key: region_database_url - name: desktop-frontend-secret - - name: BILLING_URI - valueFrom: - secretKeyRef: - key: billing_uri - name: desktop-frontend-secret - - name: JWT_SECRET_REGION - valueFrom: - secretKeyRef: - key: jwt_secret_region - name: desktop-frontend-secret - - name: JWT_SECRET_APP - valueFrom: - secretKeyRef: - key: jwt_secret_app - name: desktop-frontend-secret - - name: REGION_UID - valueFrom: - secretKeyRef: - key: region_uid - name: desktop-frontend-secret securityContext: runAsNonRoot: true runAsUser: 1001 @@ -234,12 +75,9 @@ spec: image: ghcr.io/labring/sealos-desktop-frontend:latest imagePullPolicy: IfNotPresent volumeMounts: - - name: desktop-frontend-volume - mountPath: /config.yaml - subPath: config.yaml - - mountPath: /app/data/config.json + - mountPath: /app/data/config.yaml name: desktop-frontend-volume - subPath: config.json + subPath: config.yaml resources: limits: cpu: 2000m @@ -250,16 +88,16 @@ spec: affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - - weight: 100 - podAffinityTerm: - labelSelector: - matchExpressions: - - key: "app" - operator: In - values: - - desktop-frontend - topologyKey: "kubernetes.io/hostname" + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: "app" + operator: In + values: + - desktop-frontend + topologyKey: "kubernetes.io/hostname" volumes: - name: desktop-frontend-volume configMap: - name: desktop-frontend-config + name: desktop-frontend-config \ No newline at end of file diff --git a/frontend/desktop/deploy/manifests/secret.yaml b/frontend/desktop/deploy/manifests/secret.yaml deleted file mode 100644 index 3b6988c6142..00000000000 --- a/frontend/desktop/deploy/manifests/secret.yaml +++ /dev/null @@ -1,51 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: desktop-frontend-secret - namespace: sealos -type: Opaque -data: - # base64 encode account service url, required - # default value is "http://account-service.account-system.svc:2333" - billing_uri: "aHR0cDovL2FjY291bnQtc2VydmljZS5hY2NvdW50LXN5c3RlbS5zdmM6MjMzMw==" - - - # base64 encoded mongodb uri, required - mongodb_uri: "" - # base64 encoded cockroachdb uri for global, required - global_database_url: "" - # base64 encoded cockroachdb uri for current region, required - region_database_url: "" - # base64 encoded jwt secret, required - jwt_secret: "" - # base64 encoded global jwt secret, required - jwt_secret_region: "" - # base64 encoded provider jwt secret, required - jwt_secret_app: "" - - # base64 encoded password salt, required if env PASSWORD_ENABLED is true - # please use a random string and do not change it after deployment - password_salt: "" - - # base64 encoded GitHub client id, required if env GITHUB_ENABLED is true - github_client_id: "" - # base64 encoded GitHub client secret, required if env GITHUB_ENABLED is true - github_client_secret: "" - - # base64 encoded WeChat client id, required if env WECHAT_ENABLED is true - wechat_client_id: "" - # base64 encoded WeChat client secret, required if env WECHAT_ENABLED is true - wechat_client_secret: "" - - # base64 encoded ali sms endpoint, required if env SMS_ENABLED is true - ali_sms_endpoint: "" - # base64 encoded ali access key id, required if env SMS_ENABLED is true - ali_access_key_id: "" - # base64 encoded ali access key secret, required if env SMS_ENABLED is true - ali_access_key_secret: "" - # base64 encoded ali sms sign name, required if env SMS_ENABLED is true - ali_sms_sign_name: "" - # base64 encoded ali sms template code, required if env SMS_ENABLED is true - ali_sms_template_code: "" - - diff --git a/frontend/desktop/deploy/scripts/init.sh b/frontend/desktop/deploy/scripts/init.sh index 5cb30604031..34834827549 100644 --- a/frontend/desktop/deploy/scripts/init.sh +++ b/frontend/desktop/deploy/scripts/init.sh @@ -1,13 +1,10 @@ #!/bin/bash - set -ex - kubectl apply -f manifests/deploy.yaml -f manifests/rbac.yaml -f manifests/ingress.yaml - -secret_exists=$(kubectl get secret desktop-frontend-secret -n sealos --ignore-not-found=true) -if [[ -n "$secret_exists" ]]; then - echo "desktop-frontend-secret already exists, skip create desktop secret" +cm_exists=$(kubectl get cm desktop-frontend-config -n sealos --ignore-not-found=true) +if [[ -n "cm_exists" ]]; then + echo "desktop-frontend-config already exists, skip create desktop config" else - echo "create desktop secret" - kubectl apply -f manifests/secret.yaml --validate=false + echo "create desktop config" + kubectl apply -f manifests/config.yaml --validate=false fi diff --git a/frontend/desktop/src/api/platform.ts b/frontend/desktop/src/api/platform.ts index bdb6da57c50..35dac9e942b 100644 --- a/frontend/desktop/src/api/platform.ts +++ b/frontend/desktop/src/api/platform.ts @@ -1,5 +1,14 @@ import request from '@/services/request'; -import { ApiResp, NotificationItem, Session, SystemConfigType, SystemEnv } from '@/types'; +import { + ApiResp, + NotificationItem, + LayoutConfigType, + CloudConfigType, + AuthClientConfigType, + AppClientConfigType, + CommonConfigType, + CommonClientConfigType +} from '@/types'; import { AccountCRD } from '@/types/user'; // handle baidu @@ -25,12 +34,24 @@ export const getUserAccount = () => { return request.get('/api/account/getAccount'); }; -export const getSystemEnv = () => { - return request.get('/api/platform/getEnv'); +export const getAppConfig = () => { + return request.get('/api/platform/getAppConfig'); }; -export const getSystemConfig = () => { - return request.get('/api/platform/getSystemConfig'); +export const getCloudConfig = () => { + return request.get('/api/platform/getCloudConfig'); +}; + +export const getCommonConfig = () => { + return request.get('/api/platform/getCommonConfig'); +}; + +export const getLayoutConfig = () => { + return request.get('/api/platform/getLayoutConfig'); +}; + +export const getAuthConfig = () => { + return request.get('/api/platform/getAuthConfig'); }; export const getPriceBonus = () => { diff --git a/frontend/desktop/src/components/account/index.tsx b/frontend/desktop/src/components/account/index.tsx index 006b5bc946d..1a4b99c3c88 100644 --- a/frontend/desktop/src/components/account/index.tsx +++ b/frontend/desktop/src/components/account/index.tsx @@ -18,16 +18,17 @@ import { useTranslation } from 'next-i18next'; import { useRouter } from 'next/router'; import { useMemo, useState } from 'react'; import useAppStore from '@/stores/app'; -import { ApiResp, Region } from '@/types'; +import { ApiResp } from '@/types'; import { formatMoney } from '@/utils/format'; import PasswordModify from './PasswordModify'; -import { useGlobalStore } from '@/stores/global'; -import { CopyIcon, DownloadIcon, LogoutIcon, RightArrowIcon } from '@sealos/ui'; -import { ImageFallBackUrl } from '@/stores/config'; +import { CopyIcon, DownloadIcon, LogoutIcon } from '@sealos/ui'; +import { useConfigStore } from '@/stores/config'; export default function Account({ disclosure }: { disclosure: UseDisclosureReturn }) { const [showId, setShowId] = useState(true); - const { needPassword, rechargeEnabled } = useGlobalStore((state) => state.systemEnv); + const passwordEnabled = useConfigStore().authConfig?.idp?.password?.enabled; + const rechargeEnabled = useConfigStore().commonConfig?.rechargeEnabled; + const logo = useConfigStore().layoutConfig?.logo; const router = useRouter(); const { copyData } = useCopyData(); const openApp = useAppStore((s) => s.openApp); @@ -94,7 +95,7 @@ export default function Account({ disclosure }: { disclosure: UseDisclosureRetur height={'80px'} borderRadius="full" src={user?.avatar} - fallbackSrc={ImageFallBackUrl} + fallbackSrc={logo} alt="user avator" /> @@ -128,7 +129,7 @@ export default function Account({ disclosure }: { disclosure: UseDisclosureRetur fontSize={'13px'} gap={'0px'} > - {needPassword && ( + {passwordEnabled && ( {wnapp?.name} {wnapp?.name} {wnapp?.name} {wnapp?.name} import('./time'), { ssr: false }); @@ -22,6 +22,8 @@ const TimeComponent = dynamic(() => import('./time'), { export default function DesktopContent(props: any) { const { t, i18n } = useTranslation(); const { installedApps: apps, runningInfo, openApp, setToHighestLayerById } = useAppStore(); + const backgroundImage = useConfigStore().layoutConfig?.backgroundImage; + const logo = useConfigStore().layoutConfig?.logo; const renderApps = apps.filter((item: TApp) => item?.displayType === 'normal'); const [maxItems, setMaxItems] = useState(10); const { message } = useMessage(); @@ -109,7 +111,7 @@ export default function DesktopContent(props: any) { @@ -166,7 +168,7 @@ export default function DesktopContent(props: any) { width="100%" height="100%" src={item?.icon} - fallbackSrc={ImageFallBackUrl} + fallbackSrc={logo || '/logo.svg'} draggable={false} alt="user avator" /> diff --git a/frontend/desktop/src/components/floating_button/index.tsx b/frontend/desktop/src/components/floating_button/index.tsx index 593717907ea..f8f31349038 100644 --- a/frontend/desktop/src/components/floating_button/index.tsx +++ b/frontend/desktop/src/components/floating_button/index.tsx @@ -7,7 +7,7 @@ import Iconfont from '../iconfont'; import styles from './index.module.scss'; import homeIcon from 'public/icons/home.svg'; import { APPTYPE } from '@/types'; -import { ImageFallBackUrl } from '@/stores/config'; +import { useConfigStore } from '@/stores/config'; enum Suction { None, @@ -54,6 +54,8 @@ export default function Index(props: any) { ...runningInfo ]; + const logo = useConfigStore().layoutConfig?.logo; + const [degree, contentSkewDegree, contentRotateDegree] = useMemo(() => { const len = apps?.length < 6 ? 6 : apps?.length > 8 ? 8 : apps?.length; const temp: number = 360 / len; @@ -245,7 +247,7 @@ export default function Index(props: any) { > {item?.name}, item: TApp) => { e.preventDefault(); @@ -104,7 +105,7 @@ export default function Index() { width="100%" height="100%" src={item?.icon} - fallbackSrc={ImageFallBackUrl} + fallbackSrc={logo || '/logo.svg'} draggable={false} alt="user avator" /> diff --git a/frontend/desktop/src/components/signin/auth/AuthList.tsx b/frontend/desktop/src/components/signin/auth/AuthList.tsx index d38da4df1a8..49b721dfabc 100644 --- a/frontend/desktop/src/components/signin/auth/AuthList.tsx +++ b/frontend/desktop/src/components/signin/auth/AuthList.tsx @@ -1,133 +1,137 @@ -import { useGlobalStore } from '@/stores/global'; +import { useConfigStore } from '@/stores/config'; import useSessionStore from '@/stores/session'; import { OauthProvider } from '@/types/user'; import { Button, Image, Flex, Icon, Center } from '@chakra-ui/react'; import { GithubIcon, GoogleIcon, WechatIcon } from '@sealos/ui'; import { useRouter } from 'next/router'; -import { MouseEventHandler } from 'react'; +import { MouseEventHandler, useMemo } from 'react'; const AuthList = () => { - const { systemEnv } = useGlobalStore(); - const { - needGithub = false, - needWechat = false, - needGoogle = false, - wechat_client_id = '', - github_client_id = '', - google_client_id = '', - callback_url = '', - // https://sealos.io/siginIn - oauth_proxy = '', - oauth2_client_id, - oauth2_auth_url, - needOAuth2 = false - } = systemEnv ?? {}; - const oauthLogin = async ({ url, provider }: { url: string; provider?: OauthProvider }) => { - setProvider(provider); - window.location.href = url; - }; + const conf = useConfigStore().authConfig; + const router = useRouter(); - const oauthProxyLogin = async ({ - state, - provider, - id - }: { - state: string; - provider: OauthProvider; - id: string; - }) => { - setProvider(provider); - const target = new URL(oauth_proxy); - const callback = new URL(callback_url); - callback.searchParams.append('state', state); - target.searchParams.append('oauthProxyState', callback.toString()); - target.searchParams.append('oauthProxyClientID', id); - target.searchParams.append('oauthProxyProvider', provider); - router.replace(target.toString()); - }; + + const logo = useConfigStore().layoutConfig?.logo; + const { generateState, setProvider } = useSessionStore(); - const authList: { icon: typeof Icon; cb: MouseEventHandler; need: boolean }[] = [ - { - icon: GithubIcon, - cb: (e) => { - e.preventDefault(); - const state = generateState(); - if (oauth_proxy) - oauthProxyLogin({ - provider: 'github', - state, - id: github_client_id - }); - else - oauthLogin({ - provider: 'github', - url: `https://github.com/login/oauth/authorize?client_id=${github_client_id}&redirect_uri=${callback_url}&scope=user:email%20read:user&state=${state}` - }); - }, - need: needGithub - }, - { - icon: WechatIcon, - cb: (e) => { - e.preventDefault(); - const state = generateState(); - if (oauth_proxy) - oauthProxyLogin({ - provider: 'wechat', - state, - id: wechat_client_id - }); - else - oauthLogin({ - provider: 'wechat', - url: `https://open.weixin.qq.com/connect/qrconnect?appid=${wechat_client_id}&redirect_uri=${callback_url}&response_type=code&state=${state}&scope=snsapi_login&#wechat_redirect` - }); + const authList: { icon: typeof Icon; cb: MouseEventHandler; need: boolean }[] = useMemo(() => { + if (!conf) return []; + const oauthLogin = async ({ url, provider }: { url: string; provider?: OauthProvider }) => { + setProvider(provider); + window.location.href = url; + }; + const oauthProxyLogin = async ({ + state, + provider, + id + }: { + state: string; + provider: OauthProvider; + id: string; + }) => { + // if(!conf) return + setProvider(provider); + const target = new URL(conf.proxyAddress); + const callback = new URL(conf.callbackURL); + callback.searchParams.append('state', state); + target.searchParams.append('oauthProxyState', callback.toString()); + target.searchParams.append('oauthProxyClientID', id); + target.searchParams.append('oauthProxyProvider', provider); + router.replace(target.toString()); + }; + return [ + { + icon: GithubIcon, + cb: (e) => { + e.preventDefault(); + const state = generateState(); + const githubConf = conf?.idp.github; + if (conf?.proxyAddress) + oauthProxyLogin({ + provider: 'github', + state, + id: githubConf?.clientID as string + }); + else + oauthLogin({ + provider: 'github', + url: `https://github.com/login/oauth/authorize?client_id=${githubConf?.clientID}&redirect_uri=${conf?.callbackURL}&scope=user:email%20read:user&state=${state}` + }); + }, + need: conf.idp.github.enabled }, - need: needWechat - }, - { - icon: GoogleIcon, - cb: (e) => { - e.preventDefault(); - const state = generateState(); - const scope = encodeURIComponent(`https://www.googleapis.com/auth/userinfo.profile openid`); - if (oauth_proxy) - oauthProxyLogin({ - state, - provider: 'google', - id: google_client_id - }); - else - oauthLogin({ - provider: 'google', - url: `https://accounts.google.com/o/oauth2/v2/auth?client_id=${google_client_id}&redirect_uri=${callback_url}&response_type=code&state=${state}&scope=${scope}&include_granted_scopes=true` - }); + { + icon: WechatIcon, + cb: (e) => { + const wechatConf = conf?.idp.wechat; + e.preventDefault(); + const state = generateState(); + if (conf.proxyAddress) + oauthProxyLogin({ + provider: 'wechat', + state, + id: conf.idp.wechat?.clientID + }); + else + oauthLogin({ + provider: 'wechat', + url: `https://open.weixin.qq.com/connect/qrconnect?appid=${wechatConf?.clientID}&redirect_uri=${conf?.callbackURL}&response_type=code&state=${state}&scope=snsapi_login&#wechat_redirect` + }); + }, + need: conf?.idp.wechat?.enabled as boolean }, - need: needGoogle - }, - { - icon: () => ( -
- logo -
- ), - cb: (e) => { - e.preventDefault(); - const state = generateState(); - if (oauth_proxy) - oauthProxyLogin({ - provider: 'oauth2', - state, - id: oauth2_client_id - }); - else - oauthLogin({ - provider: 'oauth2', - url: `${oauth2_auth_url}?client_id=${oauth2_client_id}&redirect_uri=${callback_url}&response_type=code&state=${state}` - }); + { + icon: GoogleIcon, + cb: (e) => { + e.preventDefault(); + const state = generateState(); + const googleConf = conf?.idp.google; + const scope = encodeURIComponent( + `https://www.googleapis.com/auth/userinfo.profile openid` + ); + if (conf.proxyAddress) + oauthProxyLogin({ + state, + provider: 'google', + id: googleConf?.clientID as string + }); + else + oauthLogin({ + provider: 'google', + url: `https://accounts.google.com/o/oauth2/v2/auth?client_id=${ + googleConf?.clientID as string + }&redirect_uri=${ + conf?.callbackURL + }&response_type=code&state=${state}&scope=${scope}&include_granted_scopes=true` + }); + }, + need: conf.idp.google.enabled as boolean }, - need: needOAuth2 - } - ]; + { + icon: () => ( +
+ logo +
+ ), + cb: (e) => { + e.preventDefault(); + const state = generateState(); + const oauth2Conf = conf?.idp.oauth2; + if (conf.proxyAddress) + oauthProxyLogin({ + provider: 'oauth2', + state, + id: oauth2Conf.clientID as string + }); + else + oauthLogin({ + provider: 'oauth2', + url: `${oauth2Conf?.authURL}?client_id=${oauth2Conf.clientID}&redirect_uri=${oauth2Conf.callbackURL}&response_type=code&state=${state}` + }); + }, + need: conf.idp.oauth2?.enabled as boolean + } + ]; + }, [conf, generateState, logo, router, setProvider]); return ( diff --git a/frontend/desktop/src/components/signin/index.tsx b/frontend/desktop/src/components/signin/index.tsx index 974bda63416..8c673c8d118 100644 --- a/frontend/desktop/src/components/signin/index.tsx +++ b/frontend/desktop/src/components/signin/index.tsx @@ -5,8 +5,7 @@ import Language from '@/components/signin/auth/useLanguage'; import usePassword from '@/components/signin/auth/usePassword'; import useProtocol from '@/components/signin/auth/useProtocol'; import useSms from '@/components/signin/auth/useSms'; -import { BackgroundImageUrl, useSystemConfigStore } from '@/stores/config'; -import { useGlobalStore } from '@/stores/global'; +import { useConfigStore } from '@/stores/config'; import useSessionStore from '@/stores/session'; import { LoginType } from '@/types'; import { @@ -30,20 +29,10 @@ import useWechat from './auth/useWechat'; import { Turnstile, TurnstileInstance } from '@marsidev/react-turnstile'; export default function SigninComponent() { - const platformEnv = useGlobalStore((state) => state.systemEnv); - - const { systemConfig } = useSystemConfigStore(); - const { - service_protocol_zh = '', - private_protocol_zh = '', - service_protocol_en = '', - private_protocol_en = '', - needPassword = false, - needSms = false, - openWechatEnabled = false, - cf_sitekey - } = platformEnv || {}; - const needTabs = needPassword && needSms; + const conf = useConfigStore(); + const needPassword = conf.authConfig?.idp.password?.enabled; + const needSms = conf.authConfig?.idp.sms?.enabled; + const needTabs = conf.authConfig?.idp.password?.enabled && conf.authConfig?.idp.sms?.enabled; const disclosure = useDisclosure(); const { t, i18n } = useTranslation(); const [tabIndex, setTabIndex] = useState(LoginType.NONE); @@ -52,13 +41,13 @@ export default function SigninComponent() { let protocol_data: Parameters[0]; if (['zh', 'zh-Hans'].includes(i18n.language)) protocol_data = { - service_protocol: service_protocol_zh, - private_protocol: private_protocol_zh + service_protocol: conf.layoutConfig?.protocol?.serviceProtocol.zh as string, + private_protocol: conf.layoutConfig?.protocol?.privateProtocol.zh as string }; else protocol_data = { - service_protocol: service_protocol_en, - private_protocol: private_protocol_en + service_protocol: conf.layoutConfig?.protocol?.serviceProtocol.en as string, + private_protocol: conf.layoutConfig?.protocol?.privateProtocol.en as string }; const { Protocol, isAgree, setIsInvalid } = useProtocol(protocol_data!); const { WechatComponent, login: wechatSubmit } = useWechat(); @@ -146,20 +135,19 @@ export default function SigninComponent() { showError(t('Read and agree')); } }, 500); - return ( - {systemConfig?.metaTitle} - + {conf.layoutConfig?.meta.title || ''} + @@ -169,7 +157,7 @@ export default function SigninComponent() { fontWeight={700} textShadow={'0px 2px 6px rgba(0, 0, 0, 0.30)'} > - {systemConfig?.title} + {conf.layoutConfig?.title}
{t('Password Login')} - {openWechatEnabled && ( + {conf.authConfig?.idp.wechat.enabled && ( {t('Official account login')} @@ -227,13 +215,13 @@ export default function SigninComponent() { {tabIndex !== LoginType.WeChat && ( <> - {!!cf_sitekey && ( + {!!conf.commonConfig?.cfSiteKey && ( )}