Skip to content

Commit

Permalink
done
Browse files Browse the repository at this point in the history
  • Loading branch information
samteb committed Feb 8, 2024
1 parent 04a5f9d commit ecd1912
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { applyDecorators } from '@nestjs/common'
import { Matches, ValidationOptions } from 'class-validator'
import { IsDefined, Matches, ValidationOptions } from 'class-validator'

export function IsAccountId(validationOptions?: ValidationOptions) {
const regex = new RegExp('^eip155:d+/w+$')
return applyDecorators(Matches(regex, validationOptions))
return applyDecorators(IsDefined(), Matches(regex, validationOptions))
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { applyDecorators } from '@nestjs/common'
import { Matches, ValidationOptions } from 'class-validator'
import { IsDefined, Matches, ValidationOptions } from 'class-validator'

export function IsAssetId(validationOptions?: ValidationOptions) {
const regex = new RegExp('^(eip155:d+/(erc1155|erc20|erc721):w+/w+|eip155:d+/slip44:d+)$')
return applyDecorators(Matches(regex, validationOptions))
return applyDecorators(IsDefined(), Matches(regex, validationOptions))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { applyDecorators } from '@nestjs/common'
import { IsDefined, Matches, ValidationOptions } from 'class-validator'

export function IsHexString(validationOptions?: ValidationOptions) {
const regex = new RegExp('^0x[a-fA-F0-9]+$')
return applyDecorators(IsDefined(), Matches(regex, validationOptions))
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@ import { ArrayMinSize, IsArray, IsDefined, IsEnum } from 'class-validator'

export function IsNotEmptyArrayEnum(Enum: object) {
return applyDecorators(
IsDefined,
IsArray,
IsDefined(),
IsArray(),
IsEnum(Enum, { each: true }),
ApiProperty({
enum: Object.values(Enum),
isArray: true
}),
ArrayMinSize(1)
ArrayMinSize(1),
ApiProperty({ enum: Object.values(Enum), isArray: true })
)
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { applyDecorators } from '@nestjs/common';
import { ApiProperty } from '@nestjs/swagger';
import { IsDefined, IsArray, IsString, ArrayMinSize } from 'class-validator';
import { applyDecorators } from '@nestjs/common'
import { ApiProperty } from '@nestjs/swagger'
import { ArrayMinSize, IsArray, IsDefined, IsString } from 'class-validator'

export function IsNotEmptyArrayString() {
return applyDecorators(
IsDefined(),
IsArray(),
IsString({ each: true }),
ApiProperty({ type: String, isArray: true }),
ArrayMinSize(1)
);
}
ArrayMinSize(1),
ApiProperty({ type: String, isArray: true })
)
}
180 changes: 149 additions & 31 deletions packages/authz-shared/src/lib/type/policy-builder.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,21 @@ import {
} from '@narval/authz-shared'
import { Intents } from '@narval/transaction-request-intent'
import { ApiExtraModels, ApiProperty, getSchemaPath } from '@nestjs/swagger'
import { Transform, plainToInstance } from 'class-transformer'
import { IsDefined, IsIn, IsString, Matches, ValidateNested } from 'class-validator'
import { Transform, Type, plainToInstance } from 'class-transformer'
import {
IsBoolean,
IsDefined,
IsIn,
IsNotEmpty,
IsNumber,
IsNumberString,
IsOptional,
IsString,
ValidateNested
} from 'class-validator'
import { IsAccountId } from '../decorators/is-account-id.decorator'
import { IsAssetId } from '../decorators/is-asset-id.decorator'
import { IsHexString } from '../decorators/is-hex-string.decorator'
import { IsNotEmptyArrayEnum } from '../decorators/is-not-empty-array-enum.decorator'
import { IsNotEmptyArrayString } from '../decorators/is-not-empty-array-string.decorator'
import { ValidateCriterion } from '../decorators/validate-criterion.decorator'
Expand Down Expand Up @@ -68,59 +79,150 @@ export const Criterion = {

export type Criterion = (typeof Criterion)[keyof typeof Criterion]

export type AmountCondition = {
currency: `${FiatCurrency}` | '*'
operator: `${ValueOperators}`
export class AmountCondition {
@IsIn([...Object.values(FiatCurrency), '*'])
currency: FiatCurrency | '*'

@IsNotEmptyArrayEnum(ValueOperators)
operator: ValueOperators

@IsNotEmpty()
@IsNumberString()
value: string
}

export type ERC1155AmountCondition = {
export class ERC1155AmountCondition {
@IsAssetId()
tokenId: AssetId
operator: `${ValueOperators}`

@IsNotEmptyArrayEnum(ValueOperators)
operator: ValueOperators

@IsNotEmpty()
@IsNumberString()
value: string
}

export type SignMessageCondition = {
operator: `${ValueOperators.EQUAL}` | `${typeof IdentityOperators.CONTAINS}`
export class SignMessageCondition {
@IsIn([ValueOperators.EQUAL, IdentityOperators.CONTAINS])
operator: ValueOperators.EQUAL | IdentityOperators.CONTAINS

@IsNotEmpty()
@IsString()
value: string
}

export type SignTypedDataDomainCondition = {
export class SignTypedDataDomainCondition {
@IsOptional()
@IsNotEmptyArrayString()
@IsNumberString({}, { each: true })
version?: string[]

@IsOptional()
@IsNotEmptyArrayString()
@IsNumberString({}, { each: true })
chainId?: string[]

@IsOptional()
@IsNotEmptyArrayString()
name?: string[]

@IsOptional()
@IsNotEmptyArrayString()
@IsHexString({ each: true })
verifyingContract?: Address[]
}

export type PermitDeadlineCondition = {
operator: `${ValueOperators}`
export class PermitDeadlineCondition {
@IsNotEmptyArrayEnum(ValueOperators)
operator: ValueOperators

@IsNotEmpty()
@IsNumberString()
value: string // timestamp in ms
}

export type ApprovalCondition = {
export class ApprovalCondition {
@IsDefined()
@IsNumber()
approvalCount: number

@IsDefined()
@IsBoolean()
countPrincipal: boolean
approvalEntityType: `${EntityType}`

@IsDefined()
@IsIn(Object.values(EntityType))
approvalEntityType: EntityType

@IsNotEmptyArrayString()
entityIds: string[]
}

export type SpendingLimitCondition = {
export class SpendingLimitTimeWindow {
@IsIn(['rolling', 'fixed'])
type?: 'rolling' | 'fixed'

@IsNumber()
@IsOptional()
value?: number // in seconds

@IsNumber()
@IsOptional()
startDate?: number // in seconds

@IsNumber()
@IsOptional()
endDate?: number // in seconds
}

export class SpendingLimitFilters {
@IsNotEmptyArrayString()
@IsAccountId({ each: true })
@IsOptional()
tokens?: AccountId[]

@IsNotEmptyArrayString()
@IsOptional()
users?: string[]

@IsNotEmptyArrayString()
@IsAccountId({ each: true })
@IsOptional()
resources?: AccountId[]

@IsNotEmptyArrayString()
@IsNumberString({}, { each: true })
@IsOptional()
chains?: string[]

@IsNotEmptyArrayString()
@IsOptional()
userGroups?: string[]

@IsNotEmptyArrayString()
@IsOptional()
walletGroups?: string[]
}

export class SpendingLimitCondition {
@IsString()
@IsNotEmpty()
limit: string
currency?: `${FiatCurrency}`
timeWindow?: {
type?: 'rolling' | 'fixed'
value?: number // in seconds
startDate?: number // in seconds
endDate?: number // in seconds
}
filters?: {
tokens?: AccountId[]
users?: string[]
resources?: AccountId[]
chains?: string[]
userGroups?: string[]
walletGroups?: string[]
}

@IsIn(Object.values(FiatCurrency))
@IsOptional()
currency?: FiatCurrency

@ValidateNested()
@Type(() => SpendingLimitTimeWindow)
@IsOptional()
timeWindow?: SpendingLimitTimeWindow

@ValidateNested()
@Type(() => SpendingLimitFilters)
@IsOptional()
filters?: SpendingLimitFilters
}

class BaseCriterion {
Expand Down Expand Up @@ -287,14 +389,16 @@ class IntentHexSignatureCriterion extends BaseCriterion {
criterion: typeof Criterion.CHECK_INTENT_HEX_SIGNATURE

@IsNotEmptyArrayString()
@Matches(/^0x[a-fA-F0-9]+$/, { each: true })
@IsHexString({ each: true })
args: Hex[]
}

class IntentAmountCriterion extends BaseCriterion {
@ValidateCriterion(Criterion.CHECK_INTENT_AMOUNT)
criterion: typeof Criterion.CHECK_INTENT_AMOUNT

@ValidateNested()
@Type(() => AmountCondition)
args: AmountCondition
}

Expand All @@ -320,13 +424,17 @@ class ERC1155TransfersCriterion extends BaseCriterion {
@ValidateCriterion(Criterion.CHECK_ERC1155_TRANSFERS)
criterion: typeof Criterion.CHECK_ERC1155_TRANSFERS

@ValidateNested()
@Type(() => ERC1155AmountCondition)
args: ERC1155AmountCondition[]
}

class IntentMessageCriterion extends BaseCriterion {
@ValidateCriterion(Criterion.CHECK_INTENT_MESSAGE)
criterion: typeof Criterion.CHECK_INTENT_MESSAGE

@ValidateNested()
@Type(() => SignMessageCondition)
args: SignMessageCondition
}

Expand All @@ -350,20 +458,26 @@ class IntentDomainCriterion extends BaseCriterion {
@ValidateCriterion(Criterion.CHECK_INTENT_DOMAIN)
criterion: typeof Criterion.CHECK_INTENT_DOMAIN

@ValidateNested()
@Type(() => SignTypedDataDomainCondition)
args: SignTypedDataDomainCondition
}

class PermitDeadlineCriterion extends BaseCriterion {
@ValidateCriterion(Criterion.CHECK_PERMIT_DEADLINE)
criterion: typeof Criterion.CHECK_PERMIT_DEADLINE

@ValidateNested()
@Type(() => PermitDeadlineCondition)
args: PermitDeadlineCondition
}

class GasFeeAmountCriterion extends BaseCriterion {
@ValidateCriterion(Criterion.CHECK_GAS_FEE_AMOUNT)
criterion: typeof Criterion.CHECK_GAS_FEE_AMOUNT

@ValidateNested()
@Type(() => AmountCondition)
args: AmountCondition
}

Expand All @@ -385,13 +499,17 @@ class ApprovalsCriterion extends BaseCriterion {
@ValidateCriterion(Criterion.CHECK_APPROVALS)
criterion: typeof Criterion.CHECK_APPROVALS

@ValidateNested()
@Type(() => ApprovalCondition)
args: ApprovalCondition[]
}

class SpendingLimitCriterion extends BaseCriterion {
@ValidateCriterion(Criterion.CHECK_SPENDING_LIMIT)
criterion: typeof Criterion.CHECK_SPENDING_LIMIT

@ValidateNested()
@Type(() => SpendingLimitCondition)
args: SpendingLimitCondition
}

Expand Down

0 comments on commit ecd1912

Please sign in to comment.