129 lines
4.9 KiB
Markdown
129 lines
4.9 KiB
Markdown
# Registration Token State Implementation Plan
|
|
|
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
|
**Goal:** Ensure registration never creates or retains a browser authentication token, while password and SMS login continue to persist theirs.
|
|
|
|
**Architecture:** `utils/ApiClient.js` remains the single owner of browser token persistence. The `register()` method will leave its request and response contract unchanged, then clear the configured storage key after a successful response. `tests/api-client.test.js` will exercise the behavior through the public client methods and an in-memory storage adapter.
|
|
|
|
**Tech Stack:** Browser JavaScript (UMD), Node.js `assert` tests, Axios request adapter.
|
|
|
|
## Global Constraints
|
|
|
|
- Only `login()` and `loginBySms()` may persist a response token under the configured token key.
|
|
- Successful `register()` clears the configured token key even when its response contains `token`, `accessToken`, or `tokenValue`.
|
|
- Failed registration leaves existing token storage unchanged.
|
|
- Registration page behavior remains a redirect to `login.html`.
|
|
- Do not refactor unrelated request, storage, page, or authentication behavior.
|
|
|
|
---
|
|
|
|
### Task 1: Enforce registration token state in the API client
|
|
|
|
**Files:**
|
|
- Modify: `tests/api-client.test.js:83-111`
|
|
- Modify: `utils/ApiClient.js:176-182`
|
|
|
|
**Interfaces:**
|
|
- Consumes: `client.register(body)` and `client.loginBySms(body)` from `GenealogyApi.createClient()`.
|
|
- Produces: `client.register(body)` returns the API response while removing the configured token key after a successful request.
|
|
|
|
- [ ] **Step 1: Write the failing regression test**
|
|
|
|
Insert the following immediately after the existing `client.loginBySms(...)` assertions and before `client.sendSmsCode(...)` in `tests/api-client.test.js`:
|
|
|
|
```js
|
|
assert.strictEqual(store.values['token-key'], 'server-token');
|
|
|
|
store.setItem('token-key', 'existing-token');
|
|
const registerResponse = await client.register({
|
|
phone: '13900000000',
|
|
password: 'register-md5',
|
|
nickName: 'new-user',
|
|
validToken: 'register-ticket'
|
|
});
|
|
assert.deepStrictEqual(registerResponse, {
|
|
token: 'server-token',
|
|
url: '/genealogy/pc/auth/register'
|
|
});
|
|
assert.strictEqual(calls[8].url, '/genealogy/pc/auth/register');
|
|
assert.strictEqual(calls[8].headers.Authorization, undefined);
|
|
assert.strictEqual(calls[8].data.grantType, 'password');
|
|
assert.strictEqual(calls[8].data.registerSource, 'PC');
|
|
assert.strictEqual(store.getItem('token-key'), null);
|
|
|
|
const failedRegisterStore = createStore({
|
|
'token-key': 'existing-token'
|
|
});
|
|
const failedRegisterClient = GenealogyApi.createClient({
|
|
baseUrl: 'https://test-genealogy-api.ddxcjp.cn',
|
|
clientId: 'client-x',
|
|
tenantId: 'tenant-x',
|
|
tokenKey: 'token-key',
|
|
tokenStore: failedRegisterStore,
|
|
axiosInstance: {
|
|
request: async () => {
|
|
throw new Error('register failed');
|
|
}
|
|
}
|
|
});
|
|
await assert.rejects(
|
|
failedRegisterClient.register({
|
|
phone: '13900000001',
|
|
password: 'register-md5',
|
|
nickName: 'failed-user',
|
|
validToken: 'register-ticket'
|
|
}),
|
|
/register failed/
|
|
);
|
|
assert.strictEqual(failedRegisterStore.getItem('token-key'), 'existing-token');
|
|
```
|
|
|
|
Move the existing `client.sendSmsCode(...)` assertions from index `8` to index `9`, then change the final call-count assertion from `9` to `10`.
|
|
|
|
- [ ] **Step 2: Run the regression test and confirm the current failure**
|
|
|
|
Run: `node tests/api-client.test.js`
|
|
|
|
Expected: failure at `assert.strictEqual(store.getItem('token-key'), null)` because the current `register()` implementation writes `server-token` to `token-key`. The failed-registration assertion will already pass, documenting that the token must change only after a successful response.
|
|
|
|
- [ ] **Step 3: Implement the minimal token-state change**
|
|
|
|
In `utils/ApiClient.js`, replace the body of `register()` with:
|
|
|
|
```js
|
|
async function register(body) {
|
|
var data = await request('POST', '/genealogy/pc/auth/register', {
|
|
auth: false,
|
|
body: Object.assign({ grantType: 'password', registerSource: 'PC' }, withTenant(body))
|
|
});
|
|
clearToken();
|
|
return data;
|
|
}
|
|
```
|
|
|
|
- [ ] **Step 4: Run the focused test and confirm it passes**
|
|
|
|
Run: `node tests/api-client.test.js`
|
|
|
|
Expected: `api-client tests passed`.
|
|
|
|
- [ ] **Step 5: Run the complete Node test suite**
|
|
|
|
Run: `Get-ChildItem -Path tests -Filter *.test.js | ForEach-Object { node $_.FullName }`
|
|
|
|
Expected: every test script prints its success message and PowerShell exits with code `0`.
|
|
|
|
- [ ] **Step 6: Check the final diff and commit the implementation**
|
|
|
|
Run: `git diff --check`
|
|
|
|
Expected: exit code `0` with no whitespace errors.
|
|
|
|
Then commit only the implementation files:
|
|
|
|
```powershell
|
|
git add -- utils/ApiClient.js tests/api-client.test.js
|
|
git commit -m "fix: clear token after registration"
|
|
```
|