line-gestao-api/postman/SystemTenant-MultiTenant-Te...

396 lines
13 KiB
JSON

{
"info": {
"name": "Line Gestao - SystemTenant Multi-tenant Tests",
"_postman_id": "c4c0b7d9-7f11-4a0c-b8ca-332633f12601",
"description": "Fluxo de testes para sysadmin, endpoints /api/system/* e isolamento por tenant.",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"variable": [
{ "key": "adminMasterToken", "value": "" },
{ "key": "tenantAUserToken", "value": "" },
{ "key": "newTenantAUserToken", "value": "" },
{ "key": "tenantAUserId", "value": "" },
{ "key": "newTenantAUserId", "value": "" },
{ "key": "newTenantAUserEmail", "value": "" },
{ "key": "newTenantAUserPassword", "value": "" },
{ "key": "newTenantAUserName", "value": "" }
],
"item": [
{
"name": "1) Login sysadmin",
"request": {
"method": "POST",
"header": [
{ "key": "Content-Type", "value": "application/json" }
],
"body": {
"mode": "raw",
"raw": "{\n \"email\": \"{{adminMasterEmail}}\",\n \"password\": \"{{adminMasterPassword}}\",\n \"tenantId\": \"{{systemTenantId}}\"\n}"
},
"url": {
"raw": "{{baseUrl}}/auth/login",
"host": ["{{baseUrl}}"],
"path": ["auth", "login"]
}
},
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status 200', function () {",
" pm.response.to.have.status(200);",
"});",
"const json = pm.response.json();",
"pm.test('Retorna token JWT', function () {",
" pm.expect(json.token).to.be.a('string').and.not.empty;",
"});",
"pm.collectionVariables.set('adminMasterToken', json.token);"
]
}
}
]
},
{
"name": "2) GET /api/system/tenants (sysadmin)",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{ "key": "token", "value": "{{adminMasterToken}}", "type": "string" }
]
},
"method": "GET",
"url": {
"raw": "{{baseUrl}}/api/system/tenants?source=MobileLines.Cliente&active=true",
"host": ["{{baseUrl}}"],
"path": ["api", "system", "tenants"],
"query": [
{ "key": "source", "value": "MobileLines.Cliente" },
{ "key": "active", "value": "true" }
]
}
},
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status 200', function () {",
" pm.response.to.have.status(200);",
"});",
"const tenants = pm.response.json();",
"pm.test('Retorna array de tenants', function () {",
" pm.expect(Array.isArray(tenants)).to.eql(true);",
"});",
"const tenantAClientName = pm.environment.get('tenantAClientName');",
"const tenantBClientName = pm.environment.get('tenantBClientName');",
"if (tenantAClientName) {",
" const tenantA = tenants.find(t => t.nomeOficial === tenantAClientName || t.NomeOficial === tenantAClientName);",
" pm.test('Tenant A encontrado por nomeOficial', function () {",
" pm.expect(tenantA).to.exist;",
" });",
" if (tenantA && (tenantA.tenantId || tenantA.TenantId)) {",
" pm.environment.set('tenantAId', tenantA.tenantId || tenantA.TenantId);",
" }",
"}",
"if (tenantBClientName) {",
" const tenantB = tenants.find(t => t.nomeOficial === tenantBClientName || t.NomeOficial === tenantBClientName);",
" pm.test('Tenant B encontrado por nomeOficial', function () {",
" pm.expect(tenantB).to.exist;",
" });",
" if (tenantB && (tenantB.tenantId || tenantB.TenantId)) {",
" pm.environment.set('tenantBId', tenantB.tenantId || tenantB.TenantId);",
" }",
"}"
]
}
}
]
},
{
"name": "3) POST /api/system/tenants/{tenantId}/users (criar usuário comum tenant A)",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{ "key": "token", "value": "{{adminMasterToken}}", "type": "string" }
]
},
"method": "POST",
"header": [
{ "key": "Content-Type", "value": "application/json" }
],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"{{tenantAUserName}}\",\n \"email\": \"{{tenantAUserEmail}}\",\n \"password\": \"{{tenantAUserPassword}}\",\n \"roles\": [\"cliente\"]\n}"
},
"url": {
"raw": "{{baseUrl}}/api/system/tenants/{{tenantAId}}/users",
"host": ["{{baseUrl}}"],
"path": ["api", "system", "tenants", "{{tenantAId}}", "users"]
}
},
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status 201 (criado) ou 409 (já existe)', function () {",
" pm.expect([201, 409]).to.include(pm.response.code);",
"});",
"if (pm.response.code === 201) {",
" const json = pm.response.json();",
" pm.collectionVariables.set('tenantAUserId', json.userId || json.UserId || '');",
"}"
]
}
}
]
},
{
"name": "4) Login usuário comum tenant A",
"request": {
"method": "POST",
"header": [
{ "key": "Content-Type", "value": "application/json" }
],
"body": {
"mode": "raw",
"raw": "{\n \"email\": \"{{tenantAUserEmail}}\",\n \"password\": \"{{tenantAUserPassword}}\",\n \"tenantId\": \"{{tenantAId}}\"\n}"
},
"url": {
"raw": "{{baseUrl}}/auth/login",
"host": ["{{baseUrl}}"],
"path": ["auth", "login"]
}
},
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status 200', function () {",
" pm.response.to.have.status(200);",
"});",
"const json = pm.response.json();",
"pm.collectionVariables.set('tenantAUserToken', json.token);"
]
}
}
]
},
{
"name": "5) Usuário comum NÃO acessa /api/system/*",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{ "key": "token", "value": "{{tenantAUserToken}}", "type": "string" }
]
},
"method": "GET",
"url": {
"raw": "{{baseUrl}}/api/system/tenants?source=MobileLines.Cliente&active=true",
"host": ["{{baseUrl}}"],
"path": ["api", "system", "tenants"],
"query": [
{ "key": "source", "value": "MobileLines.Cliente" },
{ "key": "active", "value": "true" }
]
}
},
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status 403 Forbidden', function () {",
" pm.response.to.have.status(403);",
"});"
]
}
}
]
},
{
"name": "6) Usuário comum tenant A vê apenas seu tenant",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{ "key": "token", "value": "{{tenantAUserToken}}", "type": "string" }
]
},
"method": "GET",
"url": {
"raw": "{{baseUrl}}/api/lines/clients",
"host": ["{{baseUrl}}"],
"path": ["api", "lines", "clients"]
}
},
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status 200', function () {",
" pm.response.to.have.status(200);",
"});",
"const clients = pm.response.json();",
"pm.test('Retorna lista de clientes', function () {",
" pm.expect(Array.isArray(clients)).to.eql(true);",
"});",
"const tenantAClientName = pm.environment.get('tenantAClientName');",
"const tenantBClientName = pm.environment.get('tenantBClientName');",
"if (tenantAClientName) {",
" pm.test('Contém cliente do tenant A', function () {",
" pm.expect(clients).to.include(tenantAClientName);",
" });",
"}",
"if (tenantBClientName) {",
" pm.test('Não contém cliente do tenant B', function () {",
" pm.expect(clients).to.not.include(tenantBClientName);",
" });",
"}"
]
}
}
]
},
{
"name": "7) POST /api/system/tenants/{tenantId}/users (novo usuário tenant A)",
"event": [
{
"listen": "prerequest",
"script": {
"type": "text/javascript",
"exec": [
"const suffix = Date.now().toString().slice(-8);",
"pm.collectionVariables.set('newTenantAUserEmail', `novo.tenant.a.${suffix}@test.local`);",
"pm.collectionVariables.set('newTenantAUserPassword', 'ClienteA123!');",
"pm.collectionVariables.set('newTenantAUserName', `Novo Tenant A ${suffix}`);"
]
}
},
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status 201', function () {",
" pm.response.to.have.status(201);",
"});",
"const json = pm.response.json();",
"pm.collectionVariables.set('newTenantAUserId', json.userId || json.UserId || '');"
]
}
}
],
"request": {
"auth": {
"type": "bearer",
"bearer": [
{ "key": "token", "value": "{{adminMasterToken}}", "type": "string" }
]
},
"method": "POST",
"header": [
{ "key": "Content-Type", "value": "application/json" }
],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"{{newTenantAUserName}}\",\n \"email\": \"{{newTenantAUserEmail}}\",\n \"password\": \"{{newTenantAUserPassword}}\",\n \"roles\": [\"cliente\"]\n}"
},
"url": {
"raw": "{{baseUrl}}/api/system/tenants/{{tenantAId}}/users",
"host": ["{{baseUrl}}"],
"path": ["api", "system", "tenants", "{{tenantAId}}", "users"]
}
}
},
{
"name": "8) Login novo usuário tenant A",
"request": {
"method": "POST",
"header": [
{ "key": "Content-Type", "value": "application/json" }
],
"body": {
"mode": "raw",
"raw": "{\n \"email\": \"{{newTenantAUserEmail}}\",\n \"password\": \"{{newTenantAUserPassword}}\",\n \"tenantId\": \"{{tenantAId}}\"\n}"
},
"url": {
"raw": "{{baseUrl}}/auth/login",
"host": ["{{baseUrl}}"],
"path": ["auth", "login"]
}
},
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status 200', function () {",
" pm.response.to.have.status(200);",
"});",
"const json = pm.response.json();",
"pm.collectionVariables.set('newTenantAUserToken', json.token);"
]
}
}
]
},
{
"name": "9) Novo usuário tenant A vê apenas seu tenant",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{ "key": "token", "value": "{{newTenantAUserToken}}", "type": "string" }
]
},
"method": "GET",
"url": {
"raw": "{{baseUrl}}/api/lines/clients",
"host": ["{{baseUrl}}"],
"path": ["api", "lines", "clients"]
}
},
"event": [
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
"pm.test('Status 200', function () {",
" pm.response.to.have.status(200);",
"});",
"const clients = pm.response.json();",
"const tenantAClientName = pm.environment.get('tenantAClientName');",
"const tenantBClientName = pm.environment.get('tenantBClientName');",
"if (tenantAClientName) {",
" pm.test('Contém cliente do tenant A', function () {",
" pm.expect(clients).to.include(tenantAClientName);",
" });",
"}",
"if (tenantBClientName) {",
" pm.test('Não contém cliente do tenant B', function () {",
" pm.expect(clients).to.not.include(tenantBClientName);",
" });",
"}"
]
}
}
]
}
]
}