Skip to content

Leaking JS Error when uploading a contract #20

@pgmarc

Description

@pgmarc

Given

  • SPACE is up and running in localhost
  • You have an ADMIN API key
  • Given the following Pricing2Yaml file named example.yml:
saasName: Petclinic
createdAt: "2025-03-26"
syntaxVersion: "3.0"
currency: USD
features:
  pets:
    valueType: BOOLEAN
    defaultValue: true
    expression: pricingContext['features']['pets'] && subscriptionContext['maxPets'] < pricingContext['usageLimits']['maxPets']
    serverExpression: pricingContext['features']['pets'] && subscriptionContext['maxPets'] < pricingContext['usageLimits']['maxPets']
    type: DOMAIN
  visits:
    valueType: BOOLEAN
    defaultValue: true
    expression: pricingContext['features']['visits'] && subscriptionContext['maxVisits'] < pricingContext['usageLimits']['maxVisits']
    serverExpression: pricingContext['features']['visits'] && subscriptionContext['maxVisits'] <= pricingContext['usageLimits']['maxVisits']
    type: DOMAIN
  calendar:
    valueType: BOOLEAN
    defaultValue: false
    expression: pricingContext['features']['calendar'] && subscriptionContext['calendarEventsCreationLimit'] < pricingContext['usageLimits']['calendarEventsCreationLimit']
    type: DOMAIN
  vetSelection:
    valueType: BOOLEAN
    defaultValue: false
    expression: pricingContext['features']['vetSelection']
    type: DOMAIN
  consultations:
    valueType: BOOLEAN
    defaultValue: false
    expression: pricingContext['features']['consultations']
    type: DOMAIN
  petsDashboard:
    valueType: BOOLEAN
    defaultValue: false
    expression: pricingContext['features']['petsDashboard']
    type: DOMAIN
  lowSupportPriority:
    valueType: BOOLEAN
    defaultValue: true
    expression: pricingContext['features']['lowSupportPriority']
    type: SUPPORT
  mediumSupportPriority:
    valueType: BOOLEAN
    defaultValue: false
    expression: pricingContext['features']['mediumSupportPriority']
    type: SUPPORT
  highSupportPriority:
    valueType: BOOLEAN
    defaultValue: false
    expression: pricingContext['features']['highSupportPriority']
    type: SUPPORT
  slaCoverage:
    valueType: TEXT
    defaultValue: "99%"
    expression: pricingContext['features']['slaCoverage'] === pricingContext['features']['slaCoverage']
    type: GUARANTEE
  petAdoptionCentre:
    valueType: BOOLEAN
    defaultValue: false
    expression: pricingContext['features']['petAdoptionCentre']
    type: DOMAIN
  smartClinicReports:
    valueType: BOOLEAN
    defaultValue: false
    expression: pricingContext['features']['smartClinicReports']
    type: DOMAIN
usageLimits:
  maxPets:
    valueType: NUMERIC
    defaultValue: 2
    unit: pet
    type: NON_RENEWABLE
    trackable: true
    linkedFeatures:
      - pets
  maxVisits:
    valueType: NUMERIC
    defaultValue: 1
    unit: visit
    type: RENEWABLE
    period:
      value: 1
      unit: MONTH
    linkedFeatures:
      - visits
  calendarEventsCreationLimit:
    valueType: NUMERIC
    defaultValue: 5
    unit: event
    type: RENEWABLE
    period:
      value: 1
      unit: MONTH
    linkedFeatures:
      - calendar
plans:
  BASIC:
    price: 0.0
    unit: user/month
    features: null
    usageLimits: null
  GOLD:
    price: 5.0
    unit: user/month
    features:
      calendar:
        value: true
      vetSelection:
        value: true
      slaCoverage:
        value: "99.5%"
      mediumSupportPriority:
        value: true
    usageLimits:
      maxPets:
        value: 4
      maxVisits:
        value: 3
      calendarEventsCreationLimit:
        value: 15
  PLATINUM:
    price: 12.0
    unit: user/month
    features:
      calendar:
        value: true
      vetSelection:
        value: true
      consultations:
        value: true
      slaCoverage:
        value: "99.9%"
      mediumSupportPriority:
        value: true
      highSupportPriority:
        value: true
    usageLimits:
      maxPets:
        value: 7
      maxVisits:
        value: 6
      calendarEventsCreationLimit:
        value: 50
addOns:
  petLover:
    availableFor:
    - BASIC
    - GOLD
    - PLATINUM
    price: 100.00
    usageLimits:
      maxPets:
        value: 30
  extraPets:
    availableFor:
    - BASIC
    - GOLD
    - PLATINUM
    price: 25.00
    usageLimitsExtensions:
      maxPets:
        value: 1
    subscriptionConstraints:
      minQuantity: 1
      maxQuantity: 10
      quantityStep: 1
  extraVisits:
    availableFor:
    - BASIC
    - GOLD
    - PLATINUM
    price: 10.00
    usageLimitsExtensions:
      maxVisits:
        value: 1
    subscriptionConstraints:
      minQuantity: 3
      maxQuantity: .inf
      quantityStep: 3
  petDashboard:
    availableFor:
    - PLATINUM
    price: 5.95
    features:
      petsDashboard:
        value: true
  petAdoptionCentre:
    availableFor:
    - BASIC
    - GOLD
    - PLATINUM
    price: 15.95
    features:
      petAdoptionCentre:
        value: true
  smartClinicReports:
    availableFor:
    - PLATINUM
    dependsOn:
      - petDashboard
    price: 3.95
    features:
      smartClinicReports:
        value: true

Upload the previous pricing to SPACE (POST /api/v1/services)

curl -H 'x-api-key: <your_api_key>' \
  --form [email protected] \
  http://localhost:5403/api/v1/services

When

Creating a new contract (POST /api/v1/contracts) with the following body. Notice that the body has a typo in subscriptionAddOns.petclinic instead of petAdoptionCentre the user typed petsAdoptionCentre.

curl -H 'x-api-key: <your_api_key>' \
  http://localhost:5403/api/v1/contracts \
  --json @- << EOF
{
  "userContact": {
    "userId": "72ee0357-e34b-4d8f-9e0f-b710391cb298",
    "username": "petclinicuser01"
  },
  "billingPeriod": {
    "autoRenew": true,
    "renewalDays": 365
  },
  "contractedServices": {
    "petclinic": "2025-3-26"
  },
  "subscriptionPlans": {
    "petclinic": "GOLD"
  },
  "subscriptionAddOns": {
    "petclinic": {
      "petsAdoptionCentre": 1
    }
  }
}
EOF

Then

The following JSON reponse is received:

{"error":"Invalid subscription: TypeError: Cannot read properties of undefined (reading 'dependsOn')"}

Leaking an internal JS error TypeError: Cannot read properties of undefined (reading 'dependsOn').

An alternative 4XX and error response shold be returned.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions