Remove LY SSO sign-in flow
All checks were successful
aurask-release / build-and-deploy (push) Successful in 1m52s

This commit is contained in:
Aaron 2026-04-19 21:23:27 +08:00
parent c44746a5a8
commit 4e2639ea43
13 changed files with 13 additions and 162 deletions

View File

@ -10,7 +10,7 @@ Aurask 当前处于 **可运行 MVP / 初版门户** 阶段,已覆盖:
- Python 模块化后端 - Python 模块化后端
- 标准库 HTTP Gateway - 标准库 HTTP Gateway
- 租户、用户、API Key、Session - 租户、用户、API Key、Session
- `LY SSO` / Google 登录入口 - Google 登录入口
- 首次登录自动创建独立 workspace - 首次登录自动创建独立 workspace
- 配额 / TBU / 订单 / 支付闭环 - 配额 / TBU / 订单 / 支付闭环
- 工作流模板编排 - 工作流模板编排
@ -92,7 +92,6 @@ Browser
未登录: 未登录:
- 渲染 `/signin` - 渲染 `/signin`
- 提供 `Use LY SSO`
- 提供 `Continue with Google` - 提供 `Continue with Google`
已登录: 已登录:
@ -107,11 +106,7 @@ Browser
当前支持: 当前支持:
1. `LY SSO` 1. Google
- 以按钮形式进入
- 当前实现为配置驱动的本地接入层
- 通过 `AURASK_LY_SSO_USERNAME` / `AURASK_LY_SSO_PASSWORD` 控制
2. Google
- 通过 `AURASK_GOOGLE_CLIENT_ID` 开启 - 通过 `AURASK_GOOGLE_CLIENT_ID` 开启
- 首次注册后自动开通独立 tenant + user + workspace - 首次注册后自动开通独立 tenant + user + workspace
@ -153,7 +148,7 @@ Browser
- 公网域名 - 公网域名
- API 地址 - API 地址
- Langflow / AnythingLLM 嵌入地址 - Langflow / AnythingLLM 嵌入地址
- `LY SSO` / Google 开关 - Google 开关
- DevCloud 镜像 / NodePort 默认值 - DevCloud 镜像 / NodePort 默认值
### `knowledge_base.py` ### `knowledge_base.py`
@ -180,7 +175,6 @@ Browser
GET /health GET /health
GET /plans GET /plans
GET /auth/config GET /auth/config
POST /auth/ly-sso/login
POST /auth/google/login POST /auth/google/login
POST /demo/bootstrap POST /demo/bootstrap
POST /tenants POST /tenants
@ -307,7 +301,6 @@ python -m unittest discover -s tests -v
- MVP 核心业务闭环 - MVP 核心业务闭环
- 桥接配置契约 - 桥接配置契约
- `LY SSO` 登录
- Google 首次登录建 workspace - Google 首次登录建 workspace
- Session 认证 - Session 认证

View File

@ -10,8 +10,7 @@ Aurask 当前是一个按产品边界拆分的首版实现,根目录保持为
当前版本已经补齐了用户门户登录闭环: 当前版本已经补齐了用户门户登录闭环:
- `/signin` 风格化登录页 - `/signin` 风格化登录页
- `LY SSO` 登录入口 - Google 首次注册/登录后自动创建独立 workspace
- Google 首次注册/登录后自动创建用户独立 workspace
- 登录后双标签页工作台: - 登录后双标签页工作台:
- `Workflows` 内嵌 `Langflow` - `Workflows` 内嵌 `Langflow`
- `Knowledge Base` 内嵌 `AnythingLLM` - `Knowledge Base` 内嵌 `AnythingLLM`
@ -42,7 +41,6 @@ py -3 -m aurask demo --reset
- `GET /health` - `GET /health`
- `GET /plans` - `GET /plans`
- `GET /auth/config` - `GET /auth/config`
- `POST /auth/ly-sso/login`
- `POST /auth/google/login` - `POST /auth/google/login`
- `POST /demo/bootstrap` - `POST /demo/bootstrap`
- `POST /tenants` - `POST /tenants`
@ -77,9 +75,6 @@ AURASK_PUBLIC_BASE_URL=https://aurask.xyz
AURASK_PUBLIC_API_BASE_URL=https://aurask.xyz/api AURASK_PUBLIC_API_BASE_URL=https://aurask.xyz/api
AURASK_PUBLIC_LANGFLOW_URL=https://aurask.xyz/runtime/langflow/ AURASK_PUBLIC_LANGFLOW_URL=https://aurask.xyz/runtime/langflow/
AURASK_PUBLIC_ANYTHINGLLM_URL=https://aurask.xyz/runtime/anythingllm/ AURASK_PUBLIC_ANYTHINGLLM_URL=https://aurask.xyz/runtime/anythingllm/
AURASK_LY_SSO_ENABLED=true
AURASK_LY_SSO_USERNAME=ly-xujian1
AURASK_LY_SSO_PASSWORD=<inject-secret>
AURASK_GOOGLE_ENABLED=true AURASK_GOOGLE_ENABLED=true
AURASK_GOOGLE_CLIENT_ID=<google-client-id> AURASK_GOOGLE_CLIENT_ID=<google-client-id>
AURASK_SESSION_TTL_DAYS=7 AURASK_SESSION_TTL_DAYS=7
@ -124,7 +119,7 @@ cmd /c "py -3 -m unittest discover -s tests -v"
- MVP 业务闭环 - MVP 业务闭环
- PostgreSQL / PGVector / Redis / AnythingLLM / Langflow 桥接契约 - PostgreSQL / PGVector / Redis / AnythingLLM / Langflow 桥接契约
- `LY SSO` / Google 登录与 session - Google 登录与 session
## 相关文档 ## 相关文档

View File

@ -9,7 +9,7 @@
- 租户、用户、API Key、Session`api/aurask/auth.py` - 租户、用户、API Key、Session`api/aurask/auth.py`
- 套餐、订单、支付、TBU`api/aurask/plans.py`、`api/aurask/billing.py`、`api/aurask/quota.py` - 套餐、订单、支付、TBU`api/aurask/plans.py`、`api/aurask/billing.py`、`api/aurask/quota.py`
- 工作流编排:`api/aurask/orchestrator.py` - 工作流编排:`api/aurask/orchestrator.py`
- AnythingLLM workspace / 文档接入:`api/aurask/knowledge_base.py` - AnythingLLM workspace / 文档接入门面`api/aurask/knowledge_base.py`
- PostgreSQL / PGVector / Redis / AnythingLLM / Langflow 桥接:`api/aurask/bridges/` - PostgreSQL / PGVector / Redis / AnythingLLM / Langflow 桥接:`api/aurask/bridges/`
- 门户站点配置:`api/aurask/site_config.py` - 门户站点配置:`api/aurask/site_config.py`
@ -22,7 +22,7 @@ Aurask 现在支持两类 Bearer Token
- 由创建租户/用户或 demo bootstrap 返回 - 由创建租户/用户或 demo bootstrap 返回
2. Session Token 2. Session Token
- 适用于 `protal/` 登录态 - 适用于 `protal/` 登录态
- 由 `LY SSO`Google 登录接口签发 - 由 Google 登录接口签发
## 公开接口 ## 公开接口
@ -30,7 +30,6 @@ Aurask 现在支持两类 Bearer Token
GET /health GET /health
GET /plans GET /plans
GET /auth/config GET /auth/config
POST /auth/ly-sso/login
POST /auth/google/login POST /auth/google/login
POST /demo/bootstrap POST /demo/bootstrap
POST /tenants POST /tenants
@ -60,7 +59,7 @@ GET /admin/bridge-status
- 公网站点地址 - 公网站点地址
- API 地址 - API 地址
- `LY SSO` / Google 开关 - Google 开关
- Langflow / AnythingLLM iframe 地址 - Langflow / AnythingLLM iframe 地址
- DevCloud 对齐后的镜像与 NodePort 默认值 - DevCloud 对齐后的镜像与 NodePort 默认值
@ -73,11 +72,6 @@ AURASK_PUBLIC_BASE_URL=https://aurask.xyz
AURASK_PUBLIC_API_BASE_URL=https://aurask.xyz/api AURASK_PUBLIC_API_BASE_URL=https://aurask.xyz/api
AURASK_PUBLIC_LANGFLOW_URL=https://aurask.xyz/runtime/langflow/ AURASK_PUBLIC_LANGFLOW_URL=https://aurask.xyz/runtime/langflow/
AURASK_PUBLIC_ANYTHINGLLM_URL=https://aurask.xyz/runtime/anythingllm/ AURASK_PUBLIC_ANYTHINGLLM_URL=https://aurask.xyz/runtime/anythingllm/
AURASK_LY_SSO_ENABLED=true
AURASK_LY_SSO_LOGIN_URL=
AURASK_LY_SSO_USERNAME=ly-xujian1
AURASK_LY_SSO_PASSWORD=<ly-sso-password>
AURASK_LY_SSO_EMAIL_DOMAIN=ly.szlanyou.local
AURASK_GOOGLE_ENABLED=true AURASK_GOOGLE_ENABLED=true
AURASK_GOOGLE_CLIENT_ID=<google-client-id> AURASK_GOOGLE_CLIENT_ID=<google-client-id>
AURASK_GOOGLE_TOKENINFO_URL=https://oauth2.googleapis.com/tokeninfo AURASK_GOOGLE_TOKENINFO_URL=https://oauth2.googleapis.com/tokeninfo

View File

@ -50,10 +50,6 @@ def make_handler(app: AuraskApp):
if method == "GET" and path == "/auth/config": if method == "GET" and path == "/auth/config":
self._send(200, app.public_auth_config()) self._send(200, app.public_auth_config())
return return
if method == "POST" and path == "/auth/ly-sso/login":
body = self._read_json()
self._send(200, app.login_with_ly_sso(username=body.get("username", ""), password=body.get("password", "")))
return
if method == "POST" and path == "/auth/google/login": if method == "POST" and path == "/auth/google/login":
body = self._read_json() body = self._read_json()
self._send(200, app.login_with_google(id_token=body.get("id_token", ""))) self._send(200, app.login_with_google(id_token=body.get("id_token", "")))

View File

@ -54,22 +54,6 @@ class AuraskApp:
def public_auth_config(self) -> dict: def public_auth_config(self) -> dict:
return self.site_config.public_dict() return self.site_config.public_dict()
def login_with_ly_sso(self, *, username: str, password: str) -> dict:
if not self.site_config.ly_sso_enabled:
raise AuthError("LY SSO is not enabled")
if not self.site_config.ly_sso_password:
raise AuthError("LY SSO password secret is not configured")
if username != self.site_config.ly_sso_username or password != self.site_config.ly_sso_password:
raise AuthError("invalid LY SSO credentials")
email = os.getenv("AURASK_LY_SSO_EMAIL", f"{username}@{self.site_config.ly_sso_email_domain}")
return self._sign_in_external_identity(
provider="ly_sso",
subject=username,
email=email,
display_name=username,
avatar_url="",
)
def login_with_google(self, *, id_token: str) -> dict: def login_with_google(self, *, id_token: str) -> dict:
claims = self._verify_google_id_token(id_token) claims = self._verify_google_id_token(id_token)
email = claims.get("email", "").strip().lower() email = claims.get("email", "").strip().lower()

View File

@ -17,11 +17,6 @@ class SiteConfig:
public_api_base_url: str public_api_base_url: str
langflow_embed_url: str langflow_embed_url: str
anythingllm_embed_url: str anythingllm_embed_url: str
ly_sso_enabled: bool
ly_sso_login_url: str
ly_sso_username: str
ly_sso_password: str
ly_sso_email_domain: str
google_enabled: bool google_enabled: bool
google_client_id: str google_client_id: str
google_tokeninfo_url: str google_tokeninfo_url: str
@ -40,11 +35,6 @@ class SiteConfig:
public_api_base_url=os.getenv("AURASK_PUBLIC_API_BASE_URL", f"{public_base_url}/api").rstrip("/"), public_api_base_url=os.getenv("AURASK_PUBLIC_API_BASE_URL", f"{public_base_url}/api").rstrip("/"),
langflow_embed_url=os.getenv("AURASK_PUBLIC_LANGFLOW_URL", f"{public_base_url}/runtime/langflow/"), langflow_embed_url=os.getenv("AURASK_PUBLIC_LANGFLOW_URL", f"{public_base_url}/runtime/langflow/"),
anythingllm_embed_url=os.getenv("AURASK_PUBLIC_ANYTHINGLLM_URL", f"{public_base_url}/runtime/anythingllm/"), anythingllm_embed_url=os.getenv("AURASK_PUBLIC_ANYTHINGLLM_URL", f"{public_base_url}/runtime/anythingllm/"),
ly_sso_enabled=_enabled("AURASK_LY_SSO_ENABLED", True),
ly_sso_login_url=os.getenv("AURASK_LY_SSO_LOGIN_URL", ""),
ly_sso_username=os.getenv("AURASK_LY_SSO_USERNAME", "ly-xujian1"),
ly_sso_password=os.getenv("AURASK_LY_SSO_PASSWORD", ""),
ly_sso_email_domain=os.getenv("AURASK_LY_SSO_EMAIL_DOMAIN", "ly.szlanyou.local"),
google_enabled=_enabled("AURASK_GOOGLE_ENABLED", bool(os.getenv("AURASK_GOOGLE_CLIENT_ID", ""))), google_enabled=_enabled("AURASK_GOOGLE_ENABLED", bool(os.getenv("AURASK_GOOGLE_CLIENT_ID", ""))),
google_client_id=os.getenv("AURASK_GOOGLE_CLIENT_ID", ""), google_client_id=os.getenv("AURASK_GOOGLE_CLIENT_ID", ""),
google_tokeninfo_url=os.getenv("AURASK_GOOGLE_TOKENINFO_URL", "https://oauth2.googleapis.com/tokeninfo"), google_tokeninfo_url=os.getenv("AURASK_GOOGLE_TOKENINFO_URL", "https://oauth2.googleapis.com/tokeninfo"),
@ -61,11 +51,6 @@ class SiteConfig:
"public_base_url": self.public_base_url, "public_base_url": self.public_base_url,
"public_api_base_url": self.public_api_base_url, "public_api_base_url": self.public_api_base_url,
"auth": { "auth": {
"ly_sso": {
"enabled": self.ly_sso_enabled,
"login_url": self.ly_sso_login_url,
"username_hint": self.ly_sso_username,
},
"google": { "google": {
"enabled": self.google_enabled, "enabled": self.google_enabled,
"client_id": self.google_client_id, "client_id": self.google_client_id,

View File

@ -7,15 +7,6 @@ GET http://127.0.0.1:8080/plans
### Portal auth config ### Portal auth config
GET http://127.0.0.1:8080/auth/config GET http://127.0.0.1:8080/auth/config
### LY SSO login
POST http://127.0.0.1:8080/auth/ly-sso/login
Content-Type: application/json
{
"username": "ly-xujian1",
"password": "replace-with-env-password"
}
### Google login ### Google login
POST http://127.0.0.1:8080/auth/google/login POST http://127.0.0.1:8080/auth/google/login
Content-Type: application/json Content-Type: application/json

View File

@ -3,7 +3,7 @@
本文档基于当前仓库与 DevCloud 现网结构,兼顾两部分目标: 本文档基于当前仓库与 DevCloud 现网结构,兼顾两部分目标:
- 保留已落地的 DevCloud `base + production overlay` 部署方式 - 保留已落地的 DevCloud `base + production overlay` 部署方式
- 纳入本次新增的门户登录流、`LY SSO` / Google、Langflow / AnythingLLM 嵌入配置 - 纳入本次新增的门户登录流、Google 登录、Langflow / AnythingLLM 嵌入配置
## 目录结构 ## 目录结构
@ -95,8 +95,6 @@ deploy/k3s/
- `AURASK_DEVCLOUD_WEB_IMAGE=registry.mydevcloud.love/devcloud/aurask-web:latest` - `AURASK_DEVCLOUD_WEB_IMAGE=registry.mydevcloud.love/devcloud/aurask-web:latest`
- `AURASK_DEVCLOUD_API_NODE_URL=http://45.113.2.55:30091` - `AURASK_DEVCLOUD_API_NODE_URL=http://45.113.2.55:30091`
- `AURASK_DEVCLOUD_WEB_NODE_URL=http://45.113.2.55:30090` - `AURASK_DEVCLOUD_WEB_NODE_URL=http://45.113.2.55:30090`
- `AURASK_LY_SSO_ENABLED=true`
- `AURASK_LY_SSO_USERNAME=ly-xujian1`
- `AURASK_GOOGLE_ENABLED=true` - `AURASK_GOOGLE_ENABLED=true`
- `AURASK_SESSION_TTL_DAYS=7` - `AURASK_SESSION_TTL_DAYS=7`
@ -107,7 +105,6 @@ deploy/k3s/
- `AURASK_DATABASE_URL` - `AURASK_DATABASE_URL`
- `AURASK_ANYTHINGLLM_API_KEY` - `AURASK_ANYTHINGLLM_API_KEY`
- `AURASK_LANGFLOW_API_KEY` - `AURASK_LANGFLOW_API_KEY`
- `AURASK_LY_SSO_PASSWORD`
- `AURASK_GOOGLE_CLIENT_ID` - `AURASK_GOOGLE_CLIENT_ID`
说明: 说明:
@ -122,7 +119,7 @@ deploy/k3s/
职责: 职责:
- API Gateway - API Gateway
- `LY SSO` / Google 登录 - Google 登录
- Session 签发与校验 - Session 签发与校验
- 配额、订单、支付、工作流入口 - 配额、订单、支付、工作流入口
- 返回门户配置与嵌入 URL - 返回门户配置与嵌入 URL

View File

@ -21,9 +21,6 @@ data:
AURASK_REDIS_WORKFLOW_QUEUE: aurask:workflow-runs AURASK_REDIS_WORKFLOW_QUEUE: aurask:workflow-runs
AURASK_ANYTHINGLLM_BASE_URL: http://anythingllm.aurask-runtime.svc.cluster.local:3001 AURASK_ANYTHINGLLM_BASE_URL: http://anythingllm.aurask-runtime.svc.cluster.local:3001
AURASK_LANGFLOW_BASE_URL: http://langflow-runtime.aurask-runtime.svc.cluster.local:7860 AURASK_LANGFLOW_BASE_URL: http://langflow-runtime.aurask-runtime.svc.cluster.local:7860
AURASK_LY_SSO_ENABLED: "true"
AURASK_LY_SSO_USERNAME: ly-xujian1
AURASK_LY_SSO_EMAIL_DOMAIN: ly.szlanyou.local
AURASK_GOOGLE_ENABLED: "true" AURASK_GOOGLE_ENABLED: "true"
AURASK_SESSION_TTL_DAYS: "7" AURASK_SESSION_TTL_DAYS: "7"
AURASK_CORS_ALLOW_ORIGIN: https://aurask.xyz AURASK_CORS_ALLOW_ORIGIN: https://aurask.xyz

View File

@ -8,5 +8,4 @@ stringData:
AURASK_DATABASE_URL: postgresql://aurask:<postgres-password>@postgres.aurask-data.svc.cluster.local:5432/aurask AURASK_DATABASE_URL: postgresql://aurask:<postgres-password>@postgres.aurask-data.svc.cluster.local:5432/aurask
AURASK_ANYTHINGLLM_API_KEY: <anythingllm-api-key> AURASK_ANYTHINGLLM_API_KEY: <anythingllm-api-key>
AURASK_LANGFLOW_API_KEY: <langflow-api-key> AURASK_LANGFLOW_API_KEY: <langflow-api-key>
AURASK_LY_SSO_PASSWORD: <ly-sso-password>
AURASK_GOOGLE_CLIENT_ID: <google-oauth-client-id> AURASK_GOOGLE_CLIENT_ID: <google-oauth-client-id>

View File

@ -5,7 +5,6 @@
## 当前页面能力 ## 当前页面能力
- 未登录时渲染 `/signin` 风格登录页 - 未登录时渲染 `/signin` 风格登录页
- 支持 `LY SSO` 登录按钮与本地凭据提交
- 支持 Google 登录入口 - 支持 Google 登录入口
- 新用户首次登录自动创建独立 workspace - 新用户首次登录自动创建独立 workspace
- 登录后显示: - 登录后显示:
@ -18,7 +17,6 @@
门户依赖以下 API 门户依赖以下 API
- `GET /auth/config` - `GET /auth/config`
- `POST /auth/ly-sso/login`
- `POST /auth/google/login` - `POST /auth/google/login`
- `GET /auth/session` - `GET /auth/session`
- `POST /auth/logout` - `POST /auth/logout`

View File

@ -8,7 +8,6 @@ const state = {
sessionToken: window.localStorage.getItem(STORAGE_KEY) || "", sessionToken: window.localStorage.getItem(STORAGE_KEY) || "",
profile: null, profile: null,
activeTab: window.localStorage.getItem(TAB_KEY) || "workflows", activeTab: window.localStorage.getItem(TAB_KEY) || "workflows",
lyFormOpen: false,
loading: true, loading: true,
error: "", error: "",
}; };
@ -127,31 +126,6 @@ async function bootstrap() {
} }
} }
async function submitLySso(event) {
event.preventDefault();
state.error = "";
render();
const form = new FormData(event.currentTarget);
try {
const payload = await request("/auth/ly-sso/login", {
method: "POST",
body: {
username: String(form.get("username") || "").trim(),
password: String(form.get("password") || ""),
},
});
persistSession(payload.token);
state.profile = payload;
state.lyFormOpen = false;
ensureDashboardRoute();
} catch (error) {
state.error = error.message || "LY SSO sign-in failed";
} finally {
render();
mountGoogleButton();
}
}
async function signInWithGoogle(idToken) { async function signInWithGoogle(idToken) {
state.error = ""; state.error = "";
render(); render();
@ -177,7 +151,6 @@ async function logout() {
} }
persistSession(""); persistSession("");
state.profile = null; state.profile = null;
state.lyFormOpen = false;
ensureSigninRoute(); ensureSigninRoute();
render(); render();
mountGoogleButton(); mountGoogleButton();
@ -213,7 +186,6 @@ function renderStatusPills() {
} }
function renderSignin() { function renderSignin() {
const lyConfig = state.config?.auth?.ly_sso || {};
const googleConfig = state.config?.auth?.google || {}; const googleConfig = state.config?.auth?.google || {};
const googleEnabled = Boolean(googleConfig.enabled && googleConfig.client_id); const googleEnabled = Boolean(googleConfig.enabled && googleConfig.client_id);
app.innerHTML = ` app.innerHTML = `
@ -231,37 +203,14 @@ function renderSignin() {
<div class="signin-header"> <div class="signin-header">
<p class="section-kicker">Welcome back</p> <p class="section-kicker">Welcome back</p>
<h2>Sign in to Aurask</h2> <h2>Sign in to Aurask</h2>
<p>Use your organization account first, or enable Google one-tap registration for self-serve users.</p> <p>Continue with Google to access your workspace or create a new one on first sign-in.</p>
</div> </div>
<div class="signin-actions"> ${googleEnabled ? '<div id="googleButton" class="google-box"></div>' : '<div class="signin-actions"><button class="auth-btn auth-btn-secondary" type="button" disabled>Continue with Google</button></div>'}
<button id="lyButton" class="auth-btn auth-btn-primary" type="button">Use LY SSO</button>
<button id="googleFallbackButton" class="auth-btn auth-btn-secondary" type="button" ${googleEnabled ? "" : "disabled"}>
Continue with Google
</button>
</div>
<div id="googleButton" class="google-box ${googleEnabled ? "" : "is-hidden"}"></div>
${ ${
googleEnabled googleEnabled
? '<p class="signin-tip">Google new-user login provisions a dedicated Aurask workspace on first sign-in.</p>' ? '<p class="signin-tip">Google new-user login provisions a dedicated Aurask workspace on first sign-in.</p>'
: '<p class="signin-tip">Set `AURASK_GOOGLE_CLIENT_ID` to enable Google one-tap registration.</p>' : '<p class="signin-tip">Set `AURASK_GOOGLE_CLIENT_ID` to enable Google one-tap registration.</p>'
} }
${
state.lyFormOpen
? `
<form id="lyForm" class="ly-form">
<label>
Username
<input name="username" value="${escapeHtml(lyConfig.username_hint || "ly-xujian1")}" autocomplete="username" />
</label>
<label>
Password
<input name="password" type="password" autocomplete="current-password" placeholder="Enter LY SSO password" />
</label>
<button class="auth-btn auth-btn-primary" type="submit">Sign in with LY SSO</button>
</form>
`
: ""
}
${state.error ? `<p class="message error">${escapeHtml(state.error)}</p>` : ""} ${state.error ? `<p class="message error">${escapeHtml(state.error)}</p>` : ""}
<div class="signin-footer"> <div class="signin-footer">
<span>Need a first workspace?</span> <span>Need a first workspace?</span>
@ -270,21 +219,6 @@ function renderSignin() {
</section> </section>
</main> </main>
`; `;
document.querySelector("#lyButton")?.addEventListener("click", () => {
if (lyConfig.login_url) {
window.location.href = lyConfig.login_url;
return;
}
state.lyFormOpen = !state.lyFormOpen;
render();
mountGoogleButton();
});
document.querySelector("#lyForm")?.addEventListener("submit", submitLySso);
document.querySelector("#googleFallbackButton")?.addEventListener("click", () => {
document.querySelector("#googleButton")?.scrollIntoView({ behavior: "smooth", block: "center" });
});
} }
function renderDashboard() { function renderDashboard() {

View File

@ -15,7 +15,6 @@ from aurask.app import create_app
class AuthSessionTests(unittest.TestCase): class AuthSessionTests(unittest.TestCase):
def setUp(self) -> None: def setUp(self) -> None:
self.env_keys = [ self.env_keys = [
"AURASK_LY_SSO_PASSWORD",
"AURASK_GOOGLE_ENABLED", "AURASK_GOOGLE_ENABLED",
"AURASK_GOOGLE_ALLOW_UNVERIFIED_ID_TOKEN", "AURASK_GOOGLE_ALLOW_UNVERIFIED_ID_TOKEN",
"AURASK_GOOGLE_CLIENT_ID", "AURASK_GOOGLE_CLIENT_ID",
@ -29,18 +28,6 @@ class AuthSessionTests(unittest.TestCase):
else: else:
os.environ[key] = value os.environ[key] = value
def test_ly_sso_login_creates_session_and_workspace(self) -> None:
os.environ["AURASK_LY_SSO_PASSWORD"] = "local-secret"
app = create_app(None, reset=True)
payload = app.login_with_ly_sso(username="ly-xujian1", password="local-secret")
context = app.auth.authenticate(f"Bearer {payload['token']}")
self.assertEqual(context["token_type"], "session")
self.assertEqual(payload["workspace"]["tenant_id"], payload["tenant"]["id"])
self.assertEqual(payload["quota"]["plan_code"], "free_trial")
self.assertEqual(len(app.list_workspaces(payload["tenant"]["id"])), 1)
def test_google_first_login_reuses_workspace_after_registration(self) -> None: def test_google_first_login_reuses_workspace_after_registration(self) -> None:
os.environ["AURASK_GOOGLE_ENABLED"] = "true" os.environ["AURASK_GOOGLE_ENABLED"] = "true"
os.environ["AURASK_GOOGLE_ALLOW_UNVERIFIED_ID_TOKEN"] = "true" os.environ["AURASK_GOOGLE_ALLOW_UNVERIFIED_ID_TOKEN"] = "true"
@ -62,6 +49,7 @@ class AuthSessionTests(unittest.TestCase):
self.assertFalse(second_login["is_new_user"]) self.assertFalse(second_login["is_new_user"])
self.assertEqual(first_login["workspace"]["id"], second_login["workspace"]["id"]) self.assertEqual(first_login["workspace"]["id"], second_login["workspace"]["id"])
self.assertEqual(len(app.list_workspaces(first_login["tenant"]["id"])), 1) self.assertEqual(len(app.list_workspaces(first_login["tenant"]["id"])), 1)
self.assertEqual(app.auth.authenticate(f"Bearer {first_login['token']}")["token_type"], "session")
def _fake_google_token(self, claims: dict) -> str: def _fake_google_token(self, claims: dict) -> str:
header = self._base64url({"alg": "none", "typ": "JWT"}) header = self._base64url({"alg": "none", "typ": "JWT"})