Commit Graph

4927 Commits

Author SHA1 Message Date
Naz
33696b8244 Extracted scheduling token generation into separate module
refs https://github.com/TryGhost/Team/issues/694

- This is a tiny step towards more decoupled scheduler's code organization
2021-05-24 17:34:36 +04:00
Fabien O'Carroll
f4c40249ce Fixed members auth middleware
no-issue

The JWT library we used does not throw an error which can be used by
Ghost. So we need to catch and wrap it in our own errors from
@tryghost/errors.
2021-05-24 11:28:15 +01:00
Fabien O'Carroll
730811fb6e Handled week & day interval in population of mrr events
refs https://github.com/TryGhost/Team/issues/635

This is to ensure we don't break migrations for any sites which have
imported external subscriptions which have an interval of 'week' or
'day'

The bump to members-api includes the handling of these intervals for
ongoing population of mrr events
2021-05-21 17:57:17 +01:00
Naz
459e8215b9 Split data exporter's index file into separate module
refs https://github.com/TryGhost/Team/issues/610

- This is a next step removing bloat from export module's index.js file, which get's rid of eslisn error completely
2021-05-21 19:13:55 +04:00
Naz
79439bdac5 Extracted table allowlists into a separate module
refs https://github.com/TryGhost/Team/issues/610

- Before introducing a new test for the refed issue doing a linting cleanup. The result will be removing one of `File has too many lines ` lint warnings
2021-05-21 19:13:55 +04:00
Thibaut Patel
1d5c8ccf2b Fix the OAuth callback
https://github.com/TryGhost/Team/issues/614

By binding the user session to the Ghost instance domain
2021-05-21 10:50:03 +02:00
Thibaut Patel
55a0c69451 Added the customThemes limits to all api versions
https://github.com/TryGhost/Team/issues/663
2021-05-21 09:56:22 +02:00
Fabien O'Carroll
f4017cc439 🐛 Fixed creating members linked to stripe customers
closes https://github.com/TryGhost/Ghost/issues/12942

The signature of the `linkStripeCustomer` method was updated and this
usage was missed.
2021-05-20 13:44:35 +01:00
Fabien O'Carroll
17a2083c05 Added precondition for Stripe Connect Admin API
refs https://github.com/TryGhost/Team/issues/598

Stripe Webhooks require SSL in production, and so we should not be
allowing connecting to Stripe in production mode unless the site is
running with SSL.
2021-05-20 12:08:45 +01:00
Fabien O'Carroll
5cdf910e63 Checked boot preconditions in members service init
refs https://github.com/TryGhost/Team/issues/598

We now have several pre-conditions related to members which determine
whether or not Ghost is allowed to start. Rather than burying this
within the members-api module, we have now surfaced them to an init
method which can be called during the boot sequence of Ghost. This will
allow us to exit early and explicitly.
2021-05-20 12:08:45 +01:00
Fabien O'Carroll
3f6544bebc Renamed index.js -> service.js for lint reasons
no-issue

Our linter now requires that files named index.js have less than 50
lines, so this renames the index.js file to service.js and reexports
service.js from index.js so that linting will pass.
2021-05-20 12:08:45 +01:00
Hannah Wolfe
05a16948a3
Moved testmode routes into a correctly named file
- testmode routing was in an index.js file, this breaks our coding standards
- these routes belong in routes file, same as all other routes
2021-05-20 11:42:27 +01:00
Fabien O'Carroll
5880edd722 Replaced members 'comped' status with 'paid'
refs https://github.com/TryGhost/Team/issues/693

Since we've got rid of the concept of Complimentary with the Custom
Prices work, we're removing the 'comped' status from members. This
involves a migration for existing members, a schema update for the
validation, and a bump to members-api to no longer use the 'comped'
status for new members.

We also update the aggregation of the MemberStatusEvent to consider the
'comped' status as 'paid', and that there are 0 'comped' status events
in the database.

We can consider a migration for this data in the future, either adding
new status events moving from 'comped' to 'paid', or by modifying
existing status events. However both of these are very difficulty to
write a down migration for, and might be best saved for a major version.

- @tryghost/members-api@1.7.0 is the version that includes the required
  changes, however we have already bumped to 1.8.0 in Ghost
2021-05-19 18:49:18 +01:00
Fabien O'Carroll
278ad8eaea Updated comped flag for v3 Members Admin API
refs https://github.com/TryGhost/Team/issues/693

Since we no longer have the concept the "comped" we update the v3 API to
always have a `comped` flag of `false` - maintaining backwards
compatibility.
2021-05-19 18:49:18 +01:00
Fabien O'Carroll
57a176ff3d Removed comped flag from canary Members Admin API
refs https://github.com/TryGhost/Team/issues/693

Since we no longer have a concept of "comped" we're removing the flag
from the unstable canary api.
2021-05-19 18:49:18 +01:00
Rishabh
5cabc39124 Fixed products data in members api on changing comped status
refs a4c78dbf19

Updates member data on edit to include products data when comped status is changed, as by default we don't include products data when member goes from free to paid subscription due to comped being added.
2021-05-19 23:14:04 +05:30
Rishabh
a4c78dbf19 🐛 Fixed error on saving member with susbcriptions
closes https://github.com/TryGhost/Team/issues/699

With custom products, saving a member with subscriptions on member detail page in Admin throws errors on console, though the save is successful. This breaks the Admin as user needs to refresh the screen again to get rid of error. This change -

- updates the response on member save to return `price` object in subscription
- updates tests
2021-05-19 22:32:15 +05:30
Thibaut Patel
2bcc934eb4 Disable CSRF on the oauth callback route
no issue

Keeping CSRF enabled there would prevent oauth from working as users are redirected from the provider domain to the /callback route, where they are logged-in
2021-05-18 20:44:21 +02:00
Rishabh
2e8db93ab6 Filtered selected prices in Portal settings
no refs

Filters active prices in Portal settings to only contain the selected prices by site owner in new monthly/yearly price id settings, ignoring all other prices for now.
2021-05-18 20:27:20 +05:30
Hannah Wolfe
d9367f5b20
Added debug to gscan checks for timings
- added a couple of extra debug calls to see how long gscan checks take in the boot process
2021-05-18 15:22:04 +01:00
Rishabh
4627d1c26a Added settings for monthly/yearly price ids
no refs

Since backend now allows multiple prices but we want the prices to be currently limited to monthly/yearly on UI, we need new settings to store the current monthly/yearly price by the site owner. These settings determine the active prices shown in Admin / Portal for the site till we allow all custom products/prices again.
2021-05-18 13:34:31 +05:30
Kevin Ansfield
84724537be 🐛 Fixed feature images in emails appearing very wide in Outlook
closes https://github.com/TryGhost/Team/issues/675

Outlook will display images at their native resolution if no `width` attribute is supplied. Content images were fixed a while ago but feature images would still render very wide and cause horizontal scroll and text size/alignment issues.

- modify `post.feature_image` and add a `post.feature_image_width` property before passing it through to the email template
  - for Unsplash images we assume all images are larger than 600px so we change the URL to reference a 1200px image and set the image width to 600 (to keep images on retina displays crisp)
  - for other images we probe the image to fetch the original dimensions and give set an image width of 600 if needed, if it's a locally-hosted image we update the URL to point at a max 1200px version
- updated email template to output a `width` attribute on the feature image `<img>` tag if it's set
2021-05-14 11:57:37 +01:00
Kevin Ansfield
7070572e4f Moved getLocalSize() from mobiledoc to image-size lib
no issue

- `getLocalSize()` is useful outside of the mobiledoc populate-image-sizes function
- expanded `ImageSize` class with new methods
  - `getOriginalImageSizeFromStoragePath()` - takes the "original" image extraction and test from `getLocalSize()` and makes it more generally available
  - `getImageSizeFromStorageUrl()` - takes the path extraction from `getLocalSize()` to make image sizes from local urls more generally available
  - `getOriginalImageSizeFromStorageUrl()` - URL version of the new `getOriginalImageSizeFromStoragePath()` method
2021-05-14 11:57:37 +01:00
Thibaut Patel
14cae4b154 Added notes to oauth code for future improvements
no issue
2021-05-14 12:10:27 +02:00
Rishabh
196cdafe6b 💡 Removed 401 error for logged-out member on Portal
closes https://github.com/TryGhost/Team/issues/560
closes https://github.com/TryGhost/Ghost/issues/12870

The endpoint `/members/api/member/` is used by Portal for fetching member details on site load to setup different flows. The response from this endpoint for logged out member has now changed from 401 Unauthorized to 204 No Content.

Ghost API was previously returning 401 Unauthorized error for logged-out member as this seemed to be technically correct response for unauthorized access to membership features. This resulted in a lot of confusion for end users where visible 401 errors on console were perceived as errors in the script as well as caught by loggers as erroneous traffic. Also for an end user, in the context of visiting a website - the user themselves is not trying to gain access to anything so this becomes cause for more confusion.

After internal discussion, the endpoint - [SITE_URL]/members/api/member- now returns 204 No Content instead of 401 for logged out member, denoting server was able to process the request but did not find any associated member. This should avoid any unwanted error logging on Portal load on a site, as well as make Portal functioning more transparent for a site.
2021-05-13 15:26:07 +05:30
Naz
ec01c4f004 Fixed typos 2021-05-12 17:06:10 +04:00
Fabien O'Carroll
41acc37865 Made complimentary_plan & stripe_customer_id exclusive
no-issue

When importing Members it is possible to have both the
complimentary_plan and the stripe_customer_id columns set, this can
result in unusual outcomes, for example when importing a customer with a
zero-amount subscription, they would end up with two "comped"
subscriptions, and there would be two "comped" prices in the database.

As we are deprecating the use of "comped" in favour of creating a
subscription with a specific price, we're updating the import to prefer
`stripe_customer_id` column, only using the `complimentary_plan` column
when it is the only of the two columns passed.
2021-05-11 12:33:28 +01:00
Kevin Ansfield
c36e749820
Added support for gating content by member labels and products (#12946)
refs https://github.com/TryGhost/Team/issues/581
closes https://github.com/TryGhost/Team/issues/582

Emails can now be sent to members with specific associated labels or products by specifying an NQL string. We want to bring the same members segment feature to content by allowing `visibility` to be an NQL filter string on top of the `public/members/paid` special-case strings.

As an example it's possible to set `posts.visibility` to `label:vip` to make a post available only to those members with the `vip` label.

- removed enum validations for `visibility` so it now accepts any string or `null`
    - bumped `@tryghost/admin-api-schema` for API-level validation changes
- added nql validation to API input validators by running the visibility query against the members model
- added transform of NQL to special-case visibility values when saving post model
    - ensures there's a single way of representing "members" and "paid" where NQL gives multiple ways of representing the same segment
    - useful for keeping theme-level checks such as `{{#has visibility="paid"}}` working as expected
- updated content-gating to parse nql from post's visibility and use it to query the currently logged in member to see if there's a match
    - bumped @tryghost/members-api to include label and product data when loading member
2021-05-10 19:32:11 +01:00
Rishabh
cfaddf82e8 Added migration to rename product as site title
refs https://github.com/TryGhost/Team/issues/667

On clean and existing installs, the default product created should be named the same as the site title in the first setup so the UX on Portal and everywhere is consistent. This change adds a migration to update existing sites which already have a default product created via fixture, and rename them to their current site title. The rename is only done if the Product name is still the same as in fixture - `Default Product`.
2021-05-11 00:00:12 +05:30
Rishabh
c199918465 Updated free price default description
refs https://github.com/TryGhost/Team/issues/648

We use sentence case everywhere for labels, the default description for free price should be the same
2021-05-10 18:24:36 +05:30
Rishabh
2497af0072 Updated default description for free price
refs https://github.com/TryGhost/Team/issues/671

When turning on custom products, existing sites should have default price descriptions that match existing values for prices. This change sets the default description for Free price to match existing hardcoded value.
2021-05-10 14:19:02 +05:30
Rishabh
4d4286d255 Updated setup flow to rename default product
refs https://github.com/TryGhost/Team/issues/667

On clean and existing installs, the default product created should be named the same as the site title instead of the name in fixture. This change updates the default product's name to site title during the site setup. We use the Product name in Portal.
2021-05-10 13:59:00 +05:30
Rishabh
67ea6c44ef Added free price values to Portal site settings
refs https://github.com/TryGhost/Team/issues/637

With custom products it's possible to change the name and description of any price. This assumes that people would want to change the same properties of a Free membership, and wires up the values for free membership price settings to Portal site settings API for Portal UI
2021-05-07 22:56:16 +05:30
Fabien O'Carroll
6106d1fdc4 Updated active column type from boolean -> bool
no-issue

Our base model will only automatically convert numbers to booleans if
the type is 'bool' - however this column was incorrectly added with a
type of 'boolean'. Lucklily - knex with both MySQL & SQLite3 will add
a column with the same type for both of these, so no migration is needed
to fix it.
2021-05-07 16:37:38 +01:00
Fabien O'Carroll
b35f060bef Added settings for members 'free' price
refs https://github.com/TryGhost/Team/issues/637

The "free" price - when Members signup without using Stripe, should have
a name and description, so that it can be displayed in Portal in a
similar way to paid price's. As there is only ever one, and it is not a
fully fledged price, a setting makes more sense than a dedicated db
table.
2021-05-07 16:32:12 +01:00
Fabien O'Carroll
a138586c83 Updated stripe_plans & portal_plans settings
refs https://github.com/TryGhost/Team/issues/586

We are no longer using the `stripe_plans` setting, instead we are using
the `stripe_prices` database table. However, we must keep the setting as
the migration from the setting to the database is not done as a standard
migration, but in code. This means our code has to still read and pass
the setting because we will never know if the migration in code has run
yet.

The `portal_plans` setting has been updated to only include 'free' by
default, because the setting must include id's now rather than names.
2021-05-07 16:31:08 +01:00
Naz
fc458efa90 Added periodic "emails" limit check when (re)sending a newsletter
refs https://github.com/TryGhost/Team/issues/588
refs d72ba77aba

- When limit is in place we don't want to allow sending out a new batch of emails if it would go over limit
- See referenced commit for example configuration
2021-05-07 18:45:14 +04:00
Naz
d72ba77aba Added support for max periodic limit check
refs https://github.com/TryGhost/Team/issues/588

- This is a new type of limit allowing to measure resource use (e.g. sent emails) per period (e.g. subscription, billing, cycle, etc)
- To enable periodical limit add  following values under `hostSettings.limits`:
```
"emails": {
    "maxPeriodic": 10,
    "error": "Your plan supports up to {{max}} emails. Please upgrade to reenable sending emails."
}
```
and following under `hostSettings.subscription`:
```
"subscription": {
    "start": "2020-04-02T15:53:55.000Z",
    "interval": "month"
}
```
- Above config would allow checking if 10 emails per month starting on the 2nd of every month has been reached untill now
2021-05-07 18:43:47 +04:00
Rishabh
fbd03525b0 Filtered active prices in portal settings
refs https://github.com/TryGhost/Team/issues/665

Portal only needs to work with active prices(not archived), this change filters prices sent to Portal to only include active prices
2021-05-07 19:12:22 +05:30
Fabien 'egg' O'Carroll
e9687d359d
Removed unique constraint from Product names (#12928)
refs https://github.com/TryGhost/Team/issues/586

A discussion in the Members team resulted in us determining that we do
not need to enforce unique names for Products. Stripe does not enforce
uniqueness for their Products, and we feel it's not necessary for us to.
2021-05-07 13:34:23 +01:00
Daniel Lockyer
b1499d4037 Extracted package-json lib to Utils
refs 37ebe723c6

- `package-json` was a standalone library using dependency injection so
  we could pull it out into its own package in Utils
- this was done in the commit referenced above
- this commit removes the implementation and tests in Ghost and replaces
  the require in the initialization wrapper with the new package
2021-05-07 12:35:06 +01:00
Kevin Ansfield
322664a145
Added ability to send a newsletter to members with a certain label or product (#12932)
refs https://github.com/TryGhost/Team/issues/581
refs https://github.com/TryGhost/Team/issues/582

When publishing a post via the API it was possible to send it using `?email_recipient_filter=all/free/paid` which allowed you to send to members only based on their payment status which is quite limiting for some sites.

This PR updates the `?email_recipient_filter` query param to support Ghost's `?filter` param syntax which enables more specific recipient lists, eg:

`?email_recipient_filter=status:free` = free members only
`?email_recipient_filter=status:paid` = paid members only
`?email_recipient_filter=label:vip` = members that have the `vip` label attached
`?email_recipient_filter=status:paid,label:vip` = paid members and members that have the `vip` label attached

The older `free/paid` values are still supported by the API for backwards compatibility.

- updates `Post` and `Email` models to transform legacy `free` and `paid` values to their NQL equivalents on read/write
  - lets us not worry about supporting legacy values elsewhere in the code
  - cleanup migration to transform all rows slated for 5.0
- removes schema and API `isIn` validations for recipient filters so allow free-form filters
- updates posts API input serializers to transform `free` and `paid` values in the `?email_recipient_filter` param to their NQL equivalents for backwards compatibility
- updates Post API controllers `edit` methods to run a query using the supplied filter to verify that it's valid
- updates `mega` service to use the filter directly when selecting recipients
2021-05-07 11:56:41 +01:00
Kevin Ansfield
1ee97ccfbc
Fixed editors not being able to read labels when assigning member segments (#12934)
refs https://github.com/TryGhost/Team/issues/581

Editors are allowed to restrict post visibility and send emails to particular member segments, they need to be able to read labels so that they can select them in a member segment.
2021-05-07 10:51:44 +01:00
Rishabh
6c2869db61 Updated products/prices data in member site settings
refs https://github.com/TryGhost/Team/issues/637
refs 75169b705b

With custom prices, Portal now needs to show all available custom prices in the UI as well as product's name and description in the Portal UI. This change adds product information to member site settings for Portal UI.
2021-05-07 15:15:10 +05:30
Rishabh
5628bb5f5a Updated price serialisation on subscription
refs https://github.com/TryGhost/Team/issues/586
refs aa12770329

Using `id` as ghost id for subscription prices can be confusing as everything in the method refers ids to be stripe ids. This change updates the ghost id value to use `price_id` key in the serialization
2021-05-07 15:15:10 +05:30
Kevin Ansfield
b08b95085e
Added default email recipients settings (#12925)
refs https://github.com/TryGhost/Team/issues/496

We want to give more control over the default selection of email recipients when publishing a post, to do that we need somewhere to store those settings. These settings are site-wide and intended for use by admins to control the default editor behaviour for all staff users. They _do not_ control API behaviour, if you want to send email when publishing via the API it's still necessary to explicitly opt in to that using the `?email_recipients_filter=` query param.

- new `editor` settings group to indicate that these settings only affect the UI rather than the API
- `editor_default_email_recipients` controls overall behaviour, string/enum with these allowed values:
  - `'disabled'`: no option to send email is shown in the editor's publishing dropdown
  - `'visibility'`: (default) selected member segment is dynamic and matches the post visibility filter
  - `'filter'`: specific member filter defined in `editor_default_email_recipients_filter` setting
- `editor_default_email_recipients_filter` is an NQL string for selecting members, used when `editor_default_email_recipients` is set to `'filter'`
  - default value is `'all'`
  - the segment string can be any valid NQL filter with the additional special-case values of `'all'` and `'none'`
2021-05-07 09:30:57 +01:00
Daniel Lockyer
a2f9204069
Changed Error to IncorrectUsageError in package-json
no issue

- `Error` is very generic for this case and `IncorrectUsageError`
  will populate the resulting error with the correct error code
- the `message` was pulled out to its own statement so we can avoid long
  lines
2021-05-06 13:22:59 +01:00
Daniel Lockyer
4e69f24964
Moved package-json wrapper outside implementation folder
no issue

- we're preparing the `package-json` lib to be extracted out of Ghost into
  its own package so moving the initialization wrapper outside of the
  folder makes the process a lot easier
2021-05-06 12:56:21 +01:00
Rishabh
aa12770329 Updated price id in subscription serialization
refs https://github.com/TryGhost/Team/issues/586
refs 33f26fbf32

As part of serializing subscriptions with prices, we previously attached only the stripe price id to the price object for subscription. This change updates the price object to include both Ghost id and stripe price id for the object, as Portal needs to check the Ghost price id for logged in members to verify their current plan.
2021-05-06 17:03:52 +05:30
Hannah Wolfe
01d9701096 Fixed i18n being called outside of a function
- calling i18n as a global const like this requires it to be loaded before anything else, when we have to manage this with the init() flow
- wrapping it inside the function where it's used ensures we don't call i18n til we need it
- also improved the i18n called without init error to include the key it was called with
2021-05-05 16:34:40 +01:00