feat: add admin accounts and image templates
This commit is contained in:
124
findings.md
124
findings.md
@@ -176,3 +176,127 @@
|
||||
- The visible `统一认证中心` OAuth entry was removed from the login page after user feedback.
|
||||
- The standalone login page uses the existing GSAP motion helper layer (`runScopedMotion`, `revealChildren`, `pulseFeedback`) for consistent app motion.
|
||||
- Browser viewport checks passed at 1280x800 and 390x844: no topbar, no SSO link text, logo and platform name present, login panel present, and no horizontal overflow.
|
||||
|
||||
## 2026-06-09 Repository and Runtime Status Findings
|
||||
- The current repository root is a Git checkout on `main` tracking `origin/main`.
|
||||
- The remote is `https://git.nianxx.cn/wangxuming/NianAIGC.git`.
|
||||
- The workspace was overwritten from remote and is currently clean at `d98e58a docs: update public api docs`.
|
||||
- The project uses npm (`package-lock.json`) and Next.js dev startup through `npm run dev`.
|
||||
- Local Node version during verification was `v22.22.1`, satisfying the `package.json` `>=20` engine.
|
||||
- During startup verification, ports `3000`, `3001`, and `3002` were already occupied by local Node/Next processes or listeners; use a confirmed-free alternate port rather than assuming `3000`.
|
||||
- `npm run dev -- --hostname 127.0.0.1 --port 3003` successfully started the current project and reached Next Ready in 2.9 seconds.
|
||||
- A smoke request to `http://127.0.0.1:3003/` returned `307 Temporary Redirect` to `/auth/login?next=%2F`, confirming the login-protected app flow.
|
||||
- Current status check on 2026-06-09 found no `next dev` / `next-server` process and no listener on `3003`; the project is verified startable but not currently running.
|
||||
|
||||
## 2026-07-01 Account ID Partitioning Findings
|
||||
- First-party browser APIs already pass the authenticated session user id into asset and generation flows.
|
||||
- Public API v1 currently authenticates by `clientId:key`, but jobs and assets are still created with `ownerId = DEFAULT_OWNER_ID`.
|
||||
- Public API listing/detail access filters with `externalClientId` and `api-client:<clientId>` tags, which works as an access check but keeps all API account data in one default owner partition.
|
||||
- The data store and Supabase schema already support `owner_id` indexes and idempotency uniqueness by `(owner_id, external_client_id, idempotency_key)`, so the change can be made by deriving a stable account owner id from the API client id.
|
||||
- Job detail and cancel routes currently check only `externalClientId`; they should also require the account owner id so a client id collision cannot cross account partitions.
|
||||
- Implemented owner derivation as `publicApiOwnerId(client)`, yielding `api:<sanitizedAccountId>`.
|
||||
- Public API job creation, idempotency lookup, job listing/detail/cancel, asset upload/register/list/detail/download now use the derived API account owner.
|
||||
- Documentation now states that `ZHINIAN_API_KEYS` uses `账号ID:key` and that records are partitioned under `api:<账号ID>`.
|
||||
|
||||
## 2026-07-01 Password Login Captcha Finding
|
||||
- `origin/main` is up to date at `d98e58a`; relevant history includes `ce358df 修改认证中心对接方式` and `288e31d 移除验证码输入框`.
|
||||
- Current `components/auth-login-panel.tsx` does not render captcha controls and submits only `username`, `password`, and `next`.
|
||||
- Current `app/api/auth/password/route.ts` no longer requires captcha; it only forwards `code` and `randomStr` if they are present in the request body.
|
||||
- Current local `.env.local` points password login at `https://onefeel.brother7.cn/ingress/auth` with client id `customPC`.
|
||||
- A local login probe with fake credentials returned `验证码不能为空`; a direct token request to the configured auth center with the same non-secret dummy credentials also returned `验证码不能为空`.
|
||||
- Therefore the observed captcha error is coming from the configured auth center instance, not from the current AIGC frontend or password route validation.
|
||||
- The operations SSO guide defaults external projects to OAuth client `app/app`, recommends adding token-flow clients to `security.ignore-clients`, and notes `customPC` is a special platform-user compatibility client that skips AES password decrypt.
|
||||
- Dummy token probes showed `app/app` reaches normal credential validation (`用户名或密码错误`) while `customPC` is intercepted by captcha validation on the current auth center instance.
|
||||
- Updated the project defaults, docs, `.env.example`, and local `.env.local` to use `app/app` plus `ZHINIAN_AUTH_PASSWORD_ENC_KEY=thanks,pig4cloud`.
|
||||
- After restarting the dev server, local `/api/auth/password` with dummy credentials returns `用户名或密码错误`, confirming the captcha interception is bypassed for the configured client.
|
||||
|
||||
## 2026-07-01 Internal RBAC / Account Management Findings
|
||||
- Initial requested guide `/Users/inmanx/Desktop/organization-external-api.md` was missing; updated guide `/Users/inmanx/Desktop/organization-external-api(1).md` is available and has 1310 lines.
|
||||
- Existing JWT session already stores `authorities` and `scope` on `AuthUser`, making it suitable for internal RBAC.
|
||||
- Before the RBAC change, navigation exposed `创作`, `结果`, `日志`, and `设置` to every logged-in user.
|
||||
- Before the RBAC change, middleware only checked whether a user was authenticated and did not distinguish ordinary users from administrators.
|
||||
- Before the RBAC change, `/api/settings` checked `requireAppUser()` but not admin permission.
|
||||
- Before the RBAC change, `/api/logs` relied on middleware authentication only and did not call `requireAppUser()` or admin checks inside the route.
|
||||
- RBAC now hides admin navigation for ordinary users and protects `/logs`, `/settings`, `/accounts`, `/api/logs`, `/api/settings`, and `/api/admin/*`.
|
||||
- Updated guide covers organization, department, role, member, and enterprise user operation APIs.
|
||||
- Organization/member APIs are served by `basic-capability-services-biz`; enterprise user management APIs are exposed by `hotel-staff-server-biz`.
|
||||
- Member list APIs remain `@Inner` and require header `from: Y`.
|
||||
- Enterprise user APIs require `Authorization` and a token with administrator role `1`; otherwise they return `仅管理员角色允许调用`.
|
||||
- Account creation should use `/adminOrganization/organizationMember/addOrganizationMemberAndCreatePlatformUser` to create the enterprise user and bind the organization member in one call.
|
||||
- Password maintenance is available through `/adminPcUser/resetPlatformUserPassword`, with `tenantId`, numeric `userId`, `newPassword`, and optional `mustChangePassword`.
|
||||
- Updated `/Users/inmanx/Desktop/organization-external-api(2).md` confirms the external member list path is `/adminOrganization/organizationMember/organizationMemberList` through `hotelStaff`; only the basic service internal `/organizationMember/organizationMemberList` path needs `from: Y`.
|
||||
- The updated `hotelStaff` member-list proxy is reachable from the app, but the current login token can still be rejected by the upstream service with `仅管理员角色允许调用`.
|
||||
- Local RBAC allow-listing `ceshiop` as a platform admin only controls this app's pages and APIs; it does not grant upstream `hotelStaff` administrator role `1` inside the authentication center token.
|
||||
- Account management now treats upstream member-list administrator denial like a recoverable member-list-only limitation: the page can still load configured organization data and keep account creation/password maintenance available when those upstream endpoints allow the token.
|
||||
- The updated organization guide exposes department creation at `POST /organizationGroup/createOrganizationGroup` with `organizationId`, `groupName`, optional `groupDesc`, and optional `parentId`.
|
||||
- The account page can create a department from the member form and then refresh/select the created department, so admins do not need to leave account management before creating members.
|
||||
|
||||
## 2026-07-02 Image Template Findings
|
||||
- User requested image-generation templates with selection-time effect preview and preset prompt support.
|
||||
- This should be account-managed data, not global environment configuration.
|
||||
- Existing browser image generation API already uses `requireAppUser()` and submits `ownerId: user.id`, so template APIs should use the same owner boundary.
|
||||
- Template configuration should remain inside the image generation module rather than the global settings page.
|
||||
- The create page already keeps image/video prompt state client-side, detects the active image engine from `/api/health`, and submits prompt, materials, size, force-single, and engine-specific tuning to `/api/generations/image`.
|
||||
- Implemented image templates with fields for name, category, description, preset prompt, preview image URL, width/height, force-single, and sort order.
|
||||
- New first-party routes are `/api/image-templates` and `/api/image-templates/:id`; both require the app user and use the authenticated user id as owner id.
|
||||
- Local JSON state now normalizes `imageTemplates`; Supabase deployments need the new `image_templates` table from `supabase/schema.sql`.
|
||||
- Browser verification used a temporary auth-disabled dev server to create one demo template, confirm the `/create` left template rail and template application behavior, then deleted the demo template.
|
||||
- Final dev server was restarted with the normal `.env.local` auth-enabled environment on `127.0.0.1:3001`.
|
||||
|
||||
## 2026-07-02 Large Auth Session Finding
|
||||
- A new real account could receive a successful `/api/auth/password` response and still be redirected back to `/auth/login?next=/create`, which indicates the browser did not persist a valid session rather than an upstream password failure.
|
||||
- The session cookie stores the signed session plus access token so the app can forward the current login token to organization/staff APIs.
|
||||
- Accounts with larger JWT or authority payloads can exceed a single browser cookie's practical size limit; splitting `zhinian_session` into chunked cookies keeps the same signed payload while allowing middleware and server helpers to reassemble it.
|
||||
- Settings no longer exposes a template tab.
|
||||
- In image mode, `/create` now renders a left vertical `模板选择` rail with an icon `添加模板` button and thumbnail/name-only template cards.
|
||||
- The add-template entry opens an in-module template form modal; it is not exposed from settings.
|
||||
- Clicking a template selects it and brings its preset prompt, image size, and force-single value into the generation console on the right.
|
||||
- Desktop and narrow browser verification confirmed the template picker is an independent left-side panel beside the generation panel, not a child of the generation panel, with no horizontal overflow.
|
||||
- The image/video/edit mode switch is now contained by the generation panel, not placed above or across the far-left template module.
|
||||
- Template preview image upload now uses the same `/api/assets/upload` route as workbench materials, so configured OSS storage is reused instead of accepting a manually typed preview URL.
|
||||
- New template configuration no longer exposes category or remark fields; the user-facing free text field is `简介`, backed by the existing template description data.
|
||||
- Template preset prompts can contain `@图片1` style placeholders. The generation console parses those tokens and shows missing upload slots below the prompt.
|
||||
- Placeholder upload slots bind the uploaded asset to the exact requested token, so clicking the `@图片2` slot creates/updates the `@图片2` material instead of relying on upload order.
|
||||
- Material labels are preserved after removal to avoid silently breaking prompt references created by templates.
|
||||
- UI/UX skill guidance for the add-template modal was applied as a focused SaaS workspace form: strong preview region, fewer visible decisions at once, clear bottom actions, and responsive stacking on narrow screens.
|
||||
- While editing a template prompt, parsed placeholder chips are shown below the textarea so users can confirm which upload slots the template will request after selection.
|
||||
- Image templates now store the target image generation engine in `settings.engine`, with Jimeng using `settings.scale` and Image2/EvoLink using `settings.quality`.
|
||||
- First-party image generation now accepts a per-request `engine` override and passes it into `submitImageJob()`, so template engine choices are honored by the provider payload.
|
||||
- The generation console exposes the current image engine selector; applying a template updates this selector plus the matching parameter control.
|
||||
- Material placeholders now require an explicit number, so `@图片1` and `@图2` create upload slots while bare `@图片` or `@图片这种普通文字` stay plain prompt text.
|
||||
- Template prompt editing includes explicit placeholder insertion controls for image/video/audio slots, making the placeholder confirmation action deliberate instead of relying on unfinished `@` typing.
|
||||
- Existing image templates can be reopened from the top-right edit action on each template card and saved through the account-scoped PATCH route.
|
||||
- The template rail is intentionally wider on desktop and each card separates image preview, template selection, and template editing into distinct controls.
|
||||
- Clicking a template thumbnail opens a larger preview dialog; choosing from that dialog applies the template and closes the preview.
|
||||
- Typing `@` in prompt editors now opens a temporary material draft slot instead of immediately writing a partial token into the prompt body.
|
||||
- A material draft is confirmed into the prompt only by Enter or explicit option selection; confirmed values are inserted with text boundaries so subsequent Chinese text is not absorbed into the token.
|
||||
- The temporary draft slot is shared by the generation prompt and template preset prompt; invalid text such as `图片这种普通文字` stays in the slot and does not create upload requirements.
|
||||
- Confirmed numbered tokens keep using the existing visual token overlay, placeholder chips, and missing upload-slot UI.
|
||||
- The temporary material draft slot should remain visually inside the prompt editor surface, not below the input, so `@` entry feels like an inline editing affordance.
|
||||
- Template preset prompts use the same token overlay as the generation prompt; confirmed placeholders such as `@视频1` are visibly colored inside the input area before saving the template.
|
||||
- The image template rail now uses a wider desktop/tablet track (`390-480px` desktop, `315-375px` tablet) and stacks above the generation panel on mobile so reference previews stay browseable.
|
||||
- Template thumbnails use a `4:3` viewport with contained images, allowing both `9:16` and `16:9` reference images to be inspected without cropping.
|
||||
- Template card application now requires the explicit `选择模板` button; thumbnail clicks open preview and template name/description text no longer selects the template.
|
||||
- The template rail remains visible in image and video generation modes; only the image-editing modes (`局部重绘`, `智能超清`) use the standalone editor layout without the template rail.
|
||||
- Template cards are fixed compact items (`138px x 184px`) inside the rail list, so each template has a consistent smaller footprint.
|
||||
- The template rail height is synchronized from the right generation panel through a `ResizeObserver`; the rail body is split into fixed header/action rows and a scrolling template-list row.
|
||||
- The scrollbar belongs only to `.image-template-rail-list`; `模板选择` and `添加模板` stay outside the scroll container.
|
||||
- Template rail cards now use their preview image as a full-bleed card surface with `object-fit: cover`.
|
||||
- Template card title, intro, and select action sit inside a bottom floating frosted-glass overlay; the select button remains the only action that applies the template.
|
||||
- The zoom icon was removed from template cards, while the edit icon remains on the top-right corner above the image.
|
||||
- Selected template cards use a heavier layered shadow and slight upward transform to create stronger depth.
|
||||
- The template intro/description field is no longer part of the create/edit template UI or card display; old stored descriptions may still exist in data but are ignored by this surface.
|
||||
- The template edit icon now sits inside the card's frosted-glass overlay instead of on the image corner.
|
||||
- Template selection is a toggle: the first click captures the current right-side image generation state and applies the template; clicking the selected template again restores that snapshot and clears the active template state.
|
||||
- The compact full-bleed template card target is `132px x 176px`; the widened desktop rail should fit three cards per row.
|
||||
- The card footer uses a two-row frosted-glass grid: title spans the first row, while the select/cancel button and edit icon share the second row to avoid cramped text or overlap.
|
||||
|
||||
## 2026-07-02 Create Task Module Findings
|
||||
- The creation console can reuse existing first-party APIs for a task list: `/api/generations/image`, `/api/generations/video`, and `/api/assets`.
|
||||
- `GenerationJob` already has the needed task fields: prompt/name fallback, status, created/updated timestamps, capability, and output asset ids.
|
||||
- Generated task thumbnails can be resolved by mapping `GenerationJob.outputAssetIds` to assets from `/api/assets`; queued/running tasks need a placeholder when no output asset exists yet.
|
||||
- The existing results page already has a task view and detail panel, so the create-page `查看详情` action deep-links to `/assets?view=tasks&taskId=<id>` instead of creating a separate task page.
|
||||
- Desktop create layout now supports three independent modules: left template rail, center generation console, and right task module. At narrower widths the task module drops below the main modules, and at mobile widths all modules stack without horizontal overflow.
|
||||
- The right task module now targets `560-640px` on desktop/wide screens so task name, status, elapsed time, and `查看详情` can stay on one horizontal row.
|
||||
- Queued/running jobs without output assets should render a clear `生成中` thumbnail placeholder instead of a generic empty asset icon.
|
||||
- Completed image-task thumbnails are preview actions inside `/create`; clicking them opens the same large asset-preview surface while `查看详情` remains the route to the full task page.
|
||||
|
||||
Reference in New Issue
Block a user