- Rename the filesystem browse route from /api/asset/fs-browse to /api/asset/directory (controller route, client URL, REST tests, and service log label). - Remove the old /api/asset/browse endpoint and its BrowseAssets/GetDirectoryNames repository code, plus the client BrowseAsync method. Repoint AlbumAssetPicker's admin/curator folder browse to the /directory endpoint. - Drop the now-unused pg_catalog.split_part DbFunction mapping. - Refresh .env GIT_VERSION.
2284 lines
65 KiB
HTTP
2284 lines
65 KiB
HTTP
@WepApiTest_HostAddress = http://localhost:5162
|
||
|
||
# =============================================================================
|
||
# SETUP — Create three users with distinct roles
|
||
# =============================================================================
|
||
|
||
### 1 Login as seeded admin
|
||
POST {{WepApiTest_HostAddress}}/api/auth/login
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"identifier": "admin",
|
||
"password": "admin"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("admin_token", jsonPath(response.body, "$.token"));
|
||
client.global.set("admin_id", jsonPath(response.body, "$.userId"));
|
||
client.test("Login as seeded admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 2 Create curator user (admin only)
|
||
< {%
|
||
client.global.set("curatorName", $random.alphabetic(15));
|
||
client.global.set("curatorPwd", "test" + $random.alphabetic(5));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/user
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"username": "{{curatorName}}",
|
||
"email": "{{curatorName}}@redcode.com",
|
||
"password": "{{curatorPwd}}",
|
||
"accessLevel": 2
|
||
}
|
||
|
||
> {%
|
||
client.global.set("curator_id", jsonPath(response.body, "$"));
|
||
client.test("Create curator user as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 3 Login as curator
|
||
POST {{WepApiTest_HostAddress}}/api/auth/login
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"identifier": "{{curatorName}}",
|
||
"password": "{{curatorPwd}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("curator_token", jsonPath(response.body, "$.token"));
|
||
client.test("Login as curator", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 3.5 Enable registration for testing
|
||
POST {{WepApiTest_HostAddress}}/api/settings
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "User Registration Enabled",
|
||
"value": "true",
|
||
"description": "Sets if user registration is enabled or not.",
|
||
"type": 2,
|
||
"displayType": 5
|
||
}
|
||
|
||
> {%
|
||
client.test("Enable registration", function () {
|
||
client.assert(response.status === 200);
|
||
});
|
||
%}
|
||
|
||
### 4 Register regular user
|
||
< {%
|
||
client.global.set("userName", $random.alphabetic(15));
|
||
client.global.set("userEmail", $random.alphabetic(5) + "@redcode.com");
|
||
client.global.set("userPwd", "test" + $random.alphabetic(5));
|
||
%}
|
||
|
||
POST {{WepApiTest_HostAddress}}/api/auth/register
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"username": "{{userName}}",
|
||
"email": "{{userEmail}}",
|
||
"password": "{{userPwd}}"
|
||
}
|
||
|
||
> {%
|
||
client.test("Register regular user", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 5 Login as regular user
|
||
POST {{WepApiTest_HostAddress}}/api/auth/login
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"identifier": "{{userName}}",
|
||
"password": "{{userPwd}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("user_token", jsonPath(response.body, "$.token"));
|
||
client.global.set("user_refresh", jsonPath(response.body, "$.refreshToken"));
|
||
client.global.set("user_id", jsonPath(response.body, "$.userId"));
|
||
client.test("Login as regular user", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
# =============================================================================
|
||
# AUTH TESTS
|
||
# =============================================================================
|
||
|
||
### 6 Wrong auth route should 404
|
||
POST {{WepApiTest_HostAddress}}/api/auth
|
||
Content-Type: application/json
|
||
|
||
{}
|
||
|
||
> {%
|
||
client.test("Wrong auth route returns 404", function () {
|
||
client.assert(response.status === 404)
|
||
});
|
||
%}
|
||
|
||
### 7 Login with valid token (re-authentication)
|
||
POST {{WepApiTest_HostAddress}}/api/auth/login
|
||
Authorization: Bearer {{user_token}}
|
||
Content-Type: application/json
|
||
|
||
{"identifier": "{{userName}}", "password": "{{userPwd}}"}
|
||
|
||
> {%
|
||
client.test("Re-authenticate with valid token", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 8 Logout
|
||
POST {{WepApiTest_HostAddress}}/api/auth/logout
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("Logout", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 9 Re-login user after logout
|
||
POST {{WepApiTest_HostAddress}}/api/auth/login
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"identifier": "{{userName}}",
|
||
"password": "{{userPwd}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("user_token", jsonPath(response.body, "$.token"));
|
||
client.global.set("user_refresh", jsonPath(response.body, "$.refreshToken"));
|
||
client.global.set("user_id", jsonPath(response.body, "$.userId"));
|
||
client.test("Re-login user after logout", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 10 Refresh token with empty body (should be 400)
|
||
POST {{WepApiTest_HostAddress}}/api/auth/refresh
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"userId": "",
|
||
"refreshToken": ""
|
||
}
|
||
|
||
> {%
|
||
client.test("Refresh token with empty body returns 400", function () {
|
||
client.assert(response.status === 400)
|
||
});
|
||
%}
|
||
|
||
### 11 Refresh token with valid data
|
||
POST {{WepApiTest_HostAddress}}/api/auth/refresh
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"userId": "{{user_id}}",
|
||
"refreshToken": "{{user_refresh}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("user_token", jsonPath(response.body, "$.token"));
|
||
client.test("Refresh token with valid data", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$.token") != null)
|
||
});
|
||
%}
|
||
|
||
# =============================================================================
|
||
# USER CRUD TESTS
|
||
# =============================================================================
|
||
|
||
### 12 Get all users as admin (should succeed)
|
||
GET {{WepApiTest_HostAddress}}/api/user?page=0&pageSize=5
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Get all users as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 13 Get all users as regular user (should 403)
|
||
GET {{WepApiTest_HostAddress}}/api/user
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("Get all users as regular user should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 14 Get all users as curator (should succeed — curators now have access)
|
||
GET {{WepApiTest_HostAddress}}/api/user?page=0&pageSize=5
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("Get all users as curator", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 15 Create user as regular user (should 403)
|
||
< {%
|
||
client.global.set("userCreateAttempt", $random.alphabetic(10));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/user
|
||
Authorization: Bearer {{user_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"username": "{{userCreateAttempt}}",
|
||
"email": "{{userCreateAttempt}}@redcode.com",
|
||
"password": "qwertyu",
|
||
"accessLevel": 0
|
||
}
|
||
|
||
> {%
|
||
client.test("Create user as regular user should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 16 Create user as curator (should 403)
|
||
< {%
|
||
client.global.set("curatorCreateAttempt", $random.alphabetic(10));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/user
|
||
Authorization: Bearer {{curator_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"username": "{{curatorCreateAttempt}}",
|
||
"email": "{{curatorCreateAttempt}}@redcode.com",
|
||
"password": "test1234",
|
||
"accessLevel": 0
|
||
}
|
||
|
||
> {%
|
||
client.test("Create user as curator should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 17 Get own user profile as regular user
|
||
GET {{WepApiTest_HostAddress}}/api/user/{{user_id}}
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("Get own profile as regular user", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 18 Update own profile as regular user
|
||
POST {{WepApiTest_HostAddress}}/api/user/update
|
||
Authorization: Bearer {{user_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"id": "{{user_id}}",
|
||
"username": "{{userName}}"
|
||
}
|
||
|
||
> {%
|
||
client.test("Update own profile as regular user", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
> {%
|
||
client.test("Update own profile as regular user", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
# =============================================================================
|
||
# PERSON TESTS
|
||
# =============================================================================
|
||
|
||
### 19 Create person as regular user (should 403)
|
||
PUT {{WepApiTest_HostAddress}}/api/person
|
||
Authorization: Bearer {{user_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "hacker_create"
|
||
}
|
||
|
||
> {%
|
||
client.test("Create person as regular user should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 20 Create person as curator (should succeed)
|
||
< {%
|
||
client.global.set("curatorPerson", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/person
|
||
Authorization: Bearer {{curator_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{curatorPerson}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("curatorPersonId", jsonPath(response.body, "$"));
|
||
client.test("Create person as curator", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 21 Delete person as curator (cleanup)
|
||
DELETE {{WepApiTest_HostAddress}}/api/person/{{curatorPersonId}}
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("Delete person as curator", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 22 Create test person as admin
|
||
PUT {{WepApiTest_HostAddress}}/api/person
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "Test Cosplayer Created"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("testPersonId", jsonPath(response.body, "$"));
|
||
client.test("Create test person as admin", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$") != null)
|
||
});
|
||
%}
|
||
|
||
### 23 Get all people as anonymous (should 401 — controller requires auth)
|
||
GET {{WepApiTest_HostAddress}}/api/person?page=0&pageSize=5
|
||
|
||
> {%
|
||
client.test("Get all people as anonymous should 401", function () {
|
||
client.assert(response.status === 401)
|
||
});
|
||
%}
|
||
|
||
### 24 Get all people as regular user
|
||
GET {{WepApiTest_HostAddress}}/api/person?page=0&pageSize=5
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("Get all people as regular user", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 25 Get all people as curator
|
||
GET {{WepApiTest_HostAddress}}/api/person?page=0&pageSize=5
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("Get all people as curator", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 26 Get all people as admin
|
||
GET {{WepApiTest_HostAddress}}/api/person?page=0&pageSize=5
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Get all people as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 27 Get test person by ID as admin
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{testPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Get test person by ID as admin", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$.name") === "Test Cosplayer Created")
|
||
});
|
||
%}
|
||
|
||
### 28 Get non-existent person (should 404)
|
||
GET {{WepApiTest_HostAddress}}/api/person/00000000-0000-0000-0000-000000000000
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Get non-existent person", function () {
|
||
client.assert(response.status === 404)
|
||
});
|
||
%}
|
||
|
||
### 29 Update person as regular user (should 403)
|
||
POST {{WepApiTest_HostAddress}}/api/person/{{testPersonId}}
|
||
Authorization: Bearer {{user_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "hacker_attempt"
|
||
}
|
||
|
||
> {%
|
||
client.test("Update person as regular user should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 30 Update person as curator (should succeed)
|
||
POST {{WepApiTest_HostAddress}}/api/person/{{testPersonId}}
|
||
Authorization: Bearer {{curator_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "Updated by curator"
|
||
}
|
||
|
||
> {%
|
||
client.test("Update person as curator", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 31 Update person as admin
|
||
POST {{WepApiTest_HostAddress}}/api/person/{{testPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "Updated via API Test"
|
||
}
|
||
|
||
> {%
|
||
client.test("Update person as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 32 Verify person name update
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{testPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Verify person name update", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$.name") === "Updated via API Test")
|
||
});
|
||
%}
|
||
|
||
### 33 Update non-existent person (should 404)
|
||
POST {{WepApiTest_HostAddress}}/api/person/00000000-0000-0000-0000-000000000000
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "ghost"
|
||
}
|
||
|
||
> {%
|
||
client.test("Update non-existent person", function () {
|
||
client.assert(response.status === 404)
|
||
});
|
||
%}
|
||
|
||
### 34 Delete person as regular user (should 403)
|
||
DELETE {{WepApiTest_HostAddress}}/api/person/{{testPersonId}}
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("Delete person as regular user should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 35 Bulk update person as regular user (should 403)
|
||
POST {{WepApiTest_HostAddress}}/api/person
|
||
Authorization: Bearer {{user_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"ids": ["{{testPersonId}}"],
|
||
"data": { "name": "hacker_bulk" }
|
||
}
|
||
|
||
> {%
|
||
client.test("Bulk update person as regular user should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 36 Bulk update person as admin
|
||
POST {{WepApiTest_HostAddress}}/api/person
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"ids": ["{{testPersonId}}"],
|
||
"data": { "name": "Bulk Updated Person" }
|
||
}
|
||
|
||
> {%
|
||
client.test("Bulk update person as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 37 Bulk delete person as regular user (should 403)
|
||
DELETE {{WepApiTest_HostAddress}}/api/person
|
||
Authorization: Bearer {{user_token}}
|
||
Content-Type: application/json
|
||
|
||
["{{testPersonId}}"]
|
||
|
||
> {%
|
||
client.test("Bulk delete person as regular user should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
# =============================================================================
|
||
# ALBUM TESTS
|
||
# =============================================================================
|
||
|
||
### 38 Create album as regular user (should 403)
|
||
< {%
|
||
client.global.set("albumHack", $random.alphabetic(10));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/album
|
||
Authorization: Bearer {{user_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{albumHack}}"
|
||
}
|
||
|
||
> {%
|
||
client.test("Create album as regular user should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 39 Create album as curator (should succeed)
|
||
< {%
|
||
client.global.set("curatorAlbum", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/album
|
||
Authorization: Bearer {{curator_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{curatorAlbum}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("curatorAlbumId", jsonPath(response.body, "$"));
|
||
client.test("Create album as curator", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 40 Delete album as curator (cleanup)
|
||
DELETE {{WepApiTest_HostAddress}}/api/album/{{curatorAlbumId}}
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("Delete album as curator", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 41 Create test album as admin
|
||
PUT {{WepApiTest_HostAddress}}/api/album
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "Test Album for E2E"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("testAlbumId", jsonPath(response.body, "$"));
|
||
client.test("Create test album as admin", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$") != null)
|
||
});
|
||
%}
|
||
|
||
### 42 Assign test album to test person
|
||
POST {{WepApiTest_HostAddress}}/api/album/{{testAlbumId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"person": "{{testPersonId}}"
|
||
}
|
||
|
||
> {%
|
||
client.test("Assign album to person", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 43 Update album without removePerson field (should keep person link)
|
||
POST {{WepApiTest_HostAddress}}/api/album/{{testAlbumId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "Test Album Updated"
|
||
}
|
||
|
||
> {%
|
||
client.test("Update album without removePerson", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 44 Remove person assignment from album
|
||
POST {{WepApiTest_HostAddress}}/api/album/{{testAlbumId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"removePerson": true
|
||
}
|
||
|
||
> {%
|
||
client.test("Unlink person from album", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 45 Get all albums as anonymous (should 401 — controller requires auth)
|
||
GET {{WepApiTest_HostAddress}}/api/album?page=0&pageSize=5
|
||
|
||
> {%
|
||
client.test("Get all albums as anonymous should 401", function () {
|
||
client.assert(response.status === 401)
|
||
});
|
||
%}
|
||
|
||
### 46 Get all albums as regular user
|
||
GET {{WepApiTest_HostAddress}}/api/album?page=0&pageSize=5
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("Get all albums as regular user", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 47 Get all albums as curator
|
||
GET {{WepApiTest_HostAddress}}/api/album?page=0&pageSize=5
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("Get all albums as curator", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 48 Get all albums as admin
|
||
GET {{WepApiTest_HostAddress}}/api/album?page=0&pageSize=5
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Get all albums as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 49 Search albums as admin
|
||
GET {{WepApiTest_HostAddress}}/api/album?search=Test&pageSize=5
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Search albums as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 50 Get album by ID as admin
|
||
GET {{WepApiTest_HostAddress}}/api/album/{{testAlbumId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Get album by ID as admin", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$.id") != null)
|
||
});
|
||
%}
|
||
|
||
### 51 Get non-existent album (should 404)
|
||
GET {{WepApiTest_HostAddress}}/api/album/00000000-0000-0000-0000-000000000000
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Get non-existent album", function () {
|
||
client.assert(response.status === 404)
|
||
});
|
||
%}
|
||
|
||
### 52 Delete test album as admin
|
||
DELETE {{WepApiTest_HostAddress}}/api/album/{{testAlbumId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Delete test album", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 53 Create bulk test album A
|
||
< {%
|
||
client.global.set("bulkAlbumA", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/album
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "bulk-{{bulkAlbumA}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("bulkAlbumAId", jsonPath(response.body, "$"));
|
||
client.test("Create bulk test album A", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$") != null)
|
||
});
|
||
%}
|
||
|
||
### 54 Create bulk test album B
|
||
< {%
|
||
client.global.set("bulkAlbumB", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/album
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "bulk-{{bulkAlbumB}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("bulkAlbumBId", jsonPath(response.body, "$"));
|
||
client.test("Create bulk test album B", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$") != null)
|
||
});
|
||
%}
|
||
|
||
### 55 Bulk assign both albums to test person
|
||
POST {{WepApiTest_HostAddress}}/api/album
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"ids": ["{{bulkAlbumAId}}", "{{bulkAlbumBId}}"],
|
||
"data": { "person": "{{testPersonId}}" }
|
||
}
|
||
|
||
> {%
|
||
client.test("Bulk assign albums to person", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 56 Verify bulk assignment — album A
|
||
GET {{WepApiTest_HostAddress}}/api/album/{{bulkAlbumAId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Verify bulk assignment — album A", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$.person") !== undefined, "person field should exist")
|
||
client.assert(jsonPath(response.body, "$.person") !== null, "person should be assigned")
|
||
});
|
||
%}
|
||
|
||
### 57 Verify bulk assignment — album B
|
||
GET {{WepApiTest_HostAddress}}/api/album/{{bulkAlbumBId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Verify bulk assignment — album B", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$.person") !== undefined, "person field should exist")
|
||
client.assert(jsonPath(response.body, "$.person") !== null, "person should be assigned")
|
||
});
|
||
%}
|
||
|
||
### 58 Delete bulk test album A
|
||
DELETE {{WepApiTest_HostAddress}}/api/album/{{bulkAlbumAId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Delete bulk test album A", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 59 Delete bulk test album B
|
||
DELETE {{WepApiTest_HostAddress}}/api/album/{{bulkAlbumBId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Delete bulk test album B", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
# =============================================================================
|
||
# TAG TESTS
|
||
# =============================================================================
|
||
|
||
### 60 Search tags as admin
|
||
GET {{WepApiTest_HostAddress}}/api/tag?search=test&pageSize=5
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Search tags as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 61 Create tag as regular user (should 403)
|
||
PUT {{WepApiTest_HostAddress}}/api/tag
|
||
Authorization: Bearer {{user_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "hacker-tag"
|
||
}
|
||
|
||
> {%
|
||
client.test("Create tag as regular user should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 62 Create tag as curator (should succeed)
|
||
< {%
|
||
client.global.set("e2eTag", $random.alphabetic(10));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/tag
|
||
Authorization: Bearer {{curator_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "e2e-{{e2eTag}}"
|
||
}
|
||
|
||
> {%
|
||
client.test("Create tag as curator", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
# =============================================================================
|
||
# ASSET TESTS
|
||
# =============================================================================
|
||
|
||
### 63 Search assets as regular user
|
||
GET {{WepApiTest_HostAddress}}/api/asset?page=0&pageSize=5
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("Search assets as regular user", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 64 Search assets as anonymous
|
||
GET {{WepApiTest_HostAddress}}/api/asset?page=0&pageSize=5
|
||
|
||
> {%
|
||
client.test("Search assets as anonymous", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
# =============================================================================
|
||
# MAINTENANCE TESTS — broken report, retry, filesystem browse, animated job
|
||
# =============================================================================
|
||
|
||
### 64.1 Get broken assets as admin
|
||
GET {{WepApiTest_HostAddress}}/api/asset/broken?page=0&pageSize=5
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Get broken assets as admin", function () {
|
||
client.assert(response.status === 200);
|
||
client.assert(response.headers.get("X-Total-Count") !== null, "X-Total-Count header should be present");
|
||
});
|
||
%}
|
||
|
||
### 64.2 Get broken assets as regular user (should 403)
|
||
GET {{WepApiTest_HostAddress}}/api/asset/broken?page=0&pageSize=5
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("Get broken assets as regular user (should 403)", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 64.3 Get broken assets with invalid pagination (should 400)
|
||
GET {{WepApiTest_HostAddress}}/api/asset/broken?page=-1&pageSize=5
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Get broken assets with invalid pagination (should 400)", function () {
|
||
client.assert(response.status === 400)
|
||
});
|
||
%}
|
||
|
||
### 64.4 Retry broken assets with empty list (should 400)
|
||
POST {{WepApiTest_HostAddress}}/api/asset/broken/retry
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
[]
|
||
|
||
> {%
|
||
client.test("Retry broken assets with empty list (should 400)", function () {
|
||
client.assert(response.status === 400)
|
||
});
|
||
%}
|
||
|
||
### 64.5 Retry broken assets as regular user (should 403)
|
||
POST {{WepApiTest_HostAddress}}/api/asset/broken/retry
|
||
Authorization: Bearer {{user_token}}
|
||
Content-Type: application/json
|
||
|
||
["00000000-0000-0000-0000-000000000001"]
|
||
|
||
> {%
|
||
client.test("Retry broken assets as regular user (should 403)", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 64.6 Filesystem browse non-existent folder (should 404)
|
||
GET {{WepApiTest_HostAddress}}/api/asset/directory?folderId=00000000-0000-0000-0000-000000000001&path=&page=0&pageSize=5
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Filesystem browse non-existent folder (should 404)", function () {
|
||
client.assert(response.status === 404)
|
||
});
|
||
%}
|
||
|
||
### 64.7 Filesystem browse invalid pagination (should 400)
|
||
GET {{WepApiTest_HostAddress}}/api/asset/directory?folderId=00000000-0000-0000-0000-000000000001&path=&page=0&pageSize=0
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Filesystem browse invalid pagination (should 400)", function () {
|
||
client.assert(response.status === 400)
|
||
});
|
||
%}
|
||
|
||
### 64.8 Filesystem browse as regular user (should 403)
|
||
GET {{WepApiTest_HostAddress}}/api/asset/directory?folderId=00000000-0000-0000-0000-000000000001&path=&page=0&pageSize=5
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("Filesystem browse as regular user (should 403)", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 64.9 Enqueue animated conversion job as admin
|
||
PUT {{WepApiTest_HostAddress}}/api/jobs
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{ "jobType": "AnimatedConversion", "parameters": [] }
|
||
|
||
> {%
|
||
client.test("Enqueue animated conversion job as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 64.10 Enqueue animated conversion job as regular user (should 403)
|
||
PUT {{WepApiTest_HostAddress}}/api/jobs
|
||
Authorization: Bearer {{user_token}}
|
||
Content-Type: application/json
|
||
|
||
{ "jobType": "AnimatedConversion", "parameters": [] }
|
||
|
||
> {%
|
||
client.test("Enqueue animated conversion job as regular user (should 403)", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
# =============================================================================
|
||
# STATS TESTS
|
||
# =============================================================================
|
||
|
||
### 65 Get stats as admin
|
||
GET {{WepApiTest_HostAddress}}/api/stats
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Get stats as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 66 Get stats as curator
|
||
GET {{WepApiTest_HostAddress}}/api/stats
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("Get stats as curator", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 67 Get stats as regular user (should 403)
|
||
GET {{WepApiTest_HostAddress}}/api/stats
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("Get stats as regular user should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
# =============================================================================
|
||
# SETTINGS TESTS
|
||
# =============================================================================
|
||
|
||
### 68 Get settings as admin
|
||
GET {{WepApiTest_HostAddress}}/api/settings
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Get settings as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 69 Get settings as curator (should 403)
|
||
GET {{WepApiTest_HostAddress}}/api/settings
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("Get settings as curator should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 70 Get settings as regular user (should 403)
|
||
GET {{WepApiTest_HostAddress}}/api/settings
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("Get settings as regular user should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
# =============================================================================
|
||
# DATA VISIBILITY TESTS
|
||
# =============================================================================
|
||
# These tests verify that each access level only sees the data they are
|
||
# authorized to see. All test data needed is created inline so the tests
|
||
# are self-contained regardless of database state.
|
||
# =============================================================================
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Setup: Create maintainer relationship for visibility tests
|
||
# ---------------------------------------------------------------------------
|
||
|
||
### 71 Setup: Assign test user as maintainer of test person
|
||
POST {{WepApiTest_HostAddress}}/api/person/{{testPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "Bulk Updated Person",
|
||
"maintainerUserIds": ["{{user_id}}"]
|
||
}
|
||
|
||
> {%
|
||
client.test("Assign maintainer to test person", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# User data visibility (tests 65–68)
|
||
# ---------------------------------------------------------------------------
|
||
|
||
### 72 Regular user: Get own profile — Email visible, maintainedPersonIds visible (self-view)
|
||
GET {{WepApiTest_HostAddress}}/api/user/{{user_id}}
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("User sees own email (self-view)", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$.email") != null, "Self email should be visible")
|
||
});
|
||
client.test("User sees own maintainedPersonIds (self-view)", function () {
|
||
client.assert(jsonPath(response.body, "$.maintainedPersonIds") != null, "Self maintainedPersonIds should be visible")
|
||
var ids = jsonPath(response.body, "$.maintainedPersonIds");
|
||
client.assert(ids.length > 0, "maintainedPersonIds should contain at least the test person")
|
||
});
|
||
client.test("User does NOT see own deletedAt (admin-only)", function () {
|
||
client.assert(response.body.deletedAt == null, "Self deletedAt should be hidden")
|
||
});
|
||
%}
|
||
|
||
### 73 Regular user: Get admin profile — Email, accessLevel, maintainedPersonIds hidden
|
||
GET {{WepApiTest_HostAddress}}/api/user/{{admin_id}}
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("User does NOT see admin email", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(response.body.email === null, "Other user email should be null")
|
||
});
|
||
client.test("User does NOT see admin deletedAt", function () {
|
||
client.assert(response.body.deletedAt === null)
|
||
});
|
||
client.test("User does NOT see admin accessLevel (defaults to User=0)", function () {
|
||
client.assert(response.body.accessLevel === 0, "AccessLevel should default to 0 for other users")
|
||
});
|
||
client.test("User does NOT see admin maintainedPersonIds", function () {
|
||
client.assert(response.body.maintainedPersonIds === null)
|
||
});
|
||
%}
|
||
|
||
### 74 Curator: Get admin profile — Email and maintainedPersonIds hidden (not self, not admin)
|
||
GET {{WepApiTest_HostAddress}}/api/user/{{admin_id}}
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("Curator does NOT see admin email", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(response.body.email === null)
|
||
});
|
||
client.test("Curator does NOT see admin maintainedPersonIds", function () {
|
||
client.assert(response.body.maintainedPersonIds === null)
|
||
});
|
||
%}
|
||
|
||
### 75 Admin: Get regular user profile — full data visible (email, accessLevel)
|
||
GET {{WepApiTest_HostAddress}}/api/user/{{user_id}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Admin sees other user's email", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$.email") != null)
|
||
});
|
||
client.test("Admin sees other user's accessLevel", function () {
|
||
client.assert(jsonPath(response.body, "$.accessLevel") != null)
|
||
});
|
||
%}
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Maintainer-role data visibility (tests 68.5–68.8)
|
||
# ---------------------------------------------------------------------------
|
||
|
||
### 68.5. Promote regular user to Maintainer
|
||
POST {{WepApiTest_HostAddress}}/api/user/update
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"id": "{{user_id}}",
|
||
"accessLevel": 1
|
||
}
|
||
|
||
> {%
|
||
client.test("Promote user to Maintainer", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 68.6. Re-login as promoted maintainer
|
||
POST {{WepApiTest_HostAddress}}/api/auth/login
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"identifier": "{{userName}}",
|
||
"password": "{{userPwd}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("maintainer_token", jsonPath(response.body, "$.token"));
|
||
client.test("Login as maintainer", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 68.7. Maintainer: Get admin profile — email, accessLevel, maintainedPersonIds hidden
|
||
GET {{WepApiTest_HostAddress}}/api/user/{{admin_id}}
|
||
Authorization: Bearer {{maintainer_token}}
|
||
|
||
> {%
|
||
client.test("Maintainer does NOT see admin email", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(response.body.email === null, "Other user email should be null")
|
||
});
|
||
client.test("Maintainer does NOT see admin deletedAt", function () {
|
||
client.assert(response.body.deletedAt === null)
|
||
});
|
||
client.test("Maintainer does NOT see admin accessLevel (defaults to User=0)", function () {
|
||
client.assert(response.body.accessLevel === 0, "AccessLevel should default to 0 for non-admin viewing other user")
|
||
});
|
||
client.test("Maintainer does NOT see admin maintainedPersonIds", function () {
|
||
client.assert(response.body.maintainedPersonIds === null)
|
||
});
|
||
%}
|
||
|
||
### 68.8. Demote maintainer back to regular user
|
||
POST {{WepApiTest_HostAddress}}/api/user/update
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"id": "{{user_id}}",
|
||
"accessLevel": 0
|
||
}
|
||
|
||
> {%
|
||
client.test("Demote maintainer back to User", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Person data visibility (tests 69–71)
|
||
# ---------------------------------------------------------------------------
|
||
|
||
### 76 Regular user: Get person detail — maintainerUserIds public, Visibility hidden
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{testPersonId}}
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("User gets person detail", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
client.test("User sees maintainerUserIds (public info)", function () {
|
||
client.assert(response.body.maintainerUserIds != null, "maintainerUserIds should be visible to all users")
|
||
});
|
||
client.test("User sees maintainerUsernames (public info)", function () {
|
||
client.assert(response.body.maintainerUsernames != null, "maintainerUsernames should be visible to all users")
|
||
});
|
||
client.test("User does NOT see visibility (sensitive)", function () {
|
||
client.assert(response.body.visibility === null, "visibility should be null for regular user")
|
||
});
|
||
%}
|
||
|
||
### 77 Curator: Get person detail — maintainerUserIds and visibility visible
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{testPersonId}}
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("Curator gets person detail", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
client.test("Curator sees maintainerUserIds", function () {
|
||
client.assert(jsonPath(response.body, "$.maintainerUserIds") != null)
|
||
});
|
||
client.test("Curator sees visibility", function () {
|
||
client.assert(jsonPath(response.body, "$.visibility") != null, "visibility should be non-null for curator")
|
||
});
|
||
%}
|
||
|
||
### 78 Admin: Get person detail — all fields visible
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{testPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Admin gets person detail", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
client.test("Admin sees maintainerUserIds", function () {
|
||
client.assert(jsonPath(response.body, "$.maintainerUserIds") != null)
|
||
});
|
||
client.test("Admin sees visibility value", function () {
|
||
client.assert(jsonPath(response.body, "$.visibility") != null)
|
||
});
|
||
%}
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Asset data visibility (tests 72–77)
|
||
# ---------------------------------------------------------------------------
|
||
|
||
### 79 Admin: Find first asset and verify uploader is loaded
|
||
GET {{WepApiTest_HostAddress}}/api/asset?page=0&pageSize=1
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
var firstAsset = response.body[0];
|
||
var assetId = firstAsset != null ? firstAsset.id : null;
|
||
client.global.set("testAssetId", assetId);
|
||
client.global.set("hasAssets", assetId != null ? "true" : "false");
|
||
client.test("Asset search succeeds", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 80 Regular user: Get asset detail — FileName hidden, uploader email hidden
|
||
GET {{WepApiTest_HostAddress}}/api/asset/{{testAssetId}}
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
// Only run assertions if an asset was found — skip gracefully otherwise
|
||
var hasAssets = client.global.get("hasAssets");
|
||
if (hasAssets === "true") {
|
||
client.test("User gets asset detail", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
client.test("User does NOT see original fileName", function () {
|
||
client.assert(response.body.fileName === null, "fileName should be null for regular user but was '" + response.body.fileName + "'")
|
||
});
|
||
client.test("User does NOT see uploader email", function () {
|
||
client.assert(response.body.uploadedBy === null || response.body.uploadedBy.email === null, "uploader email should be null for regular user")
|
||
});
|
||
client.test("User does NOT see asset visibility", function () {
|
||
client.assert(response.body.visibility === null)
|
||
});
|
||
} else {
|
||
client.test("No assets in database — skipping asset visibility tests", function () {
|
||
client.assert(true)
|
||
});
|
||
}
|
||
%}
|
||
|
||
### 81 Curator: Get asset detail — FileName visible, uploader email hidden (unless self)
|
||
GET {{WepApiTest_HostAddress}}/api/asset/{{testAssetId}}
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
var hasAssets = client.global.get("hasAssets");
|
||
if (hasAssets === "true") {
|
||
client.test("Curator gets asset detail", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
client.test("Curator sees original fileName", function () {
|
||
client.assert(response.body.fileName != null, "fileName should be visible to curator but was null")
|
||
});
|
||
client.test("Curator does NOT see uploader email (unless self)", function () {
|
||
client.assert(response.body.uploadedBy == null || response.body.uploadedBy.email === null, "uploader email should be null for curator viewing another user's asset")
|
||
});
|
||
} else {
|
||
client.test("No assets in database — skipping asset visibility tests", function () {
|
||
client.assert(true)
|
||
});
|
||
}
|
||
%}
|
||
|
||
### 82 Admin: Get asset detail — FileName and uploader email visible
|
||
GET {{WepApiTest_HostAddress}}/api/asset/{{testAssetId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
var hasAssets = client.global.get("hasAssets");
|
||
if (hasAssets === "true") {
|
||
client.test("Admin gets asset detail", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
client.test("Admin sees original fileName", function () {
|
||
client.assert(response.body.fileName != null)
|
||
});
|
||
client.test("Admin sees uploader email (or placeholder if server-scanned)", function () {
|
||
// uploadedBy is always present (real user or "deleted" placeholder).
|
||
// If it's a real uploader (non-empty GUID), email must be visible.
|
||
// If server-scanned (Guid.Empty placeholder), email can be null.
|
||
var uploader = response.body.uploadedBy;
|
||
client.assert(uploader != null, "uploadedBy field must be present");
|
||
if (uploader.id !== "00000000-0000-0000-0000-000000000000") {
|
||
client.assert(uploader.email != null, "real uploader email should be visible to admin")
|
||
}
|
||
});
|
||
client.test("Admin sees asset visibility", function () {
|
||
client.assert(response.body.visibility != null)
|
||
});
|
||
} else {
|
||
client.test("No assets in database — skipping asset visibility tests", function () {
|
||
client.assert(true)
|
||
});
|
||
}
|
||
%}
|
||
|
||
### 83 Regular user: Search assets — FileName hidden in previews
|
||
GET {{WepApiTest_HostAddress}}/api/asset?page=0&pageSize=3
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("User searches assets", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
client.test("User does NOT see fileName in preview list", function () {
|
||
var first = response.body[0];
|
||
client.assert(first === undefined || first === null || first.fileName === null, "fileName should be null in preview for regular user")
|
||
});
|
||
%}
|
||
|
||
### 84 Curator: Search assets — FileName visible in previews
|
||
GET {{WepApiTest_HostAddress}}/api/asset?page=0&pageSize=3
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("Curator searches assets", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
client.test("Curator sees fileName in preview list", function () {
|
||
var first = response.body[0];
|
||
client.assert(first != null && first.fileName != null, "fileName should be visible in preview for curator")
|
||
});
|
||
%}
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Authorization boundary tests (tests 78–81)
|
||
# ---------------------------------------------------------------------------
|
||
|
||
### 85 Regular user: Cannot access stats (should 403)
|
||
GET {{WepApiTest_HostAddress}}/api/stats
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("User cannot access stats", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 86 Regular user: Cannot access settings (should 403)
|
||
GET {{WepApiTest_HostAddress}}/api/settings
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("User cannot access settings", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 87 Regular user: Cannot access user list (should 403)
|
||
GET {{WepApiTest_HostAddress}}/api/user
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("User cannot list all users", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 88 Curator: Cannot access settings (should 403)
|
||
GET {{WepApiTest_HostAddress}}/api/settings
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("Curator cannot access settings", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
# =============================================================================
|
||
# VISIBILITY GATE TESTS (R2–R4, R6)
|
||
# =============================================================================
|
||
# These tests verify that entity-level visibility gating is correctly enforced
|
||
# per the formal rules established in issue #129:
|
||
# R2 — Asset visibility (independent per-asset gate)
|
||
# R3 — Album access gated by album's own visibility
|
||
# R4 — Person access gated by person's own visibility
|
||
# R6 — Edit mode: privileged users receive Private data, frontend decides display
|
||
# =============================================================================
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# R4: Person visibility gating
|
||
# ---------------------------------------------------------------------------
|
||
|
||
### 89 Create person for visibility gating tests
|
||
< {%
|
||
client.global.set("visPersonName", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/person
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{visPersonName}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("visPersonId", jsonPath(response.body, "$"));
|
||
client.test("Create visibility test person", function () {
|
||
client.assert(response.status === 200)
|
||
client.assert(jsonPath(response.body, "$") != null)
|
||
});
|
||
%}
|
||
|
||
### 90 R4: User gets new person (Public by default — should 200)
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{visPersonId}}
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("R4: User gets Public person (should 200)", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 91 R4: Update person to Private visibility
|
||
POST {{WepApiTest_HostAddress}}/api/person/{{visPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{visPersonName}}",
|
||
"visibility": 2
|
||
}
|
||
|
||
> {%
|
||
client.test("R4: Update person to Private", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 92 R4: User gets Private person (should 404)
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{visPersonId}}
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("R4: User gets Private person (should 404)", function () {
|
||
client.assert(response.status === 404)
|
||
});
|
||
%}
|
||
|
||
### 93 R4: Admin gets Private person (should 200)
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{visPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("R4: Admin gets Private person (should 200)", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 94 R4: Curator gets Private person (should 200)
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{visPersonId}}
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("R4: Curator gets Private person (should 200)", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 95 R4: Update person back to Public visibility
|
||
POST {{WepApiTest_HostAddress}}/api/person/{{visPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{visPersonName}}",
|
||
"visibility": 0
|
||
}
|
||
|
||
> {%
|
||
client.test("R4: Update person to Public", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 96 R4: User gets Public person (should 200)
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{visPersonId}}
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("R4: User gets Public person (should 200)", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 97 R4: Cleanup — Delete visibility test person
|
||
DELETE {{WepApiTest_HostAddress}}/api/person/{{visPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("R4: Delete visibility test person", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# R3: Album visibility gating
|
||
# ---------------------------------------------------------------------------
|
||
|
||
### 98 R3: Create Public album for visibility gating tests
|
||
< {%
|
||
client.global.set("visPublicAlbum", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/album
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{visPublicAlbum}}",
|
||
"visibility": 0
|
||
}
|
||
|
||
> {%
|
||
client.global.set("visPublicAlbumId", jsonPath(response.body, "$"));
|
||
client.test("R3: Create Public album", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 99 R3: Create Private album for visibility gating tests
|
||
< {%
|
||
client.global.set("visPrivateAlbum", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/album
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{visPrivateAlbum}}",
|
||
"visibility": 2
|
||
}
|
||
|
||
> {%
|
||
client.global.set("visPrivateAlbumId", jsonPath(response.body, "$"));
|
||
client.test("R3: Create Private album", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 100 R3: Create Protected album for visibility gating tests
|
||
< {%
|
||
client.global.set("visProtectedAlbum", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/album
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{visProtectedAlbum}}",
|
||
"visibility": 1
|
||
}
|
||
|
||
> {%
|
||
client.global.set("visProtectedAlbumId", jsonPath(response.body, "$"));
|
||
client.test("R3: Create Protected album", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 101 R3: User gets Public album (should 200)
|
||
GET {{WepApiTest_HostAddress}}/api/album/{{visPublicAlbumId}}
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("R3: User gets Public album (should 200)", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 102 R3: User gets Protected album (should 200)
|
||
GET {{WepApiTest_HostAddress}}/api/album/{{visProtectedAlbumId}}
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("R3: User gets Protected album (should 200)", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 103 R3: User gets Private album (should 404)
|
||
GET {{WepApiTest_HostAddress}}/api/album/{{visPrivateAlbumId}}
|
||
Authorization: Bearer {{user_token}}
|
||
|
||
> {%
|
||
client.test("R3: User gets Private album (should 404)", function () {
|
||
client.assert(response.status === 404)
|
||
});
|
||
%}
|
||
|
||
### 104 R3: Admin gets Private album (should 200)
|
||
GET {{WepApiTest_HostAddress}}/api/album/{{visPrivateAlbumId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("R3: Admin gets Private album (should 200)", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 105 R3: Curator gets Private album (should 200)
|
||
GET {{WepApiTest_HostAddress}}/api/album/{{visPrivateAlbumId}}
|
||
Authorization: Bearer {{curator_token}}
|
||
|
||
> {%
|
||
client.test("R3: Curator gets Private album (should 200)", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 106 R3: Delete Public album
|
||
DELETE {{WepApiTest_HostAddress}}/api/album/{{visPublicAlbumId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("R3: Delete Public album", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 107 R3: Delete Private album
|
||
DELETE {{WepApiTest_HostAddress}}/api/album/{{visPrivateAlbumId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("R3: Delete Private album", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 108 R3: Delete Protected album
|
||
DELETE {{WepApiTest_HostAddress}}/api/album/{{visProtectedAlbumId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("R3: Delete Protected album", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# MERGE & BULK VISIBILITY TESTS (tests 109–130)
|
||
# All test data is self-contained and cleaned up within this section.
|
||
# ---------------------------------------------------------------------------
|
||
|
||
### 109 Album merge: destination in source IDs returns 400
|
||
POST {{WepApiTest_HostAddress}}/api/album/merge
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"destinationId": "00000000-0000-0000-0000-000000000001",
|
||
"sourceIds": ["00000000-0000-0000-0000-000000000001", "00000000-0000-0000-0000-000000000002"]
|
||
}
|
||
|
||
> {%
|
||
client.test("Album merge: destination in sources returns 400", function () {
|
||
client.assert(response.status === 400)
|
||
});
|
||
%}
|
||
|
||
### 110 Person merge: destination in source IDs returns 400
|
||
POST {{WepApiTest_HostAddress}}/api/person/merge
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"destinationId": "00000000-0000-0000-0000-000000000001",
|
||
"sourceIds": ["00000000-0000-0000-0000-000000000001"]
|
||
}
|
||
|
||
> {%
|
||
client.test("Person merge: destination in sources returns 400", function () {
|
||
client.assert(response.status === 400)
|
||
});
|
||
%}
|
||
|
||
### 111 Person merge: nonexistent destination returns 404
|
||
POST {{WepApiTest_HostAddress}}/api/person/merge
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"destinationId": "00000000-0000-0000-0000-0000000000ff",
|
||
"sourceIds": ["00000000-0000-0000-0000-000000000001"]
|
||
}
|
||
|
||
> {%
|
||
client.test("Person merge: nonexistent destination returns 404", function () {
|
||
client.assert(response.status === 404)
|
||
});
|
||
%}
|
||
|
||
### 112 Create merge destination album
|
||
< {%
|
||
client.global.set("mergeDestAlbum", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/album
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{mergeDestAlbum}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("mergeDestAlbumId", jsonPath(response.body, "$"));
|
||
client.test("Create merge destination album", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 113 Create merge source album
|
||
< {%
|
||
client.global.set("mergeSourceAlbum", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/album
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{mergeSourceAlbum}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("mergeSourceAlbumId", jsonPath(response.body, "$"));
|
||
client.test("Create merge source album", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 114 Merge source album into destination
|
||
POST {{WepApiTest_HostAddress}}/api/album/merge
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"destinationId": "{{mergeDestAlbumId}}",
|
||
"sourceIds": ["{{mergeSourceAlbumId}}"]
|
||
}
|
||
|
||
> {%
|
||
client.test("Merge albums succeeds", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 115 Verify destination album still exists
|
||
GET {{WepApiTest_HostAddress}}/api/album/{{mergeDestAlbumId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Destination album exists after merge", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 116 Verify source album is hard-deleted
|
||
GET {{WepApiTest_HostAddress}}/api/album/{{mergeSourceAlbumId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Source album is hard-deleted after merge", function () {
|
||
client.assert(response.status === 404)
|
||
});
|
||
%}
|
||
|
||
### 117 Create merge destination person
|
||
< {%
|
||
client.global.set("mergeDestPerson", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/person
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{mergeDestPerson}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("mergeDestPersonId", jsonPath(response.body, "$"));
|
||
client.test("Create merge destination person", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 118 Create merge source person
|
||
< {%
|
||
client.global.set("mergeSourcePerson", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/person
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{mergeSourcePerson}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("mergeSourcePersonId", jsonPath(response.body, "$"));
|
||
client.test("Create merge source person", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 119 Create album owned by source person
|
||
< {%
|
||
client.global.set("mergePersonAlbum", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/album
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{mergePersonAlbum}}",
|
||
"person": "{{mergeSourcePersonId}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("mergePersonAlbumId", jsonPath(response.body, "$"));
|
||
client.test("Create album for source person", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 120 Merge source person into destination
|
||
POST {{WepApiTest_HostAddress}}/api/person/merge
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"destinationId": "{{mergeDestPersonId}}",
|
||
"sourceIds": ["{{mergeSourcePersonId}}"]
|
||
}
|
||
|
||
> {%
|
||
client.test("Merge people succeeds", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 121 Verify destination person exists and has the album
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{mergeDestPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Destination person exists after merge", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
client.test("Destination person has the merged album", function () {
|
||
var albums = response.body.albums || [];
|
||
var found = albums.some(function(a) { return a.id === client.global.get("mergePersonAlbumId"); });
|
||
client.assert(found, "Expected the merged album to belong to the destination person");
|
||
});
|
||
%}
|
||
|
||
### 122 Verify source person is hard-deleted
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{mergeSourcePersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Source person is hard-deleted after merge", function () {
|
||
client.assert(response.status === 404)
|
||
});
|
||
%}
|
||
|
||
### 123 Cleanup: delete merge test person and album
|
||
DELETE {{WepApiTest_HostAddress}}/api/person/{{mergeDestPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Delete merge destination person", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 124 Create person for bulk visibility test
|
||
< {%
|
||
client.global.set("bulkVisPerson", $random.alphabetic(15));
|
||
%}
|
||
|
||
PUT {{WepApiTest_HostAddress}}/api/person
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"name": "{{bulkVisPerson}}"
|
||
}
|
||
|
||
> {%
|
||
client.global.set("bulkVisPersonId", jsonPath(response.body, "$"));
|
||
client.test("Create person for bulk visibility test", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 125 Bulk visibility update (people) as regular user (should 403)
|
||
POST {{WepApiTest_HostAddress}}/api/person
|
||
Authorization: Bearer {{user_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"ids": ["{{bulkVisPersonId}}"],
|
||
"data": { "name": "{{bulkVisPerson}}", "visibility": 1 }
|
||
}
|
||
|
||
> {%
|
||
client.test("Bulk visibility update (people) as regular user should 403", function () {
|
||
client.assert(response.status === 403)
|
||
});
|
||
%}
|
||
|
||
### 126 Bulk visibility update (people) as admin (should succeed)
|
||
POST {{WepApiTest_HostAddress}}/api/person
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"ids": ["{{bulkVisPersonId}}"],
|
||
"data": { "name": "{{bulkVisPerson}}", "visibility": 1 }
|
||
}
|
||
|
||
> {%
|
||
client.test("Bulk visibility update (people) as admin succeeds", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 127 Verify person visibility was updated
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{bulkVisPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Person visibility updated to Protected", function () {
|
||
client.assert(response.status === 200);
|
||
client.assert(response.body.visibility === 1, "Expected visibility 1 (Protected) but got " + response.body.visibility)
|
||
});
|
||
%}
|
||
|
||
### 128 Bulk visibility update (assets) as admin
|
||
POST {{WepApiTest_HostAddress}}/api/asset
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"ids": ["{{testAssetId}}"],
|
||
"data": { "visibility": 1 }
|
||
}
|
||
|
||
> {%
|
||
var hasAssets = client.global.get("hasAssets");
|
||
if (hasAssets === "true") {
|
||
client.test("Bulk visibility update (assets) succeeds", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
} else {
|
||
client.test("No assets — skipping asset bulk visibility test", function () {
|
||
client.assert(true)
|
||
});
|
||
}
|
||
%}
|
||
|
||
### 129 Revert asset visibility back to Public
|
||
POST {{WepApiTest_HostAddress}}/api/asset
|
||
Authorization: Bearer {{admin_token}}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"ids": ["{{testAssetId}}"],
|
||
"data": { "visibility": 0 }
|
||
}
|
||
|
||
> {%
|
||
var hasAssets = client.global.get("hasAssets");
|
||
if (hasAssets === "true") {
|
||
client.test("Revert asset visibility to Public", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
} else {
|
||
client.test("No assets — skipping asset revert test", function () {
|
||
client.assert(true)
|
||
});
|
||
}
|
||
%}
|
||
|
||
### 130 Cleanup: delete bulk visibility test person
|
||
DELETE {{WepApiTest_HostAddress}}/api/person/{{bulkVisPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Delete bulk visibility test person", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# R2: Asset visibility gating — existing assets test
|
||
# ---------------------------------------------------------------------------
|
||
|
||
### 131 R2: Anonymous gets asset detail (should 200 for Public assets)
|
||
GET {{WepApiTest_HostAddress}}/api/asset/{{testAssetId}}
|
||
|
||
> {%
|
||
var hasAssets = client.global.get("hasAssets");
|
||
if (hasAssets === "true") {
|
||
client.test("R2: Anonymous gets asset detail", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
} else {
|
||
client.test("R2: No assets — skipping", function () {
|
||
client.assert(true)
|
||
});
|
||
}
|
||
%}
|
||
|
||
# =============================================================================
|
||
# CLEANUP
|
||
# =============================================================================
|
||
|
||
### 132 Delete test person as admin
|
||
DELETE {{WepApiTest_HostAddress}}/api/person/{{testPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Delete test person as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 133 Verify test person is deleted
|
||
GET {{WepApiTest_HostAddress}}/api/person/{{testPersonId}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Verify test person is deleted", function () {
|
||
client.assert(response.status === 404)
|
||
});
|
||
%}
|
||
|
||
### 134 Delete curator user as admin
|
||
DELETE {{WepApiTest_HostAddress}}/api/user/{{curator_id}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Delete curator user as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 135 Verify curator user is soft-deleted
|
||
GET {{WepApiTest_HostAddress}}/api/user/{{curator_id}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Verify curator user is soft-deleted", function () {
|
||
client.assert(response.status === 200);
|
||
client.assert(response.body.deletedAt !== null, "deletedAt should be set after soft delete");
|
||
});
|
||
%}
|
||
|
||
### 136 Delete regular user as admin
|
||
DELETE {{WepApiTest_HostAddress}}/api/user/{{user_id}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Delete regular user as admin", function () {
|
||
client.assert(response.status === 200)
|
||
});
|
||
%}
|
||
|
||
### 137 Verify regular user is soft-deleted
|
||
GET {{WepApiTest_HostAddress}}/api/user/{{user_id}}
|
||
Authorization: Bearer {{admin_token}}
|
||
|
||
> {%
|
||
client.test("Verify regular user is soft-deleted", function () {
|
||
client.assert(response.status === 200);
|
||
client.assert(response.body.deletedAt !== null, "deletedAt should be set after soft delete");
|
||
});
|
||
%}
|
||
|
||
# =============================================================================
|
||
# STRESS TEST — Auth rate limit bucket
|
||
# =============================================================================
|
||
# Sends 15 rapid login attempts with invalid credentials to exceed the auth
|
||
# rate-limit bucket (PermitLimit=10, WindowSeconds=60). Requests 1-10 should
|
||
# return 401 (invalid credentials), request 11+ should return 429 (rate limited).
|
||
# =============================================================================
|
||
|
||
### 138 Auth rate limit stress test (15 iterations)
|
||
# @repeat = 15
|
||
POST {{WepApiTest_HostAddress}}/api/auth/login
|
||
Content-Type: application/json
|
||
|
||
{ "identifier": "stress-load-test-user", "password": "invalid-pwd" }
|
||
|
||
> {%
|
||
var idx = parseInt("{{$repeatIndex}}") + 1;
|
||
var seen429 = parseInt(client.global.get("stressSeen429") || "0");
|
||
if (response.status === 429) {
|
||
seen429 = 1;
|
||
client.global.set("stressSeen429", "1");
|
||
}
|
||
|
||
if (idx === 15) {
|
||
client.test("[" + idx + "/15] At least one 429 was triggered", function () {
|
||
client.assert(seen429 === 1, "Expected at least one 429 response within 15 requests");
|
||
});
|
||
client.global.set("stressSeen429", "0");
|
||
}
|
||
|
||
client.test("[" + idx + "/15] Status is 401 or 429", function () {
|
||
client.assert(
|
||
response.status === 401 || response.status === 429,
|
||
"Expected 401 (invalid) or 429 (rate limited) but got " + response.status
|
||
);
|
||
});
|
||
%}
|