0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-11 02:12:21 -05:00
ghost/core/server/api
Rishabh Garg e17f5004cc
🐛 Fixed unable to create new prices on switching Stripe account (#13013)
closes https://github.com/TryGhost/Team/issues/724
closes https://github.com/TryGhost/Team/issues/739

Currently, site owners are allowed to disconnect Stripe if they don't have any active subscriptions for a member. On disconnect, all stripe related data for the old account in DB should be cleared as using Stripe id for old account can cause weird failures due to incorrect Stripe key being used. This was also causing site owners to not be able to create new prices after connecting to new account as it ended up using old stripe product id which failed on Stripe request.
2021-06-08 21:28:16 +05:30
..
canary 🐛 Fixed unable to create new prices on switching Stripe account (#13013) 2021-06-08 21:28:16 +05:30
shared Moved i18n to shared 2021-05-04 13:03:38 +01:00
v2 Disallowed aditing "labs" settings in v2/v3 APIs 2021-06-08 02:18:17 +12:00
v3 Disallowed aditing "labs" settings in v2/v3 APIs 2021-06-08 02:18:17 +12:00
index.js Reordered API exports to improve readability 2021-03-04 11:27:09 +13:00
README.md

API Versioning

Ghost supports multiple API versions. Each version lives in a separate folder e.g. api/v2, api/v3, api/canary etc. Next to the API folders there is a shared folder, which contains shared code, which all API versions use.

Stages

Each request goes through the following stages:

  • input validation
  • input serialisation
  • permissions
  • query
  • output serialisation

The framework we are building pipes a request through these stages in respect of the API controller configuration.

Frame

Is a class, which holds all the information for request processing. We pass this instance by reference. Each function can modify the original instance. No need to return the class instance.

Structure

{
  original: Object,
  options: Object,
  data: Object,
  user: Object,
  file: Object,
  files: Array
}

Example

{
  original: {
    include: 'tags'
  },
  options: {
    withRelated: ['tags']
  },
  data: {
    posts: []
  }
}

API Controller

A controller is no longer just a function, it's a set of configurations.

Structure

edit: function || object
edit: {
  headers: object,
  options: Array,
  data: Array,
  validation: object | function,
  permissions: boolean | object | function,
  query: function
}

Examples

edit: {
  headers: {
    cacheInvalidate: true
  },
  // Allowed url/query params
  options: ['include']
  // Url/query param validation configuration
  validation: {
    options: {
      include: {
        required: true,
        values: ['tags']
      }
    }
  },
  permissions: true,
  // Returns a model response!
  query(frame) {
    return models.Post.edit(frame.data, frame.options);
  }
}
read: {
  // Allowed url/query params, which will be remembered inside `frame.data`
  // This is helpful for READ requests e.g. `model.findOne(frame.data, frame.options)`.
  // Our model layer requires sending the where clauses as first parameter.
  data: ['slug']
  validation: {
    data: {
      slug: {
        values: ['eins']
      }
    }
  },
  permissions: true,
  query(frame) {
    return models.Post.findOne(frame.data, frame.options);
  }
}
edit: {
  validation() {
    // custom validation, skip framework
  },
  permissions: {
    unsafeAttrs: ['author']
  },
  query(frame) {
    return models.Post.edit(frame.data, frame.options);
  }
}