diff --git a/authserver/.gitignore b/authserver/.gitignore index 6097006..eca0741 100644 --- a/authserver/.gitignore +++ b/authserver/.gitignore @@ -5,7 +5,7 @@ .DS_Store *.tar bin/ -/server +server web/node_modules/ web/dist/ certs/ diff --git a/authserver/cmd/server/main.go b/authserver/cmd/server/main.go deleted file mode 100644 index 7ad3580..0000000 --- a/authserver/cmd/server/main.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "log" - - "authserver/internal/config" - "authserver/internal/database" - "authserver/internal/router" -) - -func main() { - cfg := config.Load() - - db, err := database.Open(cfg.MySQLDSN) - if err != nil { - log.Fatalf("open database: %v", err) - } - - if cfg.AutoMigrate { - if err := database.AutoMigrate(db); err != nil { - log.Fatalf("auto migrate: %v", err) - } - } - if err := database.SeedDefaults(db, cfg); err != nil { - log.Fatalf("seed defaults: %v", err) - } - - r := router.New(router.Dependencies{ - Config: cfg, - DB: db, - }) - - log.Printf("authserver listening on %s", cfg.HTTPAddr) - if err := r.Run(cfg.HTTPAddr); err != nil { - log.Fatalf("run server: %v", err) - } -} diff --git a/authserver/internal/handler/saml.go b/authserver/internal/handler/saml.go index 0ca7f23..a90818d 100644 --- a/authserver/internal/handler/saml.go +++ b/authserver/internal/handler/saml.go @@ -97,15 +97,15 @@ func (h *SAMLHandler) ACS(c *gin.Context) { func ssoRedirectURL(relayState, token string) string { target := strings.TrimSpace(relayState) - if target == "" || !strings.HasPrefix(target, "/") { - target = "/" + if target == "" || !strings.HasPrefix(target, "/auth/") { + target = "/auth/" } if strings.HasPrefix(target, "//") { - target = "/" + target = "/auth/" } parsed, err := url.Parse(target) if err != nil || parsed.IsAbs() { - parsed = &url.URL{Path: "/"} + parsed = &url.URL{Path: "/auth/"} } values := parsed.Query() values.Set("sso_token", token) diff --git a/authserver/k8s/nginx.yaml b/authserver/k8s/nginx.yaml deleted file mode 100644 index fae0081..0000000 --- a/authserver/k8s/nginx.yaml +++ /dev/null @@ -1,148 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: authserver-nginx-conf - namespace: authserver -data: - default.conf.template: | - server { - listen 80; - server_name _; - - client_max_body_size 10m; - - location = /healthz { - proxy_pass ${AUTHSERVER_BACKEND_UPSTREAM}; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - location = /readyz { - proxy_pass ${AUTHSERVER_BACKEND_UPSTREAM}; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - location /auth/api/ { - proxy_pass ${AUTHSERVER_BACKEND_UPSTREAM}; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 5s; - proxy_send_timeout 60s; - proxy_read_timeout 60s; - } - - location /auth/oauth/ { - proxy_pass ${AUTHSERVER_BACKEND_UPSTREAM}; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 5s; - proxy_send_timeout 60s; - proxy_read_timeout 60s; - } - - location /auth/.well-known/ { - proxy_pass ${AUTHSERVER_BACKEND_UPSTREAM}; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 5s; - proxy_send_timeout 60s; - proxy_read_timeout 60s; - } - - location /internal/clouddm/ { - proxy_pass ${CLOUDDM_UPSTREAM}/; - proxy_http_version 1.1; - proxy_set_header Host ${CLOUDDM_PUBLIC_HOST}; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Host ${CLOUDDM_PUBLIC_HOST}; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto http; - proxy_connect_timeout 5s; - proxy_send_timeout 60s; - proxy_read_timeout 60s; - } - - location / { - return 404; - } - } ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: authserver-nginx - namespace: authserver -spec: - replicas: 1 - selector: - matchLabels: - app: authserver-nginx - template: - metadata: - labels: - app: authserver-nginx - spec: - containers: - - name: nginx - image: nginx:1.29-alpine - imagePullPolicy: IfNotPresent - ports: - - containerPort: 80 - env: - - name: AUTHSERVER_BACKEND_UPSTREAM - value: http://authserver-backend:8083 - - name: CLOUDDM_UPSTREAM - value: http://open-cdm.db.svc.cluster.local:8222 - - name: CLOUDDM_PUBLIC_HOST - value: 218.11.5.223:30009 - volumeMounts: - - name: nginx-conf - mountPath: /etc/nginx/templates/default.conf.template - subPath: default.conf.template - readinessProbe: - httpGet: - path: /readyz - port: 80 - initialDelaySeconds: 5 - periodSeconds: 10 - livenessProbe: - httpGet: - path: /healthz - port: 80 - initialDelaySeconds: 10 - periodSeconds: 20 - volumes: - - name: nginx-conf - configMap: - name: authserver-nginx-conf ---- -apiVersion: v1 -kind: Service -metadata: - name: authserver-nginx - namespace: authserver -spec: - type: NodePort - selector: - app: authserver-nginx - ports: - - name: http - port: 80 - targetPort: 80 - nodePort: 30080 diff --git a/authserver/web/.dockerignore b/authserver/web/.dockerignore new file mode 100644 index 0000000..a7e5733 --- /dev/null +++ b/authserver/web/.dockerignore @@ -0,0 +1,4 @@ +node_modules/ +dist/ +.DS_Store + diff --git a/authserver/web/Dockerfile b/authserver/web/Dockerfile new file mode 100644 index 0000000..debcaaf --- /dev/null +++ b/authserver/web/Dockerfile @@ -0,0 +1,16 @@ +FROM node:14-alpine AS builder + +WORKDIR /app + +COPY package*.json ./ +RUN npm install --no-audit --no-fund + +COPY . . +RUN npm run build + +FROM nginx:1.29-alpine + +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=builder /app/dist /usr/share/nginx/html/auth + +EXPOSE 80 diff --git a/authserver/web/index.html b/authserver/web/index.html new file mode 100644 index 0000000..f469a73 --- /dev/null +++ b/authserver/web/index.html @@ -0,0 +1,12 @@ + + + + + + AuthServer + + +
+ + + diff --git a/authserver/web/nginx.conf b/authserver/web/nginx.conf new file mode 100644 index 0000000..caaae48 --- /dev/null +++ b/authserver/web/nginx.conf @@ -0,0 +1,90 @@ +server { + listen 80; + server_name _; + + client_max_body_size 10m; + + root /usr/share/nginx/html; + index index.html; + + location = / { + return 302 /auth/; + } + + location = /healthz { + proxy_pass http://authserver-backend:8083; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location = /readyz { + proxy_pass http://authserver-backend:8083; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /auth/api/ { + proxy_pass http://authserver-backend:8083; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_connect_timeout 5s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } + + location /auth/oauth/ { + proxy_pass http://authserver-backend:8083; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_connect_timeout 5s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } + + location /auth/.well-known/ { + proxy_pass http://authserver-backend:8083; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_connect_timeout 5s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } + + location /internal/clouddm/ { + proxy_pass http://open-cdm.db.svc.cluster.local:8222/; + proxy_http_version 1.1; + proxy_set_header Host 218.11.5.223:30009; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Host 218.11.5.223:30009; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto http; + proxy_connect_timeout 5s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + } + + location /auth/ { + try_files $uri $uri/ /auth/index.html; + } + + location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|woff2?)$ { + expires 7d; + add_header Cache-Control "public, max-age=604800"; + try_files $uri =404; + } +} diff --git a/authserver/web/package-lock.json b/authserver/web/package-lock.json new file mode 100644 index 0000000..6c2df8d --- /dev/null +++ b/authserver/web/package-lock.json @@ -0,0 +1,379 @@ +{ + "name": "authserver-web", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==" + }, + "@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==" + }, + "@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "requires": { + "@babel/types": "^7.29.7" + } + }, + "@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "requires": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + } + }, + "@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "optional": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" + }, + "@vitejs/plugin-vue": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.6.2.tgz", + "integrity": "sha512-kqf7SGFoG+80aZG6Pf+gsZIVvGSCKE98JbiWqcCV9cThtg91Jav0yvYFC9Zb+jKetNGF6ZKeoaxgZfND21fWKw==" + }, + "@vue/compiler-core": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.17.tgz", + "integrity": "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==", + "requires": { + "@babel/parser": "^7.27.5", + "@vue/shared": "3.5.17", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "@vue/compiler-dom": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz", + "integrity": "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==", + "requires": { + "@vue/compiler-core": "3.5.17", + "@vue/shared": "3.5.17" + } + }, + "@vue/compiler-sfc": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz", + "integrity": "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==", + "requires": { + "@babel/parser": "^7.27.5", + "@vue/compiler-core": "3.5.17", + "@vue/compiler-dom": "3.5.17", + "@vue/compiler-ssr": "3.5.17", + "@vue/shared": "3.5.17", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.17", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "@vue/compiler-ssr": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz", + "integrity": "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==", + "requires": { + "@vue/compiler-dom": "3.5.17", + "@vue/shared": "3.5.17" + } + }, + "@vue/reactivity": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.17.tgz", + "integrity": "sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw==", + "requires": { + "@vue/shared": "3.5.17" + } + }, + "@vue/runtime-core": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.17.tgz", + "integrity": "sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q==", + "requires": { + "@vue/reactivity": "3.5.17", + "@vue/shared": "3.5.17" + } + }, + "@vue/runtime-dom": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.17.tgz", + "integrity": "sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g==", + "requires": { + "@vue/reactivity": "3.5.17", + "@vue/runtime-core": "3.5.17", + "@vue/shared": "3.5.17", + "csstype": "^3.1.3" + } + }, + "@vue/server-renderer": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.17.tgz", + "integrity": "sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA==", + "requires": { + "@vue/compiler-ssr": "3.5.17", + "@vue/shared": "3.5.17" + } + }, + "@vue/shared": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.17.tgz", + "integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==" + }, + "csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==" + }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + }, + "esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "requires": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "optional": true + }, + "magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "requires": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "nanoid": { + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==" + }, + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "postcss": { + "version": "8.5.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.18.tgz", + "integrity": "sha512-xdB1oSLHbz1vRWgCDalrCqEFTWzFlhqFC5tIHLMOSUIjhm3XXQ1qrFy8S/ESr1JYRRXqM3c1QFiMZUJdUTqyMQ==", + "requires": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + } + }, + "rollup": { + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.30.0.tgz", + "integrity": "sha512-kQvGasUgN+AlWGliFn2POSajRQEsULVYFGTvOZmK06d7vCD+YhZztt70kGk3qaeAXeWYL5eO7zx+rAubBc55eA==", + "requires": { + "fsevents": "~2.3.2" + } + }, + "source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" + }, + "vite": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.3.tgz", + "integrity": "sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==", + "requires": { + "esbuild": "^0.18.10", + "fsevents": "~2.3.2", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + } + }, + "vue": { + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.17.tgz", + "integrity": "sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g==", + "requires": { + "@vue/compiler-dom": "3.5.17", + "@vue/compiler-sfc": "3.5.17", + "@vue/runtime-dom": "3.5.17", + "@vue/server-renderer": "3.5.17", + "@vue/shared": "3.5.17" + } + } + } +} diff --git a/authserver/web/package.json b/authserver/web/package.json new file mode 100644 index 0000000..3f7d557 --- /dev/null +++ b/authserver/web/package.json @@ -0,0 +1,20 @@ +{ + "name": "authserver-web", + "version": "0.1.0", + "private": true, + "type": "module", + "engines": { + "node": ">=14.18.0" + }, + "scripts": { + "dev": "vite --host 0.0.0.0", + "build": "vite build", + "preview": "vite preview --host 0.0.0.0" + }, + "dependencies": { + "@vitejs/plugin-vue": "4.6.2", + "vite": "4.5.3", + "vue": "3.5.17" + }, + "devDependencies": {} +} diff --git a/authserver/web/src/App.vue b/authserver/web/src/App.vue new file mode 100644 index 0000000..be8f366 --- /dev/null +++ b/authserver/web/src/App.vue @@ -0,0 +1,219 @@ + + + diff --git a/authserver/web/src/main.js b/authserver/web/src/main.js new file mode 100644 index 0000000..2425c0f --- /dev/null +++ b/authserver/web/src/main.js @@ -0,0 +1,5 @@ +import { createApp } from 'vue' +import './style.css' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/authserver/web/src/style.css b/authserver/web/src/style.css new file mode 100644 index 0000000..9283195 --- /dev/null +++ b/authserver/web/src/style.css @@ -0,0 +1,206 @@ +* { + box-sizing: border-box; +} + +body { + margin: 0; + min-width: 320px; + min-height: 100vh; + color: #172033; + background: #f5f7fb; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", + sans-serif; +} + +button, +input { + font: inherit; +} + +button { + min-height: 36px; + border: 1px solid #cfd7e6; + border-radius: 6px; + background: #ffffff; + color: #172033; + cursor: pointer; +} + +button:disabled { + cursor: not-allowed; + opacity: 0.55; +} + +input { + width: 100%; + min-height: 36px; + border: 1px solid #cfd7e6; + border-radius: 6px; + padding: 0 10px; + background: #ffffff; + color: #172033; +} + +h1, +p { + margin: 0; +} + +h1 { + font-size: 22px; + line-height: 1.2; +} + +.login-page { + min-height: 100vh; + display: grid; + place-items: center; + padding: 24px; +} + +.login-panel { + width: min(420px, 100%); + display: grid; + gap: 22px; + border: 1px solid #dbe3ef; + border-radius: 8px; + padding: 28px; + background: #ffffff; + box-shadow: 0 18px 50px rgb(43 57 84 / 10%); +} + +.primary { + border-color: #1b64d8; + background: #1b64d8; + color: #ffffff; + font-weight: 650; +} + +.secondary { + padding: 0 14px; + border-color: #b8c5d9; + background: #ffffff; +} + +.eyebrow { + margin-bottom: 6px; + color: #526174; + font-size: 12px; + font-weight: 700; + letter-spacing: 0; + text-transform: uppercase; +} + +.message { + margin-top: 4px; + color: #31516f; + font-size: 13px; +} + +.app-page { + min-height: 100vh; + display: grid; + grid-template-rows: auto 1fr; + background: + linear-gradient(135deg, rgb(22 82 170 / 8%), transparent 42%), + #f5f7fb; +} + +.app-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 22px 28px; + border-bottom: 1px solid #dbe3ef; + background: rgb(255 255 255 / 86%); + backdrop-filter: blur(10px); +} + +.app-main { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 360px)); + justify-content: center; + align-items: center; + gap: 18px; + padding: 32px 20px; +} + +.app-button { + width: min(280px, 78vw); + aspect-ratio: 1; + display: grid; + place-items: center; + align-content: center; + gap: 18px; + border-color: #cfdaf0; + border-radius: 8px; + background: #ffffff; + box-shadow: 0 18px 50px rgb(43 57 84 / 12%); +} + +.app-button:hover:not(:disabled), +.app-button:focus-visible { + border-color: #1b64d8; + box-shadow: 0 22px 60px rgb(27 100 216 / 18%); + outline: none; +} + +.app-icon { + width: 112px; + height: 112px; + display: grid; + place-items: center; + border-radius: 28px; + color: #ffffff; + font-size: 64px; + font-weight: 800; + line-height: 1; +} + +.wayen-icon { + background: #1b64d8; +} + +.clouddm-icon { + background: #0f7b6c; +} + +.app-title { + color: #172033; + font-size: 22px; + font-weight: 750; +} + +.user-block { + display: flex; + align-items: center; + gap: 12px; + color: #526174; + font-size: 14px; +} + +@media (max-width: 560px) { + .app-header { + align-items: flex-start; + flex-direction: column; + padding: 18px 20px; + } + + .user-block { + width: 100%; + justify-content: space-between; + } + + .app-icon { + width: 92px; + height: 92px; + border-radius: 22px; + font-size: 52px; + } + + .app-main { + grid-template-columns: 1fr; + } +} diff --git a/authserver/web/vite.config.js b/authserver/web/vite.config.js new file mode 100644 index 0000000..6cb45ed --- /dev/null +++ b/authserver/web/vite.config.js @@ -0,0 +1,15 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +export default defineConfig({ + base: '/auth/', + plugins: [vue()], + server: { + port: 5173, + proxy: { + '/auth/api': 'http://127.0.0.1:8083', + '/healthz': 'http://127.0.0.1:8083', + '/readyz': 'http://127.0.0.1:8083', + }, + }, +})