Replace Meshkee password when linking an existing account to a new site.
Cross-site register now updates the password to the signup value and documents passwordUpdated for storefronts. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
b0d4916138
commit
e027cc96ea
@@ -253,7 +253,7 @@ All routes are prefixed with `/api/v1`.
|
|||||||
|
|
||||||
| Method | Path | Description |
|
| Method | Path | Description |
|
||||||
|--------|------|-------------|
|
|--------|------|-------------|
|
||||||
| POST | `/auth/register` | Customer registration by domain |
|
| POST | `/auth/register` | Customer registration by domain. Cross-site link updates Meshkee password to the new signup password (`passwordUpdated`). |
|
||||||
| POST | `/auth/login` | Cell + password |
|
| POST | `/auth/login` | Cell + password |
|
||||||
| POST | `/auth/login-otp` | Passwordless login with SMS OTP |
|
| POST | `/auth/login-otp` | Passwordless login with SMS OTP |
|
||||||
| POST | `/auth/reset-password` | Reset password with SMS OTP |
|
| POST | `/auth/reset-password` | Reset password with SMS OTP |
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ You are building a **Meshkee business website (storefront)**. You must use the M
|
|||||||
1. Resolve tenant first: `GET /tenants/<WEBSITE_DOMAIN>` → save `businessId` from `id`.
|
1. Resolve tenant first: `GET /tenants/<WEBSITE_DOMAIN>` → save `businessId` from `id`.
|
||||||
2. All public content uses `/tenants/<WEBSITE_DOMAIN>/...` (no auth).
|
2. All public content uses `/tenants/<WEBSITE_DOMAIN>/...` (no auth).
|
||||||
3. Cart, orders, favorites use `/businesses/<businessId>/...` with `Authorization: Bearer <accessToken>`.
|
3. Cart, orders, favorites use `/businesses/<businessId>/...` with `Authorization: Bearer <accessToken>`.
|
||||||
4. Customer register body must include `"domain": "<WEBSITE_DOMAIN>"`. If the cell already exists on another Meshkee site and the password differs, API returns `409` with `CELL_EXISTS_OTHER_SITE:...`. Retry register with `"acknowledgeExistingAccount": true` to link that account (password/profile stay unchanged), then complete SMS OTP.
|
4. Customer register body must include `"domain": "<WEBSITE_DOMAIN>"`. If the cell already exists on another Meshkee site and the password differs, API returns `409` with `CELL_EXISTS_OTHER_SITE:...`. Retry register with `"acknowledgeExistingAccount": true` to link that account (profile unchanged; **password is replaced** with the new signup password), then complete SMS OTP.
|
||||||
5. Cell numbers are E.164 (`+98912...`).
|
5. Cell numbers are E.164 (`+98912...`).
|
||||||
6. Do not call dashboard/CMS routes (`/businesses/.../products` write APIs, media upload, domain-admin, etc.).
|
6. Do not call dashboard/CMS routes (`/businesses/.../products` write APIs, media upload, domain-admin, etc.).
|
||||||
7. **Partner SMS** (`POST /public/sms/send`) is for external partner backends with an issued `X-Api-Key` only — not for normal storefront UI. See https://api.meshkee.com/docs/website/SMS.md
|
7. **Partner SMS** (`POST /public/sms/send`) is for external partner backends with an issued `X-Api-Key` only — not for normal storefront UI. See https://api.meshkee.com/docs/website/SMS.md
|
||||||
|
|||||||
@@ -1557,7 +1557,7 @@
|
|||||||
},
|
},
|
||||||
"acknowledgeExistingAccount": {
|
"acknowledgeExistingAccount": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "If true, link an existing Meshkee account from another website without matching its password. Existing password and profile stay unchanged."
|
"description": "If true, link an existing Meshkee account from another website without matching its password. Profile stays unchanged; password is replaced with the new signup password. Response may include passwordUpdated: true."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,10 +97,19 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const linkedExistingAccount = Boolean(existingUser);
|
||||||
|
|
||||||
const user = await this.prisma.$transaction(async (tx) => {
|
const user = await this.prisma.$transaction(async (tx) => {
|
||||||
const account =
|
let account = existingUser;
|
||||||
existingUser ??
|
|
||||||
(await tx.user.create({
|
if (account) {
|
||||||
|
// Cross-site join: replace Meshkee password with the one entered on this signup.
|
||||||
|
account = await tx.user.update({
|
||||||
|
where: { id: account.id },
|
||||||
|
data: { passwordHash },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
account = await tx.user.create({
|
||||||
data: {
|
data: {
|
||||||
cellNumber: dto.cellNumber,
|
cellNumber: dto.cellNumber,
|
||||||
passwordHash,
|
passwordHash,
|
||||||
@@ -109,7 +118,8 @@ export class AuthService {
|
|||||||
lastName: dto.lastName,
|
lastName: dto.lastName,
|
||||||
cellVerifiedAt: smsEnabled ? null : new Date(),
|
cellVerifiedAt: smsEnabled ? null : new Date(),
|
||||||
},
|
},
|
||||||
}));
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await tx.businessCustomer.create({
|
await tx.businessCustomer.create({
|
||||||
data: {
|
data: {
|
||||||
@@ -143,10 +153,15 @@ export class AuthService {
|
|||||||
const tokens = await this.issueTokens(authUser);
|
const tokens = await this.issueTokens(authUser);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: smsEnabled
|
message: linkedExistingAccount
|
||||||
|
? smsEnabled
|
||||||
|
? 'Joined this website. Your Meshkee password was updated to the one you just entered. Please verify your cell number with OTP.'
|
||||||
|
: 'Joined this website. Your Meshkee password was updated to the one you just entered.'
|
||||||
|
: smsEnabled
|
||||||
? 'Registration successful. Please verify your cell number with OTP.'
|
? 'Registration successful. Please verify your cell number with OTP.'
|
||||||
: 'Registration successful. SMS verification is disabled — account auto-verified.',
|
: 'Registration successful. SMS verification is disabled — account auto-verified.',
|
||||||
smsEnabled,
|
smsEnabled,
|
||||||
|
passwordUpdated: linkedExistingAccount,
|
||||||
user: this.serializeUser(authUser),
|
user: this.serializeUser(authUser),
|
||||||
registeredBusiness: {
|
registeredBusiness: {
|
||||||
id: business.id,
|
id: business.id,
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ export class RegisterDto {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* When true, link an existing Meshkee account (other websites) to this tenant
|
* When true, link an existing Meshkee account (other websites) to this tenant
|
||||||
* without requiring the existing password. Existing password and profile stay unchanged.
|
* without requiring the existing password. Profile stays unchanged; the password
|
||||||
|
* is replaced with the one submitted in this registration.
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ You are building a **Meshkee business website (storefront)**. You must use the M
|
|||||||
1. Resolve tenant first: `GET /tenants/<WEBSITE_DOMAIN>` → save `businessId` from `id`.
|
1. Resolve tenant first: `GET /tenants/<WEBSITE_DOMAIN>` → save `businessId` from `id`.
|
||||||
2. All public content uses `/tenants/<WEBSITE_DOMAIN>/...` (no auth).
|
2. All public content uses `/tenants/<WEBSITE_DOMAIN>/...` (no auth).
|
||||||
3. Cart, orders, favorites use `/businesses/<businessId>/...` with `Authorization: Bearer <accessToken>`.
|
3. Cart, orders, favorites use `/businesses/<businessId>/...` with `Authorization: Bearer <accessToken>`.
|
||||||
4. Customer register body must include `"domain": "<WEBSITE_DOMAIN>"`. If the cell already exists on another Meshkee site and the password differs, API returns `409` with `CELL_EXISTS_OTHER_SITE:...`. Retry register with `"acknowledgeExistingAccount": true` to link that account (password/profile stay unchanged), then complete SMS OTP.
|
4. Customer register body must include `"domain": "<WEBSITE_DOMAIN>"`. If the cell already exists on another Meshkee site and the password differs, API returns `409` with `CELL_EXISTS_OTHER_SITE:...`. Retry register with `"acknowledgeExistingAccount": true` to link that account (profile unchanged; **password is replaced** with the new signup password), then complete SMS OTP.
|
||||||
5. Cell numbers are E.164 (`+98912...`).
|
5. Cell numbers are E.164 (`+98912...`).
|
||||||
6. Do not call dashboard/CMS routes (`/businesses/.../products` write APIs, media upload, domain-admin, etc.).
|
6. Do not call dashboard/CMS routes (`/businesses/.../products` write APIs, media upload, domain-admin, etc.).
|
||||||
7. **Partner SMS** (`POST /public/sms/send`) is for external partner backends with an issued `X-Api-Key` only — not for normal storefront UI. See https://api.meshkee.com/docs/website/SMS.md
|
7. **Partner SMS** (`POST /public/sms/send`) is for external partner backends with an issued `X-Api-Key` only — not for normal storefront UI. See https://api.meshkee.com/docs/website/SMS.md
|
||||||
|
|||||||
@@ -1557,7 +1557,7 @@
|
|||||||
},
|
},
|
||||||
"acknowledgeExistingAccount": {
|
"acknowledgeExistingAccount": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "If true, link an existing Meshkee account from another website without matching its password. Existing password and profile stay unchanged."
|
"description": "If true, link an existing Meshkee account from another website without matching its password. Profile stays unchanged; password is replaced with the new signup password. Response may include passwordUpdated: true."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user