Skip to content

Commit

Permalink
Add spending limit operator condition (#118)
Browse files Browse the repository at this point in the history
  • Loading branch information
samteb authored Feb 19, 2024
1 parent 336fc2c commit 1f687f9
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ test_checkRollingTimeWindow {
test_checkSpendingLimitByAmount {
conditions = {
"limit": "1000000000000000000",
"operator": operators.greaterThan,
"timeWindow": {
"type": "rolling",
"value": (12 * 60) * 60,
Expand All @@ -57,6 +58,7 @@ test_checkSpendingLimitByAmount {
test_checkSpendingLimitByValue {
conditions = {
"limit": "900000000000000000",
"operator": operators.greaterThan,
"currency": "fiat:usd",
"timeWindow": {
"type": "rolling",
Expand Down
32 changes: 29 additions & 3 deletions apps/authz/src/opa/rego/lib/criteria/spendingLimit.rego
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,28 @@ checkSpendingTimeWindow(timestamp, timeWindow) {
timestampNs >= time.now_ns() - secondsToNanoSeconds(timeWindow.value)
}

# Check By Operator

checkSpendingOperator(spendings, operator, limit) {
operator == operators.lessThan
spendings < limit
}

checkSpendingOperator(spendings, operator, limit) {
operator == operators.lessThanOrEqual
spendings <= limit
}

checkSpendingOperator(spendings, operator, limit) {
operator == operators.greaterThan
spendings > limit
}

checkSpendingOperator(spendings, operator, limit) {
operator == operators.greaterThanOrEqual
spendings >= limit
}

# Calculate Spending

calculateSpending(transfer, currency) = result {
Expand All @@ -105,6 +127,8 @@ checkSpendingLimit(params) {
conditions = object.union(
{
"currency": wildcard,
"limit": wildcard,
"operator": wildcard,
"timeWindow": {
"type": wildcard,
"value": wildcard, # in seconds
Expand All @@ -123,10 +147,12 @@ checkSpendingLimit(params) {
params,
)

limit = conditions.limit

currency = conditions.currency

limit = to_number(conditions.limit)

operator = conditions.operator

timeWindow = conditions.timeWindow

filters = conditions.filters
Expand Down Expand Up @@ -166,5 +192,5 @@ checkSpendingLimit(params) {
spending = calculateSpending(transfer, currency)
])

spendings + amount > to_number(limit)
checkSpendingOperator(spendings + amount, operator, limit)
}
2 changes: 1 addition & 1 deletion apps/authz/src/opa/rego/policies/e2e.rego
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ forbid[{"policyId": "exampleForbidPolicy"}] = reason {
checkWalletId({"eip155:eoa:0x90d03a8971a2faa19a9d7ffdcbca28fe826a289b"})
checkIntentType({"transferNative"})
checkIntentToken({"eip155:137/slip44:966"})
checkSpendingLimit({"limit": "1000000000000000000", "timeWindow": {"type": "rolling", "value": 43200}, "filters": {"tokens": ["eip155:137/slip44:966"], "users": ["matt@narval.xyz"]}})
checkSpendingLimit({"limit": "1000000000000000000", "operator": "gt", "timeWindow": {"type": "rolling", "value": 43200}, "filters": {"tokens": ["eip155:137/slip44:966"], "users": ["matt@narval.xyz"]}})
reason = {"type": "forbid", "policyId": "exampleForbidPolicy", "approvalsSatisfied": [], "approvalsMissing": []}
}
6 changes: 6 additions & 0 deletions apps/authz/src/opa/rego/policies/spendings.rego
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ forbid[{"policyId": "spendingLimitByRole"}] = reason {
checkIntentToken(tokens)
checkSpendingLimit({
"limit": limit,
"operator": operators.greaterThan,
"currency": currency,
"timeWindow": {
"type": "rolling",
Expand Down Expand Up @@ -57,6 +58,7 @@ forbid[{"policyId": "spendingLimitByUser"}] = reason {
checkIntentToken(tokens)
checkSpendingLimit({
"limit": limit,
"operator": operators.greaterThan,
"currency": currency,
"timeWindow": {
"type": "rolling",
Expand Down Expand Up @@ -89,6 +91,7 @@ forbid[{"policyId": "spendingLimitByWalletResource"}] = reason {
checkWalletId(resources)
checkSpendingLimit({
"limit": limit,
"operator": operators.greaterThan,
"currency": currency,
"timeWindow": {
"type": "rolling",
Expand Down Expand Up @@ -120,6 +123,7 @@ forbid[{"policyId": "spendingLimitByUserGroup"}] = reason {
checkIntentType(transferTypes)
checkSpendingLimit({
"limit": limit,
"operator": operators.greaterThan,
"currency": currency,
"timeWindow": {
"type": "rolling",
Expand Down Expand Up @@ -151,6 +155,7 @@ forbid[{"policyId": "spendingLimitByWalletGroup"}] = reason {
checkIntentType(transferTypes)
checkSpendingLimit({
"limit": limit,
"operator": operators.greaterThan,
"currency": currency,
"timeWindow": {
"type": "rolling",
Expand Down Expand Up @@ -191,6 +196,7 @@ permit[{"policyId": "spendingLimitWithApprovals"}] = reason {
checkIntentToken(tokens)
checkSpendingLimit({
"limit": limit,
"operator": operators.greaterThan,
"currency": currency,
"timeWindow": {
"type": "rolling",
Expand Down
1 change: 1 addition & 0 deletions apps/authz/src/opa/template/mockData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export const exampleForbidPolicy: Policy = {
criterion: Criterion.CHECK_SPENDING_LIMIT,
args: {
limit: '1000000000000000000',
operator: ValueOperators.GREATER_THAN,
timeWindow: {
type: 'rolling',
value: 12 * 60 * 60
Expand Down
4 changes: 4 additions & 0 deletions apps/authz/src/shared/types/policy.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,10 @@ export class SpendingLimitCondition {
@ApiProperty()
limit: string

@IsEnum(ValueOperators)
@ApiProperty({ enum: ValueOperators })
operator: ValueOperators

@IsOptional()
@IsEnum(FiatCurrency)
@ApiPropertyOptional({ enum: FiatCurrency })
Expand Down

0 comments on commit 1f687f9

Please sign in to comment.