138 lines
6.4 KiB
Plaintext
138 lines
6.4 KiB
Plaintext
|
|
# =============================================================
|
||
|
|
# OxiCloud — email-only registration (PR 18)
|
||
|
|
# =============================================================
|
||
|
|
# PR 18 makes `password` (and `username`) optional in
|
||
|
|
# `POST /api/auth/register`. Email-only signup:
|
||
|
|
# - returns a uniform 200 message (no JWT, no UserDto)
|
||
|
|
# - mints a welcome magic-link mailed to `email`
|
||
|
|
# - redemption lands the new internal user on `/#/files`
|
||
|
|
# (not `/#/sharedwithme`, which is for externals)
|
||
|
|
#
|
||
|
|
# Requires `OXICLOUD_SMTP_MOCK=true` (set in tests/common/server.env).
|
||
|
|
# =============================================================
|
||
|
|
|
||
|
|
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
# Step 1 — admin login (cleanup ops at the end need her token).
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
POST {{base_url}}/api/auth/login
|
||
|
|
Content-Type: application/json
|
||
|
|
{ "username": "{{username}}", "password": "{{password}}" }
|
||
|
|
|
||
|
|
HTTP 200
|
||
|
|
[Captures]
|
||
|
|
alice_token: jsonpath "$.access_token"
|
||
|
|
|
||
|
|
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
# Step 2 — Classic registration (with password) still works.
|
||
|
|
# Returns 201 + UserDto (existing behaviour, unchanged).
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
POST {{base_url}}/api/auth/register
|
||
|
|
Content-Type: application/json
|
||
|
|
{
|
||
|
|
"username": "charlie",
|
||
|
|
"email": "charlie@example.com",
|
||
|
|
"password": "TestPassword1!"
|
||
|
|
}
|
||
|
|
|
||
|
|
HTTP 201
|
||
|
|
[Asserts]
|
||
|
|
jsonpath "$.username" == "charlie"
|
||
|
|
jsonpath "$.email" == "charlie@example.com"
|
||
|
|
jsonpath "$.is_external" == false
|
||
|
|
[Captures]
|
||
|
|
charlie_user_id: jsonpath "$.id"
|
||
|
|
|
||
|
|
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
# Step 3 — Email-only registration. No username, no password.
|
||
|
|
# Returns 200 + uniform message; welcome magic-link
|
||
|
|
# is captured by the MockEmailSender.
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
POST {{base_url}}/api/auth/register
|
||
|
|
Content-Type: application/json
|
||
|
|
{
|
||
|
|
"email": "pr18-emailonly@example.com"
|
||
|
|
}
|
||
|
|
|
||
|
|
HTTP 200
|
||
|
|
[Asserts]
|
||
|
|
jsonpath "$.message" contains "sign-in link"
|
||
|
|
|
||
|
|
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
# Step 4 — Capture the welcome mail + extract the magic-link.
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
GET {{base_url}}/api/admin/smtp/test/captured?to=pr18-emailonly@example.com
|
||
|
|
Authorization: Bearer {{alice_token}}
|
||
|
|
|
||
|
|
HTTP 200
|
||
|
|
[Asserts]
|
||
|
|
jsonpath "$.to" == "pr18-emailonly@example.com"
|
||
|
|
jsonpath "$.text_body" matches "/magic/v1/[A-Za-z0-9_-]+"
|
||
|
|
[Captures]
|
||
|
|
pr18_magic_url: jsonpath "$.text_body" regex "(https?://[^\\s]+/magic/v1/[A-Za-z0-9_-]+)"
|
||
|
|
|
||
|
|
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
# Step 5 — Redeem the welcome link. Internal user with no
|
||
|
|
# resource target → lands on `/#/files` (NOT
|
||
|
|
# `/#/sharedwithme`, which is the external-user
|
||
|
|
# landing).
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
GET {{pr18_magic_url}}
|
||
|
|
|
||
|
|
HTTP 302
|
||
|
|
[Asserts]
|
||
|
|
header "Location" == "/#/files"
|
||
|
|
[Captures]
|
||
|
|
pr18_access_token: cookie "oxicloud_access"
|
||
|
|
|
||
|
|
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
# Step 6 — The new user can read their own profile. After PR 18
|
||
|
|
# the username field is omitted (no handle claimed yet),
|
||
|
|
# and `is_external` is false (they're an internal user
|
||
|
|
# who signed up directly, not via invitation).
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
GET {{base_url}}/api/auth/me
|
||
|
|
Authorization: Bearer {{pr18_access_token}}
|
||
|
|
|
||
|
|
HTTP 200
|
||
|
|
[Asserts]
|
||
|
|
jsonpath "$.email" == "pr18-emailonly@example.com"
|
||
|
|
jsonpath "$.is_external" == false
|
||
|
|
jsonpath "$.username" not exists
|
||
|
|
[Captures]
|
||
|
|
pr18_user_id: jsonpath "$.id"
|
||
|
|
|
||
|
|
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
# Step 7 — Dave can request another magic-link (he has no
|
||
|
|
# password configured → eligible). Anti-enumeration
|
||
|
|
# 200 either way.
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
POST {{base_url}}/api/auth/magic-link/send
|
||
|
|
Content-Type: application/json
|
||
|
|
{ "email": "pr18-emailonly@example.com" }
|
||
|
|
|
||
|
|
HTTP 200
|
||
|
|
[Asserts]
|
||
|
|
jsonpath "$.message" contains "sign-in link"
|
||
|
|
|
||
|
|
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
# Cleanup — admin deletes charlie + dave so the DB-clean sweep
|
||
|
|
# at run.sh end sees no stragglers.
|
||
|
|
# ─────────────────────────────────────────────────────────────
|
||
|
|
DELETE {{base_url}}/api/admin/users/{{charlie_user_id}}
|
||
|
|
Authorization: Bearer {{alice_token}}
|
||
|
|
|
||
|
|
HTTP *
|
||
|
|
|
||
|
|
DELETE {{base_url}}/api/admin/users/{{pr18_user_id}}
|
||
|
|
Authorization: Bearer {{alice_token}}
|
||
|
|
|
||
|
|
HTTP *
|