Skip to content

Commit 021a554

Browse files
committed
add license/user token management authz for products
1 parent 44b487e commit 021a554

File tree

11 files changed

+648
-77
lines changed

11 files changed

+648
-77
lines changed

app/models/token.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,11 +356,12 @@ def user_token?
356356
bearer.has_role? :user
357357
end
358358

359-
def activation_token?
359+
def license_token?
360360
return false if orphaned_token?
361361

362362
bearer.has_role? :license
363363
end
364+
alias :activation_token? :license_token?
364365

365366
def kind
366367
case

app/policies/environments/token_policy.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ def index?
1111
case bearer
1212
in role: Role(:admin | :developer | :sales_agent | :support_agent | :read_only)
1313
allow!
14-
in role: Role(:environment) if environment == bearer
15-
record.all? { _1 in bearer_type: ^(Environment.name), bearer_id: ^(bearer.id) }
14+
in role: Role(:environment), id: bearer_id if environment == bearer
15+
record.all? { _1 in bearer_type: 'Environment', bearer_id: ^bearer_id }
1616
else
1717
deny!
1818
end

app/policies/products/token_policy.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ def index?
1313
case bearer
1414
in role: Role(:admin | :developer | :sales_agent | :support_agent | :read_only | :environment)
1515
allow!
16-
in role: Role(:product) if product == bearer
17-
record.all? { _1 in bearer_type: ^(Product.name), bearer_id: ^(bearer.id) }
16+
in role: Role(:product), id: bearer_id if product == bearer
17+
record.all? { _1 in bearer_type: 'Product', bearer_id: ^bearer_id }
1818
else
1919
deny!
2020
end

app/policies/token_policy.rb

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,12 @@ def index?
1010
case bearer
1111
in role: Role(:admin | :developer | :sales_agent | :support_agent | :read_only | :environment)
1212
allow!
13-
in role: Role(:product)
14-
record.all? { _1 in { bearer_type: ^(Product.name), bearer_id: ^(bearer.id) } |
15-
{ bearer_type: ^(License.name) | ^(User.name) } }
16-
in role: Role(:license)
17-
record.all? { _1 in { bearer_type: ^(License.name), bearer_id: ^(bearer.id) } }
18-
in role: Role(:user)
19-
record.all? { _1 in { bearer_type: ^(User.name), bearer_id: ^(bearer.id) } }
13+
in role: Role(:product), id: bearer_id
14+
record.all? { _1 in { bearer_type: 'Product', bearer_id: ^bearer_id } | { bearer_type: 'License' | 'User' } }
15+
in role: Role(:license), id: bearer_id
16+
record.all? { _1 in { bearer_type: 'License', bearer_id: ^bearer_id } }
17+
in role: Role(:user), id: bearer_id
18+
record.all? { _1 in { bearer_type: 'User', bearer_id: ^bearer_id } }
2019
else
2120
deny!
2221
end
@@ -31,6 +30,10 @@ def show?
3130
case bearer
3231
in role: Role(:admin | :developer | :sales_agent | :support_agent | :read_only | :environment)
3332
allow!
33+
in role: Role(:product) if record.user_token? && record.bearer.products.exists?(bearer.id)
34+
allow!
35+
in role: Role(:product) if record.license_token? && record.bearer.product == bearer
36+
allow!
3437
else
3538
record.bearer == bearer
3639
end
@@ -47,7 +50,11 @@ def generate?
4750
case bearer
4851
in role: Role(:admin | :developer | :sales_agent | :support_agent | :read_only | :environment) if record.bearer == bearer
4952
allow!
50-
in role: Role(:admin | :developer | :environment) if record.bearer.user?
53+
in role: Role(:admin | :developer | :environment) if record.user_token?
54+
allow!
55+
in role: Role(:product) if record.user_token? && record.bearer.products.exists?(bearer.id)
56+
allow!
57+
in role: Role(:product) if record.license_token? && record.bearer.product == bearer
5158
allow!
5259
in role: Role(:user) if record.bearer == bearer
5360
deny! 'user is banned' if
@@ -64,9 +71,13 @@ def regenerate?
6471
verify_environment!
6572

6673
case bearer
67-
in role: Role(:admin | :developer) if record.bearer == bearer || record.bearer.environment? || record.bearer.product? || record.bearer.license? || record.bearer.user?
74+
in role: Role(:admin | :developer) if record.bearer == bearer || record.environment_token? || record.product_token? || record.license_token? || record.user_token?
6875
allow!
69-
in role: Role(:environment) if record.bearer == bearer || record.bearer.product? || record.bearer.license? || record.bearer.user?
76+
in role: Role(:environment) if record.bearer == bearer || record.product_token? || record.license_token? || record.user_token?
77+
allow!
78+
in role: Role(:product) if record.user_token? && record.bearer.products.exists?(bearer.id)
79+
allow!
80+
in role: Role(:product) if record.license_token? && record.bearer.product == bearer
7081
allow!
7182
else
7283
record.bearer == bearer
@@ -80,6 +91,10 @@ def revoke?
8091
case bearer
8192
in role: Role(:admin | :developer | :environment)
8293
allow!
94+
in role: Role(:product) if record.user_token? && record.bearer.products.exists?(bearer.id)
95+
allow!
96+
in role: Role(:product) if record.license_token? && record.bearer.product == bearer
97+
allow!
8398
else
8499
record.bearer == bearer
85100
end

features/api/v1/tokens/generate.feature

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,6 +1369,257 @@ Feature: Generate authentication token
13691369
And sidekiq should have 1 "metric" job
13701370
And sidekiq should have 1 "request-log" job
13711371

1372+
Scenario: Admin generates a new token for an invalid product
1373+
Given the current account is "test1"
1374+
And I am an admin of account "test1"
1375+
And I authenticate with a token
1376+
When I send a POST request to "/accounts/test1/tokens" with the following:
1377+
"""
1378+
{
1379+
"data": {
1380+
"type": "token",
1381+
"relationships": {
1382+
"bearer": {
1383+
"data": { "type": "product", "id": "2845d39b-050f-417a-8f06-a50f31c2b792" }
1384+
}
1385+
}
1386+
}
1387+
}
1388+
"""
1389+
Then the response status should be "403"
1390+
And sidekiq should have 0 "webhook" jobs
1391+
And sidekiq should have 1 "request-log" job
1392+
And sidekiq should have 0 "event-log" jobs
1393+
1394+
Scenario: Product generates a new token for themselves
1395+
Given the current account is "test1"
1396+
And the current account has 1 "product"
1397+
And I am a product of account "test1"
1398+
And I authenticate with a token
1399+
When I send a POST request to "/accounts/test1/tokens"
1400+
Then the response status should be "403"
1401+
And sidekiq should have 0 "webhook" jobs
1402+
And sidekiq should have 1 "request-log" job
1403+
And sidekiq should have 0 "event-log" jobs
1404+
1405+
Scenario: Product generates a new token for a product
1406+
Given the current account is "test1"
1407+
And the current account has 2 "products"
1408+
And I am a product of account "test1"
1409+
And I authenticate with a token
1410+
When I send a POST request to "/accounts/test1/tokens" with the following:
1411+
"""
1412+
{
1413+
"data": {
1414+
"type": "token",
1415+
"relationships": {
1416+
"bearer": {
1417+
"data": { "type": "product", "id": "$products[1]" }
1418+
}
1419+
}
1420+
}
1421+
}
1422+
"""
1423+
Then the response status should be "403"
1424+
And sidekiq should have 0 "webhook" jobs
1425+
And sidekiq should have 1 "request-log" job
1426+
And sidekiq should have 0 "event-log" jobs
1427+
1428+
Scenario: Product generates a new token for their license
1429+
Given the current account is "test1"
1430+
And the current account has 1 "product"
1431+
And the current account has 1 "policy" for the last "product"
1432+
And the current account has 1 "license" for the last "policy"
1433+
And I am a product of account "test1"
1434+
And I authenticate with a token
1435+
When I send a POST request to "/accounts/test1/tokens" with the following:
1436+
"""
1437+
{
1438+
"data": {
1439+
"type": "token",
1440+
"relationships": {
1441+
"bearer": {
1442+
"data": { "type": "licenses", "id": "$licenses[0]" }
1443+
}
1444+
}
1445+
}
1446+
}
1447+
"""
1448+
Then the response status should be "201"
1449+
And the response body should be a "token" with the following relationships:
1450+
"""
1451+
{
1452+
"bearer": {
1453+
"links": { "related": "/v1/accounts/$account/licenses/$licenses[0]" },
1454+
"data": { "type": "licenses", "id": "$licenses[0]" }
1455+
}
1456+
}
1457+
"""
1458+
And the response body should be a "token" with the following attributes:
1459+
"""
1460+
{ "kind": "activation-token" }
1461+
"""
1462+
And sidekiq should have 0 "webhook" jobs
1463+
And sidekiq should have 1 "request-log" job
1464+
And sidekiq should have 1 "event-log" job
1465+
1466+
Scenario: Product generates a new token for a license
1467+
Given the current account is "test1"
1468+
And the current account has 1 "product"
1469+
And the current account has 1 "license"
1470+
And I am a product of account "test1"
1471+
And I authenticate with a token
1472+
When I send a POST request to "/accounts/test1/tokens" with the following:
1473+
"""
1474+
{
1475+
"data": {
1476+
"type": "token",
1477+
"relationships": {
1478+
"bearer": {
1479+
"data": { "type": "licenses", "id": "$licenses[0]" }
1480+
}
1481+
}
1482+
}
1483+
}
1484+
"""
1485+
Then the response status should be "403"
1486+
And sidekiq should have 0 "webhook" jobs
1487+
And sidekiq should have 1 "request-log" job
1488+
And sidekiq should have 0 "event-log" jobs
1489+
1490+
Scenario: Product generates a new token for an admin
1491+
Given the current account is "test1"
1492+
And the current account has 1 "product"
1493+
And the current account has 1 "admin"
1494+
And I am a product of account "test1"
1495+
And I authenticate with a token
1496+
When I send a POST request to "/accounts/test1/tokens" with the following:
1497+
"""
1498+
{
1499+
"data": {
1500+
"type": "token",
1501+
"relationships": {
1502+
"bearer": {
1503+
"data": { "type": "users", "id": "$users[1]" }
1504+
}
1505+
}
1506+
}
1507+
}
1508+
"""
1509+
Then the response status should be "403"
1510+
And sidekiq should have 0 "webhook" jobs
1511+
And sidekiq should have 1 "request-log" job
1512+
And sidekiq should have 0 "event-log" jobs
1513+
1514+
Scenario: Product generates a new token for their user
1515+
Given the current account is "test1"
1516+
And the current account has 1 "user"
1517+
And the current account has 1 "license" for the last "user" as "owner"
1518+
And I am a product of account "test1"
1519+
And I authenticate with a token
1520+
When I send a POST request to "/accounts/test1/tokens" with the following:
1521+
"""
1522+
{
1523+
"data": {
1524+
"type": "token",
1525+
"relationships": {
1526+
"bearer": {
1527+
"data": { "type": "user", "id": "$users[1]" }
1528+
}
1529+
}
1530+
}
1531+
}
1532+
"""
1533+
Then the response status should be "201"
1534+
And the response body should be a "token" with the following relationships:
1535+
"""
1536+
{
1537+
"bearer": {
1538+
"links": { "related": "/v1/accounts/$account/users/$users[1]" },
1539+
"data": { "type": "users", "id": "$users[1]" }
1540+
}
1541+
}
1542+
"""
1543+
And the response body should be a "token" with the following attributes:
1544+
"""
1545+
{ "kind": "user-token" }
1546+
"""
1547+
And sidekiq should have 0 "webhook" jobs
1548+
And sidekiq should have 1 "request-log" job
1549+
And sidekiq should have 1 "event-log" job
1550+
1551+
Scenario: Product generates a new token for a user
1552+
Given the current account is "test1"
1553+
And the current account has 1 "product"
1554+
And the current account has 1 "user"
1555+
And I am a product of account "test1"
1556+
And I authenticate with a token
1557+
When I send a POST request to "/accounts/test1/tokens" with the following:
1558+
"""
1559+
{
1560+
"data": {
1561+
"type": "token",
1562+
"relationships": {
1563+
"bearer": {
1564+
"data": { "type": "user", "id": "$users[1]" }
1565+
}
1566+
}
1567+
}
1568+
}
1569+
"""
1570+
Then the response status should be "403"
1571+
And sidekiq should have 0 "webhook" jobs
1572+
And sidekiq should have 1 "request-log" job
1573+
And sidekiq should have 0 "event-log" jobs
1574+
1575+
Scenario: Product generates a new token for an invalid user
1576+
Given the current account is "test1"
1577+
And the current account has 1 "product"
1578+
And the current account has 1 "user"
1579+
And I am a product of account "test1"
1580+
And I authenticate with a token
1581+
When I send a POST request to "/accounts/test1/tokens" with the following:
1582+
"""
1583+
{
1584+
"data": {
1585+
"type": "token",
1586+
"relationships": {
1587+
"bearer": {
1588+
"data": { "type": "user", "id": "0ea6a022-5fa1-42f2-9bf0-b0a3c5bbcc24" }
1589+
}
1590+
}
1591+
}
1592+
}
1593+
"""
1594+
Then the response status should be "403"
1595+
And sidekiq should have 0 "webhook" jobs
1596+
And sidekiq should have 1 "request-log" job
1597+
And sidekiq should have 0 "event-log" jobs
1598+
1599+
Scenario: Product generates a new token for an environment
1600+
Given the current account is "test1"
1601+
And the current account has 1 "product"
1602+
And the current account has 1 "environment"
1603+
And I am a product of account "test1"
1604+
And I authenticate with a token
1605+
When I send a POST request to "/accounts/test1/tokens" with the following:
1606+
"""
1607+
{
1608+
"data": {
1609+
"type": "token",
1610+
"relationships": {
1611+
"bearer": {
1612+
"data": { "type": "environment", "id": "$environments[0]" }
1613+
}
1614+
}
1615+
}
1616+
}
1617+
"""
1618+
Then the response status should be "403"
1619+
And sidekiq should have 0 "webhook" jobs
1620+
And sidekiq should have 1 "request-log" job
1621+
And sidekiq should have 0 "event-log" jobs
1622+
13721623
Scenario: User generates a new token via basic authentication
13731624
Given the current account is "test1"
13741625
And the current account has 1 "user"

0 commit comments

Comments
 (0)