Commit Graph

814 Commits

Author SHA1 Message Date
Kevin Ansfield
47e81e3ca1 Fixed error when creating emails when track opens is disabled
no issue

- ensure `email.track_opens` is a boolean rather than `null`
2020-11-25 08:08:15 +00:00
Kevin Ansfield
7bbbeeb5b0 Fixed linting 2020-11-23 19:58:34 +00:00
Kevin Ansfield
a8d8598003 Updated mega service to use open tracking from settings
refs https://github.com/TryGhost/Ghost/issues/12390

- switched from enabling open tracking based on `enableDeveloperExperiments` to using the track-opens setting
2020-11-23 18:53:55 +00:00
Kevin Ansfield
4c96aa5c95 Fixed bulk email only having 'bulk-email' tag in certain circumstances
no issue

- the `'bulk-email`' tag was only being added to bulk emails if another more specific tag was set up via config
- we always want the `'bulk-email'` tag to be present for better event filtering
2020-11-23 18:34:17 +00:00
Peter Zimon
bf9820f97d Fixed sans-serif link style
no refs.
- fixed regression that links in emails with sans-serif setting wasn't underlined
2020-11-23 15:50:02 +01:00
Fabien 'egg' O'Carroll
f8b617af64
Supported redirecting externally after signup (#12391)
refs #12391

Adds support for redirecting to external URL's after successful signup for members.
2020-11-23 09:36:45 +00:00
Thibaut Patel
5fefa9fe96 Disabled Personal Tokens of inactive/locked users
no issue
2020-11-20 09:53:18 +01:00
Thibaut Patel
be4146e324 Enabled authentication using an api key with a user_id
no issue

- Enables the Personal Tokens feature.
2020-11-20 09:53:18 +01:00
Fabien 'egg' O'Carroll
38d19c999d
Removed search params from custom signup redirects (#12386)
refs #12366

This means that custom redirects will not trigger the built in notifications handled by Portal.
2020-11-19 14:47:08 +00:00
Fabien 'egg' O'Carroll
9ba3e96790
Redirected to custom path on successful signup (#12372)
refs #12366 

This implements redirection based on the settings for successful member sign up!
- Removes support for redirecting to `req.path` afterwards, this was never used and
  we now have a more configurable implementation.
- Retains redirection to the homepage for unsuccessful sign up (invalid/expired token)
2020-11-19 09:58:32 +00:00
Peter Zimon
02d78a89aa Udpated email template footer spacings
no refs.
- updated padding between Ghost badge and rest of the footer
2020-11-16 12:31:37 +01:00
Peter Zimon
cfac18cb32 Newsletter email template refinements
no refs.
- updated color styles, links for footer text
- refined spacings for email footer paragraphs
2020-11-13 16:58:56 +01:00
Fabien 'egg' O'Carroll
3f9053ae94
Added setting for newsletter footer content (#12359)
no-issue

We want to give users to ability to customise the content of their newsletter, and the first step
toward that is a setting in which we can store text or html to embed in the template
2020-11-13 13:18:47 +00:00
Peter Zimon
215bfd0a7a
Added newsletter design settings (#12352)
refs https://github.com/TryGhost/Ghost/issues/12355

- Adds new default settings for newsletter customisations - `newsletter_show_badge`, `newsletter_show_header` and `newsletter_body_font_category`
- Adds migrations to update group for new settings
- Add migration to update settings based on existing config value for newsletter settings
- Passes new newsletter settings to newsletter template and updates design based on them
- Fix tests
2020-11-11 18:26:11 +05:30
Fabien 'egg' O'Carroll
6140a98351
Updated newsletter functionality to use email_recipient_filter (#12343)
no-issue

* Used email_recipient_filter in MEGA

This officially decouples the newsletter recipients from the post
visibility allowing us to send emails to free members only

* Supported enum for send_email_when_published in model

This allows us to migrate from the previously used boolean to an enum
when we eventually rename the email_recipient_filter column to
send_email_when_published

* Updated the posts API to handle email_recipient_filter

We now no longer rely on the send_email_when_published property to send
newsletters, meaning we can remove the column and start cleaning up the
new columns name

* Handled draft status changes when emails not sent

We want to reset any concept of sending an email when a post is
transition to the draft status, if and only if, and email has not
already been sent. If an email has been sent, we should leave the email
related fields as they were.

* Removed send_email_when_published from add method

This is not supported at the model layer

* Removed email_recipient_filter from v2&Content API

This should not be exposed on previous api versions, or publicly

* Removed reference to send_email_when_published

This allows us to move completely to the email_recipient_filter
property, keeping the code clean and allowing us to delete the
send_email_when_published column in the database. We plan to then
migrate _back_ to the send_email_when_published name at both the
database and api level.
2020-11-06 17:32:23 +00:00
Fabien O'Carroll
44b43a4755 Fixed error with removal of global.Promise override
refs #12182

These were missed in the cleanup and were causing errors.
2020-11-06 16:49:10 +00:00
Fabien O'Carroll
0ce8e3171b Bound SSOAdapter methods to their instance
no-issue

This allows custom SSO adapters to store instance config and refer to
in their methods
2020-11-05 13:08:11 +00:00
Kevin Ansfield
aface9ed4c Enabled Mailgun open tracking when dev experiments is enabled
no issue

- set `emails.track_opens` to `true` when the `enableDeveloperExperiments` flag is set
- update mailgun bulk-email provider to pass the open-tracking header to Mailgun when the email's `track_opens` flag is set
2020-11-05 12:55:08 +00:00
Kevin Ansfield
7a74b78940 Included email-id as user variable when sending bulk emails via mailgun
no issue

- adding user variables via the mailgun API when sending emails means that events related to email have those variables attached to them
- adding the `email.id` value to user variables means we can easily associate mailgun events to emails, otherwise we'd have look up the batch via `email_batches.provider_id` then use a join to get back to the associated email
2020-10-29 16:37:42 +00:00
Rish
c4c6bdf353 Updated mail template for member email change
no issue

The email change verification template was using the same as for `subscribe`, which did not have the right messaging that needs to be communicated about the action thats happening in this case. Updates the email template to same as what we use for email verification for support/newsletter address
2020-10-29 17:40:19 +05:30
Rish
746ccbd7ed Added custom action param for magic links
closes https://github.com/TryGhost/Ghost/issues/12253

- Allows using custom action param for requests from Portal by using a new `requestSrc` option that is passed down when a request for magic link is made via Portal
2020-10-29 13:42:52 +05:30
Peter Zimon
43b7c7b344
Updated members admin redirect to new page(#12296)
no refs.

- Members settings were moved to a new page [here](https://github.com/TryGhost/Ghost-Admin/pull/1736)
- updated members related redirect for from/newsletter email address change to point to new page
2020-10-22 16:10:25 +05:30
naz
8ddf83f3c5
Fixed "no-shadow" linting error in server modules (#12287)
refs 143921948d

- Continuation of changes started in referenced commit
2020-10-20 12:02:56 +13:00
Rish
54e638310c Added default support address for member site data
no issue

- In a case where support address is null, member's site data won't load as there was no fallback.
- The fix adds default `noreply` as the support address for site data
2020-10-15 14:44:16 +05:30
Kevin Ansfield
cde364bf27 🐛 Fixed email card replacements showing raw replacement text in emails
closes https://github.com/TryGhost/Ghost/issues/12257

- there was a destructuring problem introduced in the recent email refactor which meant the correct replacement data was not being passed over to the Mailgun provider when sending email
2020-10-05 17:24:48 +01:00
Kevin Ansfield
4f211d025d Fixed members with multiple subscriptions receiving multiple newsletters
closes https://github.com/TryGhost/Ghost/issues/12259

- adds a `DISTINCT` to the query used to fetch member rows when generating an email recipient list
- this increases query time 2.7s vs 1.6s locally with ~94k paid members but once the `members.paid` column is implemented this slow query can be removed
2020-10-05 16:53:35 +01:00
Kevin Ansfield
8f3ab3c535 🐛 Fixed email showing as success when an email batch fails to send
no issue

- fixed passing of errors up through send/processBatch/processEmail
- fixed errant overwrite of email status with a "submitted" status after a failure had occurred
2020-10-02 14:26:57 +01:00
Kevin Ansfield
b5ffb38726 Fixed partial email batch/recipient records when email creation fails
no issue

- wrap email batch/recipient record creation in a transaction so if an error occurs during creation we're not left with a partially created batch/recipient set in the database
2020-10-02 13:47:14 +01:00
Kevin Ansfield
0f30b9f6a0 🐛 Fixed email not showing as failed if error occurs when preparing email
no issue

- if an error occurred whilst creating email batch/recipient records the email status was never updated and was left in the 'pending' status
- adjusted the error handling to update the email status and record the error message if such a scenario occurs
2020-10-02 12:40:49 +01:00
Kevin Ansfield
7b789e1cd5 🐛 Fixed newsletters being sent to Stripe customer emails in place of member emails
no issue

- the paid-member SQL query that is obtained using `models.Member.getFilteredCollectionQuery({paid: true})` can return multiple columns with the same name (eg, `email`, `name`), when that happens the last column with duplicate names "wins" and it's value is used in the resulting knex row instance
- in the `mega` service when fetching email recipient rows we ran into this problem, to avoid it we adjust the query to explicitly select only the data from the `members` table
2020-10-02 12:17:17 +01:00
Kevin Ansfield
82126f29e6 Added guard for member rows having missing data when creating email recipients
no issue

- we've had an issue with emails failing due to unexpectedly missing data when inserting email recipient rows
- added a validation check before adding recipient details along with a log so that invalid data can be investigated
2020-10-02 11:29:10 +01:00
Kevin Ansfield
defb43fe7a 🐛 Fixed newsletters emails having no subject
no issue

- subject was not being picked out of the message data when passing over to the mailgun-js send method
2020-10-01 19:51:01 +01:00
Kevin Ansfield
e34acc31c5 🐛 Fixed newsletter email sending
no issue

- there was an typo in the recent email sending refactor that resulted in `Error: 'to' parameter is missing` errors when sending email previews and bulk emails
2020-10-01 19:03:57 +01:00
Fabien 'egg' O'Carroll
244704156c
Updated all Origin header checks to handle 'null' (#12246)
closes #12244

As per RFC 6454 the Origin header MUST be set to the string 'null' when
in a "privacy-sensitive" context. We were not handling this string and
this was causing errors. This commit updates all checks of the 'Origin'
header to treat the value 'null' as if the header was not present.

ref: https://tools.ietf.org/html/rfc6454#section-7.3
2020-10-01 09:37:22 +01:00
Rishabh Garg
eb4933d27e
Added extra settings to member auth emails (#12238)
no issue

- Adds accent color, site domain and url to member auth emails for customization
2020-10-01 12:31:36 +05:30
Fabien O'Carroll
fd5194ea46 Updated magic link expiry to 24 hours
no-issue

As discussed with @JohnONolan 24 hours is the preferred expiry for magic links
2020-09-30 10:53:35 +01:00
Kevin Ansfield
474e6c4c45 Refactor mega service to use stored email content and batch/recipient records
no issue

- store raw content in email record
  - keep any replacement strings in the html/plaintext content so that it can be used when sending email rather than needing to re-serialize the post content which may have changed
- split post email serializer into separate serialization and replacement parsing functions
  - serialization now returns any email content that is derived from the post content (subject/html/plaintext) rather than post content plus replacements
  - `parseReplacements` has been split out so that it can be run against email content rather than a post, this allows mega and the email preview service to work with the stored email content
- move mailgun-specific functionality into the mailgun provider
  - previously mailgun-specific behaviour was spread across the post email serializer, mega, and bulk-email service
  - the per-batch `send` functionality was moved from the `bulk-email` service to the mailgun provider and updated to take email content, recipient info, and replacement info so that all mailgun-specific headers and replacement formatting can be handled in one place
  - exposes the `BATCH_SIZE` constant because batch sizes are limited to what the provider allows
- `bulk-email` service split into three methods
  - `send` responsible for taking email content and recipients, parsing replacement info from the email content and using that to collate a recipient data object, and finally coordinating the send via the mailgun provider. Usable directly for use-cases such as test emails
  - `processEmail` takes an email ID, loads it and coordinates sending related batches concurrently
  - `processEmailBatch` takes an email_batch ID, loads it along with associated email_recipient records and passes the data through to the `send` function, updating the batch status as it's processed
  - `processEmail` and `processEmailBatch` take IDs rather than objects ready for future use by job-queues, it's best to keep job parameters as minimal as possible
- refactored `mega` service
  - modified `getEmailData` to collate email content (from/reply-to/subject/html/plaintext) rather than being responsible for dealing with replacements and mailgun-specific replacement formats
    - used for generating email content before storing in the email table, and when sending test emails
    - from/reply-to calculation moved out of the post-email-serializer into mega and extracted into separate functions used by `getEmailData`
  - `sendTestEmail` updated to generate `EmailRecipient`-like objects for each email address so that appropriate data can be supplied to the updated `bulk-email.send` method
  - `sendEmailJob` updated to create `email_batches` and associated `email_recipients` records then hand over processing to the `bulk-email` service
  - member row fetching extracted into a separate function and used by `createEmailBatches`
  - moved updating of email status from `mega` to the `bulk-email` service, keeps concept of Successful/FailedBatch internal to the `bulk-email` service
2020-09-29 17:17:54 +01:00
Kevin Ansfield
d34a3263e8 Store email batch and recipient records when sending newsletters (#12195)
requires https://github.com/TryGhost/Ghost/pull/12192

- added initial `EmailBatch` and `EmailRecipient` model definitions with defaults and relationships
- added missing `post` relationship function to email model
- fetch member list without bookshelf
    - bookshelf can add around 3x overhead when fetching the members list for an email
    - we don't need full members at this point, only having the data is fine
    - if we need full models later on we can push the model hydration into background jobs where recipient batches are fetched ready for an email to be sent
    - bookshelf model instantiation of many models blocks the event loop, using knex directly keeps concurrent requests fast
    - adds `getFilteredCollectionQuery` method to base model to facilitate getting a knex query based on our normal model filters along with transaction/forUpdate applied
- store recipient list before sending email
    - chunk already-fetched members list into batches and insert records into the `email_recipients` table via knex
    - chunked into batches of 1000 to match the number of emails that Mailgun accepts in a single API request but this may not be the absolute fastest batch size for recipient insertion:
        | Batch size | Batch time | Total time |
        | ---------- | ---------- | ---------- |
        |        500 |       20ms |     4142ms |
        |       1000 |       50ms |     4651ms |
        |       5000 |      170ms |     3540ms |
        |      10000 |      370ms |     3684ms |
    - create an email_batch record before inserting recipient rows so we can effeciently fetch recipients by batch and store the overall batch status
2020-09-29 17:17:54 +01:00
Rish
8e0976fc8f Allowed accent color in members site data
no issue

- The accent_color setting was being removed from members site data when behind portal flag
- The accent color setting is now allowed in members site data for all cases as it doesn't make any sense to remove it specifically from here where we already have all the other Portal settings included which is a dev/portal flag feature anyways
2020-09-29 17:23:33 +05:30
Rish
03968219a7 🐛 Fixed email verification mails not sent
no issue

- Email ownership verification emails for support/from address was not using the updated magic link service syntax
2020-09-24 23:39:25 +05:30
Kukhyeon Heo
635d26469f
Fixed settings reinit to only emit changed settings events (#12184)
closes #12038

Previously we were emitting changed events for _all_ settings which would
cause any listeners for those to be triggered, this ensures that listeners are
only triggered if the corresponding setting, _did_ in fact change.
2020-09-23 14:35:03 +01:00
Nazar Gargol
32b37d7ba8 Improved error messaging for password reset process
refs #11878

- When password reset link is invalid previous messaging left the user
without clear information about why the reset failed and what they could do about it.
- Updated messaging around password reset tokens including detection of
when password token has invalid structure, has expired or has already
been used
2020-09-22 15:45:19 +12:00
Kevin Ansfield
6dc8d91ace Revert "Store email batch and recipient records when sending newsletters (#12195)"
This reverts commit 80af56b530.

- reverting temporarily so that all associated functionality can be merged in a single release
- creating email batch/recipient records without using them would cause inconsistent data
2020-09-21 17:02:59 +01:00
Fabien 'egg' O'Carroll
39dd492927
Updated magic link expiry information to 4 hours (#12224)
no-issue

Since TryGhost/Ghost#12218 magic links now have
an expiry of 4 hours.
2020-09-21 16:08:21 +01:00
Kristian Freeman
aca94e65c3
Added support for Stripe promo codes in config (#12149)
closes #12111 

* Added default value in defaults.json
* Passed config to members-api module

refs: https://github.com/TryGhost/Members/pull/194
2020-09-21 13:15:41 +01:00
Fabien 'egg' O'Carroll
7c5a3bb537
Updated magic links to use shorter, single us, longer lived tokens (#12218)
no-issue

* Added SingleUseTokenProvider to members service

This implements the TokenProvider interface required by members-api to
generate magic links. It handles checking if the token is expired and
pulls out any associated data.

Future improvments may include the email in the error for expired
tokens, which would make resending a token simpler.

* Passed SingleUseTokenProvider to members-api

This sets up the members-api module to use the new single use tokens

* Installed @tryghost/members-api@0.30.0

This includes the change to allow us to pass a token provider to the members-api
2020-09-18 17:32:18 +01:00
Rish
ac146f1e3b Updated ownership verification email flow to use different From address
no issue

- In a recent change to ownership verification email flow, we changed the FROM address of ownership verification mails to use the same email as the one we are verifying, aka TO address.
- Email clients like Gmail flags off such emails as possible spam
- Fix updates the `FROM` address to `noreply@domain.com` where domain.com is domain for TO address
-  In case the TO is already noreply@domain.com, we use no-reply@domain.com to bypass the same address restriction.
2020-09-17 19:52:51 +05:30
Rish
49abeaf398 Added blog domain for default support address
no issue

- Members site data was not appending blog domain for default support address which is `noreply`
- The change allows Portal to use default support address correctly
2020-09-17 12:33:16 +05:30
Kevin Ansfield
80af56b530
Store email batch and recipient records when sending newsletters (#12195)
requires https://github.com/TryGhost/Ghost/pull/12192

- added initial `EmailBatch` and `EmailRecipient` model definitions with defaults and relationships
- added missing `post` relationship function to email model
- fetch member list without bookshelf
    - bookshelf can add around 3x overhead when fetching the members list for an email
    - we don't need full members at this point, only having the data is fine
    - if we need full models later on we can push the model hydration into background jobs where recipient batches are fetched ready for an email to be sent
    - bookshelf model instantiation of many models blocks the event loop, using knex directly keeps concurrent requests fast
- store recipient list before sending email
    - chunk already-fetched members list into batches and insert records into the `email_recipients` table via knex
    - chunked into batches of 1000 to match the number of emails that Mailgun accepts in a single API request but this may not be the absolute fastest batch size for recipient insertion:
        | Batch size | Batch time | Total time |
        | ---------- | ---------- | ---------- |
        |        500 |       20ms |     4142ms |
        |       1000 |       50ms |     4651ms |
        |       5000 |      170ms |     3540ms |
        |      10000 |      370ms |     3684ms |
    - create an email_batch record before inserting recipient rows so we can effeciently fetch recipients by batch and store the overall batch status
2020-09-14 15:40:00 +01:00
Talha
afa976066a
🐛 Fixed table constraint error when updating member's email with an already existing email (#12178)
closes #12045

- When member's email is updated to an already existing email of different member it caused table's unique constraint error, which was not handled properly. 
- Added handling for this error similar to one in members `add` method.
2020-09-10 16:03:57 +12:00
Nazar Gargol
5582d030e3 Added routes.yaml content checksum storage to the db
closes #11999

- When the routes.yaml file changes (manually or through API) we need
to store a checksum to be able to optimize routes reloads in the future
- Added mechanism to detect differences between stored and current routes.yaml hash value
- Added routes.yaml sync on server boot
- Added routes.yaml handling in controllers
- Added routes hash synchronization method in core settings. It lives in core settings
as it needs access to model layer. To avoid coupling with the frontend settings it accepts
a function which has to resolve to a routes hash
- Added note about settings validation side-effect. It mutates input!
- Added async check for currently loaded routes hash
- Extended frontend settings loader with async loader. The default behavior of the loader is
to load settings syncronously for reasons spelled in 0ac19dcf84
To avoid blocking the eventloop added async loading method
- Refactored frontend setting loader for reusability of  settings file path
- Added integrity check test for routes.yaml file
2020-09-10 10:54:57 +12:00
Talha
c8a6939b2e
🐛 Fixed error caused by accepting invitation with existing email (#12172)
closes #12060

- A 500 error what happening when invited user provided an email that is associated with an existing user
- Additional validation for existing email address was added to prevent invalid data hitting db constraint error
2020-09-09 11:58:53 +12:00
Rish
3c7a95aefa Added members support address to site data
refs https://github.com/TryGhost/members.js/issues/90

- Includes new members_support_address in member site data endpoint for Portal
2020-09-08 20:48:57 +05:30
Rish
2d2fa1a0ba Fixed missing subscription data in member update endpoint
closes https://github.com/TryGhost/members.js/issues/94

- The member-api package was recently updated to work directly with models and needs explicit `withRelated` options to attack relations
- Without options, the endpoint was returning the default member data without subscriptions attached, which in Portal showed paid member as free
- Fix updates the middleware for updating member data to correctly pass the relations needed to populate the member
2020-09-04 17:11:04 +05:30
Rish
dd6ac57aca Fixed missing domain for default support address
no issue

- By default for new sites, support address is set same as from address to `noreply` , with full email address using the domain for `@`
- For newsletter emails, the support address was missing the default site domain to be added to address if its `noreply`
- Fix updates the support address to use the same format as from address and add relevant domain for default case
2020-09-03 16:34:47 +05:30
Rish
696e60dd51 🐛 Fixed missing member email on unsubscribe page
no refs

- The `update` method in members-api package was edited to return Model object instead of JSON directly - TryGhost/Members@a28bcc5
- This unsubscribe handler was returning the raw member object returned from `update` method, which is now a model object and not able to access `member.email`
- Fix updates the unsubscribe request handler to return the member JSON again
2020-09-02 12:03:10 +05:30
Rish
806d0f8e21 Updated sender address for ownership verification emails to new address
no issue

- We used existing "from" address as sender for mails sent to new email address for verification, but that breaks the flow to update if the current "from" address has DMARC policy set.
- This updates the flow to always send the ownership verification email TO the new address and FROM the new address which both verifies the email deliverability for new address and ownership
2020-08-31 18:09:38 +05:30
Rish
8d022ecfb5 Updated newsletter emails to include reply-to address
no issue

- The newsletter emails are sent out with `from` address as sender
- The new `members_reply_address` setting is now used to set reply-to address for emails, which can be either newsletter or support address
2020-08-31 18:09:38 +05:30
Rish
ca8b77182c Updated sender address for member auth emails to support address
no issue

- Member auth emails were previously using the `from` address as sender
- New `members_support_address` was introduced with default as original "from" address
- Auth emails use the new support address as sender
2020-08-31 18:09:38 +05:30
Rish
cbb3664bdd Added handling for new members support/reply email addresses
no issue

- Updated magic link generation and validation methods for email update API to handle new support address
- Updated importer to ignore the new support address as it can only be updated via verification
- Updated members service to listen on settings edit for new support/reply address fields as well
- Updated tests to include the new settings
2020-08-31 18:09:38 +05:30
Rishabh Garg
bc2f6eb8e9 Added migrations for support and reply email address setting (#12163)
no issue

- Added default settings for the two new setting fields - `members_support_address` and `members_reply_address`
- Added migrations for setting group for new email settings
- Migration sets current from address as new support address default
- Added migration to set new support address same as from address
- Updated tests for new settings
- `members_support_address` - How members can reach for help with their account, public setting
- `members_reply_address` - Where you receive responses to newsletters
2020-08-31 17:16:53 +05:30
Nazar Gargol
e8248cdc9e Refactored members imporeter in preparation for jobs
no issue

- This refactor extracts labels related code into a separate module for easier reuse by the "job-aware" batched importer
2020-08-27 21:47:00 +12:00
Nazar Gargol
262d33b73c Improved import_label creation logic
no issue

- When an import was done and there were no "global labels" present Ghost created generic `import-[data]` label which later helped to find a specific batch of imported data
- It did not make sense to create such generic label when user provided their own unique label
- The rules that work now are:
1. When there is no global provided Ghost generates on and removes it in case there are no imported records
2. When there is a unique new global label provided no new label is generated, but the label stays even if there are no imported records
2020-08-27 19:07:27 +12:00
Kevin Ansfield
f30d3cd2c2 Switched to bookshelf count in getTotalMembers()
no issue

- tested performance between knex raw, knex `count()` and bookshelf `count()` and found no difference over 1000 iterations of each (each ~19,500ms +- 500ms for 104k members locally)
- switched to using bookshelf as the code is the simplest
2020-08-27 01:52:36 +01:00
Nazar Gargol
9fe5007929 Removed date handling validation in members importer logic
no issue

- This is handled on input sanitization layer with date
format check in JSON schema validation, so there's no need to do this
check again in the importer.
2020-08-26 17:25:24 +12:00
Nazar Gargol
95044e3ba0 Added error handling for failed member imports
no issue

- When bulk insert fails there is no transactional logic to revert
related records form being inserted. Also, previously there were no
attempts to "retry" the insert.
- To avoid complex retry logic, an iterative one-by-one insert retry
approach was taken. If this becomes a bottleneck in the future, the
retry algorithm could be improved.
- To avoid a lot of code duplication refactored model's `bulkAdd` & `bulkDestroy`
methods to use 'bulk-operations' module.
- Updated error handling and logging for bulk delete operations. It's very
unlikely for error to happen here,  but still need to make sure there is
a proper logging in place to trace back the failure.
- Added debug logs. This should improve debugging experience and
performance measurements.
- Added handling for unrecognized errors. Handling inspired by current unrecognized
error handling by ghost importer -10e5d5f3d4/core/server/data/importer/importers/data/base.js (L148-L154)
2020-08-26 17:11:35 +12:00
Kevin Ansfield
e07e0a17c6 🐛 Fixed bookmark card display in member emails when using Gmail+Chrome
no issue

- updates `@tryghost/kg-default-cards` which contains two fixes
  - removes email-specific output being added to post html (had no visual impact due to use of conditional comments but keeps rendered html smaller+cleaner)
  - adds a background-url style to the thumbnail container to give two options for styling
- updates member email template styling to hide the `<img>` element in bookmark cards and use a background image instead to get consistent rendering across email clients
2020-08-24 18:21:09 +01:00
Peter Zimon
75f5ab637d Added minor member newsletter customisations via config
no issue
- adds a `members:emailTemplate` config object
  - `showSiteHeader` - defaults to `true`, shows the site title and icon in member emails
  - `showPoweredBy` - defaults to `false`, adds a "Publish with Ghost" button to member email footer
- updates member newsletter email template with hideable site header and "powered by" badge
2020-08-24 10:44:22 +01:00
Rish
297b63edce 🐛 Fixed response for members API update endpoint
closes https://github.com/TryGhost/members.js/issues/87

- The `update` method in members-api package was edited to return Model object instead of JSON directly [here](a28bcc5b2a)
- This caused the update member API on member endpoint to return partial response only as most properties couldn't be fetched
- Fix updates the middleware to correctly call `toJSON` before formatting response
2020-08-24 13:38:21 +05:30
Nazar Gargol
91d1417df2 Fixed email newsletter error when post has no content
closes #12158
2020-08-24 19:46:46 +12:00
Nazar Gargol
5670d99f46 Improved error handling for batch deleted records
no issue

- Similar handling to one introduced in 8418c829de
- Having granular tracking for failed to remove id's would make it possible to return more specific errors to the client
2020-08-20 19:11:41 +12:00
Nazar Gargol
8418c829de Improved error handling for batch inserted records
no issue

- Similar to 3a594ce22e this adds error handling to batch operations done outside models
2020-08-20 19:01:17 +12:00
Nazar Gargol
f8adb4a672 Refactored bulk insert/delete operations into separate module
no issue

- Moved bulk db operations outside of importer module to create clearer separation of responsibilities
2020-08-20 18:42:38 +12:00
naz
3a594ce22e
Improved error handling for batch inserted member records (#12146)
no issue

- When batch insert fails handling should be more granular and aim to retry and insert as many records from the batch as possible.  
- Added retry logic for failed member's batch inserts. It's a sequential insert for each record in the batch. This implementation was chosen to keep it as simple as possible
- Added filtering of "toCreate" records when member fails to insert. We should not try inserting related members_labels/members_stripe_customers/members_stripe_customer_subscriptions records because they would definitely fail insertion without associated member record
2020-08-20 17:41:47 +12:00
Nazar Gargol
2e769e3122 Fixed handling for Stripe connected members import
no issue

- When stripe is disconnected and there are Stripe-connected records present in imported set they should not be processed and proper error should be thrown
2020-08-20 17:08:19 +12:00
Nazar Gargol
4498b4624a Fixed label serialization in members bulk importer
no issue

- After a refactor logic was missing trimming logic and handling for empty labels
2020-08-20 16:43:42 +12:00
Nazar Gargol
32fd913ac3 Fixed default subscribed value for member model in the importer
no issue

- The default value should not be a string but rather a boolean
2020-08-19 23:42:48 +12:00
Kevin Ansfield
d8e319af88 🐛 Fixed card spacing and caption styling for member emails in Outlook
closes https://github.com/TryGhost/Ghost/issues/12139

- once the email content has been rendered in the post serializer, perform some whole-content transformation of `figure` and `figcaption` to `div` using cheerio
- juiced will have already inlined the elements styles so there's no need to adjust the template's stylesheet
2020-08-19 12:34:14 +01:00
Jeremy Davidson
681c96b5e9
🐛 Fixed bookmark card author/publisher spacing in member emails (#12134)
closes #12078

- Root cause was that pseudo class .kg-bookmark-author:after was not getting inlined to email newsletter or its preview.
  - That is where the margin and bullet-point content are added between author and publisher.
- Dependency juice supports an option inlinePseudoElements which is false by default.
- Fix was to set inlinePseudoElements to true when serializing post email.

Co-authored-by: Jeremy Davidson <jeremy@crossingcontour.com>
2020-08-18 16:18:44 +01:00
Kevin Ansfield
cefcdad090 🐛 Fixed emails appearing very wide in Outlook and improved email image sizes
closes https://github.com/TryGhost/Ghost/issues/11536

- bumps `@tryghost/kg-default-cards`
  - image and gallery cards now output `width/height` attributes on `img` elements with a max width of 600px
  - uses resized images where possible to keep email weight down
- adds `height: auto` style to image card images so that the `height` attribute does not cause distortion at smaller screen widths
2020-08-18 15:33:54 +01:00
Fabien 'egg' O'Carroll
cada88975a
Updated bulk importer to improve performance (#12128)
no-issue

* Added bulkAdd method to Member,Customer&Subscription model
  This allows us to keep the db access in the model layer
* Updated @tryghost/members-api to 0.27.2
  This includes fixes for rate-limiting of requests, and exposes necessary
  Stripe methods for creating customers and complimentary subscriptions,
  without affecting the database.
* Refactored importer to parallelise tasks where possible
  By parallelising our tasks we are able to improve the speed at which the
  entire import completes.
2020-08-18 13:39:45 +01:00
Nazar Gargol
4126187df3 Fixed parameter naming for members importer 2020-08-13 21:08:34 +12:00
Nazar Gargol
d2fbe327e4 Update Stripe concurrency in members importer
no issue

- There were many failed import records due to rate-limit errors. With concurrency of 9 imports go through with 100% success
- Would need to verify these limits with live API to make the most of it
2020-08-13 21:04:57 +12:00
Nazar Gargol
78b4dff656 Moved batching logic inside the members importer module
no issue

- This way importer is more self contained and controller logic doesn't have to know about batch sizes and other unecessary variables
2020-08-13 20:31:11 +12:00
Kevin Ansfield
c434666ba2 🐛 Removed [http://url/] output in member email preview text
no issue

- we output the post excerpt in a hidden div in the email template so that email clients pick it up as the "preview" text when listing emails
- when no custom excerpt is provided the preview text is grabbed from post.excerpt which is the first 500 chars of the post.plaintext value
- post.plaintext formats links as "Link [http://url/]" which is unwanted in html email previews

- add a basic replacement to the post email serializer to remove any `[http://url/]` occurrences from the post excerpt before rendering the email content
2020-08-12 20:14:06 +01:00
Kevin Ansfield
163092f377 🐛 Fixed apostrophes not displaying correctly in Outlook for member emails
refs https://github.com/TryGhost/Ghost/issues/11536

- Outlook supports `&#39;` as a special char for apostrophes but not `&#apos;` which is what cheerio/juiced render
- adds a basic string placement to the email serializer to switch to the older style of special char
2020-08-12 20:01:42 +01:00
Kevin Ansfield
c7ff4c9e93 Moved email sending to the background job queue
no issue

- moves the meat of `pendingEmailHandler()` code into a new function `sendEmailJob()` that is passed over to the new job service
- lets the server keep processing email generation and sending when it receives a shutdown request rather than halting processing mid-send and ending up in a partial state
2020-08-12 17:02:14 +01:00
Fabien 'egg' O'Carroll
1294e3f92c
Replaced all usage of member models with members-api (#12117)
no-issue

* Added stripeSubscriptions relation to member model

This allows us to fetch the subscriptions for a member via standard
model usage, e.g. `withRelated: ['stripeSubscriptions']` rather than
offloading to loops and `decorateWithSubscriptions` functions, this is
more performant and less non-standard than the existing method.

* Updated serialize methods to match existing format

The current usage of `decorateWithSubscriptions` and the usage of
members throughout the codebase has a subscriptions array on a stripe
object on the member, this ensures that when we serialize members to
JSON that we are using the same format.

There is definitely room to change this in future, but this is an
attempt to create as few breaking changes as possible.

* Installed @tryghost/members-api@0.26.0

This includes the required API changes so that everywhere can use
members-api directly rather than models and/or helper methods
2020-08-12 14:17:44 +01:00
Nazar Gargol
c696d715c1 Extracted batched member import into separate module
no issue

- The code in controller was becoming hard to reason about.
- Having a single module shows exactly how many dependencies are there to do an import for single batch.
- Having a separate module would make it easier to extract into it's own package in Members monorepo
2020-08-12 20:18:30 +12:00
Hannah Wolfe
bbbd011074 Added job-manager & wired up shutdown and testmode
- Bottom line - we need to manage shutting down gracefully when doing long-running tasks
- To achieve that, we're going to use job queues

In this commit:
- added new @tryghost/job-manager dependency
- added a minimal job service, that handles in passing things like logging and (maybe later) config
- job service is wired up to server shutdown, so that the queue finishes before the server exits
- also added a new job endpoint to testmode so that it's easy to test job behaviour without needing to do real work
2020-08-11 21:31:34 +01:00
Daniel Lockyer
5b471e1bbe Extracted promise libs and history into @tryghost/promise
- deleted files under `core/server/lib/promise` and related test files
- added `@tryghost/promise` as a dependency
- fixed all local requires to point to the new package
2020-08-11 18:44:21 +01:00
Daniel Lockyer
c9a5b28669 Extracted core/server/lib/security to @tryghost/security package
- code and tests were extracted out to this package
- deletes these files
- replaces all local requires, and adds it as a dependency
2020-08-11 14:06:50 +01:00
Daniel Lockyer
8799feb801 Replaced constants file with @tryghost/constants
- extracted constants file into a new package
- replaced all local requires of the file with new package
2020-08-11 12:51:16 +01:00
Kevin Ansfield
2efcf94645
Improved performance of sending newsletter emails (#12091)
no-issue

- switch from `membersService.api.members.list` to using bookshelf `Member.findPage()` with the `{paid: true}` filter to avoid per-member queries (N+1) to decorate members with subscriptions and a heavy post-fetch filter via `contentGating`
- add concurrency to the Mailgun API requests in `bulk-email` service to reduce overall time submitting API requests
- add debug statements with timing output for easier measurements
2020-08-06 15:19:39 +02:00
Gerardo Lopez Dueñas
275bf41ba3
Fixed bookmark card image size in fastmail (#11970)
closes #11907

The image in the bookmark card was being shown out of the bounds of
the card because of a general style `height: auto !important`.

I added a new `max-height` property to the image to avoid exceeding
parent height.
2020-08-03 18:38:45 +01:00
Kevin Ansfield
29d94e7814 Fixed mailgun config not allowing custom hosts with ports
no issue

- `mailgun()` expects the `host` option not to include a port but `url.host` will include the port, we instead want to use `url.hostname` which skips the port
2020-07-30 17:28:51 +01:00
Hannah Wolfe
436db4ec3b Updated host limit message to be clearer
- limits are based on total members not number of members that will be emailed
2020-07-26 20:49:30 +01:00
Hannah Wolfe
92446d85ea Changed member limit to be DRY & use raw query
- Member limit code was duplicated in 2 places unnecessarily
- Also used member api code that fetched members and subscriptions fully hyrated when we only need a count
- Using a raw query significantly improves performance here
2020-07-26 20:49:30 +01:00
Hannah Wolfe
3491e60c9d Added config to send bulk email in testmode
- mailgun has a testmode flag we can use to get email to be accepted but not delivered
- this is useful for developers testing general bulk email code - not for users - so it is only available via config
2020-07-24 11:55:34 +01:00
Rish
2ac69e637e Added publication icon to members site data
refs https://github.com/TryGhost/members.js/issues/72

- Portal is using using publication logo from settings for signup/signin pages
- Instead, we are switching to using publication icon from settings, which also needs to be passed in site data API
2020-07-23 17:04:44 +05:30
Fabien 'egg' O'Carroll
69080824de
🐛 Ensured webhooks are created once (#12075)
refs #12074

Since we've split members settings into multiple keys the
reconfiguration of the members-api has been happening in quick
succession as the stripe_connect_* settings are all set at once.

This debounces the call to reconfigure the members-api so that we only
need to instantiate it once.
2020-07-22 12:27:05 +02:00
Rish
3d164d222b Updated error name check in GhostMailer
no issue
refs e8511d0568

- Adds extra check for empty `err` object while checking error name for status code in GhostMailer
2020-07-21 01:08:19 +05:30
Rish
e8511d0568 Updated error code for incorrect recipients in GhostMailer
no issue

- By default, GhostMailer throws EmailError with statusCode as `500` for any failure in sending mail
- In case of failure due to `RecipientError`, status code as now correctly sent as `400` as its a bad request and not an error we can't handle.
2020-07-21 01:05:21 +05:30
Rish
90b39fbb9a Updated status and error message for newsletter email failures
refs https://github.com/TryGhost/Ghost/issues/11971

- Added statusCode from bulk email provider to API response
- Updated error messages for different bulk email(mailgun) failure states
- Added `context` to preview mail API error message with mail provider's error message
2020-07-17 13:54:09 +05:30
Rishabh Garg
ead073ad68
Updated sender email to existing "from-address" (#12044)
refs #12043

- On updating From-address from Members settings in Labs, we send a confirmation email to the updated address with magic link for verification
- Previously, no explicit sender email was being set for this so fallback config address was used
- This updates the sender address to use the current from address for "from-address" update emails
2020-07-13 17:57:31 +05:30
Fabien O'Carroll
06c7152f4b 🐛 Fixed Stripe webhooks for subdirectory setups
no-issue

- Added breaking test for webhook url including subdirectory

- Previously the webhook handler URL was generated incorrectly when
  running Ghost on a subdirectory, appending the path to the root of the
  host, this fix ensures that the subdirectory is included before the
  path.
2020-07-10 17:43:46 +02:00
Fabien O'Carroll
832ecad43b Improved handling of Stripe webhooks on boot
no-issue

This version of members-api includes changes to how webhooks are
managed, previously they would be deleted and recreated on every boot of
Ghost. Now they are created and the secret is persisted, on boot the
webhook is updated to the most current url and events. If the api
version is wrong or the update fails, the webhook is deleted and
recreated and the settings updated.

 - Installed @tryghost/members-api@0.24.0
 - Updated config to work with 0.24.0
2020-07-10 17:43:46 +02:00
Fabien 'egg' O'Carroll
e14188807d Fixed express-jwt config
no-issue

express-jwt expects an array of valid algorithms, not a single algorithm.
2020-07-08 15:09:44 +02:00
Rish
c5d360e647 Fixed members plan currency symbol
no issue

The refactor to new settings lost the uppercasing of the currency string, this puts it back
2020-07-08 10:47:28 +05:30
Fabien O'Carroll
694d92d270 Added guards for stripe_plans setting being null
no-issue

There is concern that the settings cache can return `null` for values
which it cannot parse correctly, this just ensures that we always have
an array where we expect one
2020-07-07 13:10:17 +02:00
Rish
8d989bd3c3 Updated members site data to include new portal settings
no issue

- Adds new portal button settings to members site data for portal script
- Updates settings input/output serializers to handle portal icon image url
2020-07-07 14:06:04 +05:30
Daniel Lockyer
8956a9df35 Merged 3.22.2 into master
* tag '3.22.2':
  v3.22.2
  Updated Ghost-Admin to v3.22.2
  Emitted all settings events on reinit of cache (#12012)
  🐛 Updated access to be true by default in v3 API
  Hardened members subscription migration against missing data (#12009)
2020-07-06 16:19:55 +01:00
Fabien 'egg' O'Carroll
8b6ec4d922
Emitted all settings events on reinit of cache (#12012)
closes #12003

There are a few parts of Ghost that rely on the settings events being
emitted anytime a setting is changed, so that the data is kept in sync.

When a setting is renamed in a migration essentially what happens is
that the settings value is changed from a default value to its actual
value, but this does no emit an event.

Anything that is initialised before migrations have run that relies on
the events to keep it up to date will have stale data - e.g. the themes
i18n service.

This change ensures that when we `reinit` after migrations have been
run, we emit events for every setting to tell the rest of Ghost that it
has changed.
2020-07-06 17:09:43 +02:00
Fabien O'Carroll
5e6a4f6f7d Updated bulk-email service to use mailgun settings
refs #10318
2020-07-03 11:48:47 +02:00
Kevin Ansfield
fd4a011995
🐛 Fixed settings cache being out of sync after migrations (#11987)
refs https://github.com/TryGhost/Ghost/issues/10318

- re-initialize settings cache after migrations by shutting down to clean up event listeners then and calling `init` again
- important to ensure `db.ready` event is not emitted until settings have finished re-initializing to avoid problems with background processes using the db connection which is disconnected/re-connected or being kicked off with out-of-date settings
2020-07-01 17:16:57 +01:00
Fabien 'egg' O'Carroll
ee786aaa5d
Cleaned up members & stripe settings (#11957)
* Updated members default settings

ref #10318

This pulls out the members_subscription_settings & stripe_connect_intgration settings into separate keys

* Updated usage of members_from_address

* Updated stripe_connect usage

* Updated members config to use new settings

* Updated members middleware to use isStripeConnected

* Updated members service to reload correctly

We reload the members-api instance when the related settings change, so
this makes sure we're listening to the correct settings changes

* Updated ghost_head helper to use new settings

* Updated theme middleware to use new settings

* Renamed members_allow_signup -> members_allow_free_signup

* Fixed tests after settings refactor

* Removed  from direct key settings key

* Fixed regression tests for settings api
2020-06-29 16:22:42 +02:00
Nazar Gargol
2de1c07dd4 Renamed settings key brand.primaryColor to accent_color
refs #10318
2614565d5a

- Changes naming throughout the codebase matching the change in the
referenced commit
2020-06-24 14:18:13 +12:00
Nazar Gargol
f0a811e9fe Renamed ghost_head/ghost_foot to codeinjection_head/codeinjection_foot
refs #10318
refs 2614565d5a

- Renamed ghost_head/ghost_foot in settings to match the new names
introduced in migrations
- Above change lead to reshufling in the mappings in input/output
serializers
- Makes sure change is compatible with v2 API
2020-06-24 14:18:13 +12:00
Nazar Gargol
5f1060a8bf Renamed settings keys active_timezone to timezone
refs https://github.com/TryGhost/Ghost/issues/10318
refs 2614565d5a

- Renames to match referenced migration renames
- Fixed API responses so they are consistent with newly renamed fields
- Not returning lang and timezone keys from settings in API v2 ther rest should be returned in API v3/canary
2020-06-24 14:11:20 +12:00
Nazar Gargol
c4dff2d50e Renamed settings keys from default_locale to lang
refs #10318
refs 2614565d5a

- Renames default_locale settings key as introduced in referenced
migration
2020-06-24 14:07:24 +12:00
Kevin Ansfield
8a817050c5
Organised default settings into new groups (#11952)
refs https://github.com/TryGhost/Ghost/issues/10318

- precursor to migrating from `settings.type` to `settings.group`
- renames `blog` type to `site`
- renames `bulk_email` type to `email`
- moves settings out of `site` (previously `blog`) into more appropriate groups such as `core` or individual feature groups
2020-06-23 20:49:08 +01:00
Rish
77e1ada6c6 Added new settings for members modal
no issue

-  reverts commit 87c31444fd but with modifications to settings naming
-  Adds new settings for members modal customization to default settings
- `portal_button` controls the visibility of beacon in members modal
- `portal_name` controls the visibility of name field in signup
- `portal_plans` controls the visibility of plans allowed for member to signup with
-  Adds stripe connect check to determine if stripe is setup or not
-  Adds the 3 new settings to members site data
-  Updates to snake case naming for members site API data
2020-06-19 21:35:49 +05:30
Rish
87c31444fd Revert "Added new settings for members modal settings (#11927)"
This reverts commit ea7d450a9b.
2020-06-18 19:06:13 +05:30
Rishabh Garg
ea7d450a9b
Added new settings for members modal settings (#11927)
no issue

-  Adds new settings for members modal customization to default settings
- `membersjs_show_beacon` controls the visibility of beacon in members modal
- `membersjs_show_signup_name` controls the visibility of name field in signup
- `membersjs_allowed_plans` controls the visibility of plans allowed for member to signup with
-  Adds stripe connect check to determine if stripe is setup or not
-  Adds the 3 new settings to members site data
2020-06-18 17:11:08 +05:30
Hannah Wolfe
27066ce910
🐛 Fixed missing text version in bulk email (#11919)
closes #11917

- Pass text-only version to mailgun as `text` not `plaintext`
- This ensures we send a text-only version of the email, and this in turn should help to improve spam scores
2020-06-15 15:31:09 +01:00
Hannah Wolfe
edff7ac853
Adding INR currency support (#11911)
- We have many customers asking for INR as there are special rules in Stripe for this currency
- As well as a desire for local-selling
- Meaning it's not valid to use e.g. USD instead
2020-06-12 19:36:25 +01:00
Fabien O'Carroll
63f1e57036 Fixed Members Stripe config for Stripe Connect
no-issue

This was initially missed as local settings always had the original
stripeDirect keys, this ensures that regardless of Connect vs Direct vs
Both vs Neither that the config is correct.

Also ensures that the Members API instance is reloaded when the Stripe
Connect settings are changed.
2020-06-12 19:22:36 +02:00
Rish
41b3ecc744 Removed extra redirect on Admin for from address update
no issue

- Ghost-Admin redirects all paths to `/ghost/settings...` as `/ghost/#/settings/...`, this updates the admin redirect on successful magic link validation to directly use the latter to avoid extra redirect
2020-06-11 19:49:19 +05:30
Rish
9c478d778a Fixed email copy for update email template
no issue

- Fixes email copy changes for update-email mails sent for from address update
2020-06-11 18:19:53 +05:30
Rish
82cf095600 Added stripe config check to members site data
refs https://github.com/TryGhost/members.js/issues/43

- Adds new `isStripeConfigured` flag to public members site data which denotes if stripe setup is completed
- Helps clients like members.js/themes to configure payment behavior based on this flag
2020-06-10 21:15:13 +05:30
Fabien O'Carroll
5f808dfbee Encoded the mode in the Stripe Connect OAuth state
no-issue

The service at stripe.ghost.org must know which client_secret to use,
either the test, or live one. By encoding a JSON object as the state we
are able to pass data through the flow to inform this decision at the
end.

Note, that we still keep a random value in the state to protect against
CSRF attacks.
2020-06-10 14:06:57 +02:00
Fabien O'Carroll
2ff151a893 Added support for stripe connect test mode
no-issue

This adds the ability to pass a `mode` param of 'test' to the members stripe
connect service, which will ensure we use a testmode client_id for the
Stripe Connect OAuth flow.

This will allow users to connect their account in testmode.
2020-06-10 14:06:57 +02:00
Fabien O'Carroll
9348134afe Added display_name & account_id to stripe connect
no-issue

This will allow us to display this information in the Admin to make it
easier for the user to see what the current state is.
2020-06-09 17:11:17 +02:00
Nazar Gargol
81fc5f8eda Added special handling for member import with Stripe connection
no issue

- When imported member contains stripe_customer_id data but there is no Stripe configured on the Ghost instance such import should faiil. The logic is consistent with one where import fails after not being able to find customer in linked Stripe account
- Fixed import stats to show import failures instead of "duplicate" when the validation error is of "Stripe" origin
2020-06-09 23:02:38 +12:00
Rish
c63f7f2b13 Updated copy for email address change template
no issue

- Fixes typo and title for email address update mails
2020-06-09 12:11:57 +05:30
Daniel Lockyer
5d30af1513 Fixed wrong require in post email serializer
refs https://github.com/TryGhost/Ghost/pull/11807

- this was originally reported in the PR above, but we could not
  reproduce it on master
- presumably the user had the latest version of moment installed for
  other purposes and so they were seeing the issue
- between moment 2.24.0 and 2.26.0, something must have changed which
  stopped the previous functionality working
2020-06-08 19:43:55 +01:00
Rish
bca41e1877 Allowed updating from address domain for member emails
refs https://github.com/TryGhost/Ghost/issues/11414

Confirms if the fromAddress for sending member emails is valid and accessible using magic link flow, allowing owners to update full from address including domain change.

- Extends member service to handle magic link generation and validation for email update
- Updates existing setting endpoint to not directly update from address
- Adds new endpoint to send magic link to new address
- Adds new endpoint for validating the magic link when clicked and update the new email for from address
- Adds new email template for from address update email
2020-06-09 00:06:07 +05:30
Rish
bbcd32d204 🐛 Fixed "from" parameter handling for bulk email
closes https://github.com/TryGhost/Ghost/issues/11768

- Wraps from parameter in double quotes so mail clients can read it whole
- Escapes double quotes in site title to avoid clash with wrapping
2020-06-08 21:56:11 +05:30
Fabien O'Carroll
37a1947fc5 Fixed broken regression tests from #11861
no-issue

The config is now a class and the context of `this` was not bound
2020-06-02 16:20:57 +02:00
Fabien O'Carroll
44f1c0a7b6 Updated members config to respect stripeDirect
no-issue

If the stripeDirect config value is NOT set / false, then connect token
should be used over the API keys if both are present, or else use
whichever is present.  If the stripeDirect config value is set /
true,then API keys should be used and stripe connect token should be
completely ignored.

The reason for this is that we want to use Stripe Connect as the primary
auth method going forward, but we want to keep the direct version
availiable should the Ghost Foundation ever dismantle. This will allow
people to use all the same features with no dependency on an external
service.
2020-06-02 15:28:42 +02:00
Fabien O'Carroll
a1f883edbc Refactored members config to use DI
no-issue

This makes testing it much easier
2020-06-02 15:28:42 +02:00
Fabien O'Carroll
eb962d8e5c Added stripe connect module to member service
no-issue

This module handles the creation of a url used for authorization of
Stripe Connect, and also the parsing of the data eventually received
from the authorization flow.
2020-06-02 15:28:42 +02:00
Rish
d2cf7111ec Added new mail type for member email update
refs https://github.com/TryGhost/members.js/issues/30

- Added new `updateEmail` type for sending email address update confirmation mail to member
- The link in email updates member's email address
2020-06-02 14:27:03 +05:30
Rish
9948e85154 Updated member subscribe email template
no issue

- Updated button copy to "Confirm email address"
- Added missing color to copy link address
2020-06-01 12:55:47 +05:30
Vikas Potluri
00c324fa4e
Moved core/server/lib/common/logging to core/shared/logging (#11857)
- Represents that logging is shared across all parts of Ghost at present
  * moved core/server/lib/common/logging to core/shared/logging
  * updated logging path for generic imports
  * updated migration and schema imports of logging
  * updated tests and index logging import
  * 🔥 removed logging from common module
  * fixed tests
2020-05-28 19:30:23 +01:00
Rish
3471a21bc3 Removed email update directly using member session auth
refs https://github.com/TryGhost/members.js/issues/30

- Member cannot update their email directly but need to do it via magic link sent to new email address
- Previous profile update change had allowed email to be updated directly as well for authenticated member
2020-05-28 19:31:00 +05:30
Vikas Potluri
1bd8c18a16
Moved core/server/lib/url-utils to core/shared/url-utils (#11856)
* moved url-utils from server to shared
* updated imports of url-utils
2020-05-28 11:57:02 +01:00
Vikas Potluri
15d9a77092
Moved config from server to shared (#11850)
* moved `server/config` to `shared/config`
* updated config import paths in server to use shared
* updated config import paths in frontend to use shared
* updated config import paths in test to use shared
* updated config import paths in root to use shared
* trigger regression tests
* of course the rebase broke tests
2020-05-27 18:47:53 +01:00
Vikas Potluri
aeee302c9d
refactored 'lib/image' imports to use destructuring (#11847)
* refactored 'lib/image' imports to use destructuring
* trigger all-tests
2020-05-26 19:11:23 +01:00
Rishabh Garg
fe3eab1836
Added member update endpoint with session auth (#11824)
- Allows member logged in with valid session to update their profile info - name, email, subscribed(newsletter subscription status)
- Adds new util method for formatted member response on the endpoints
- Adds common middlewares for body/bool parser and maintenance
- Adds `subscribed` status to member response
2020-05-20 14:37:58 +05:30
Peter Zimon
c2470bcddb
Fixed truncated URL for password reset email (#11827)
no issue

- shows the full URL instead of a truncated link in password reset email body. This is required for security and usability reasons (copy/paste)
2020-05-20 08:22:37 +01:00
Hannah Wolfe
998eb62e22 Added success indicator for members magic links
- Add a query param that indicates whether signin/up succeeded or failed
- Add unit tests for all 3 possible cases for the createSessionFromMagicLink middleware
- Added an acceptance test to show the behaviour works in principle
2020-05-08 13:17:51 +01:00
Hannah Wolfe
7ee2e56bb4
Redirect members on token error (#11796)
- This restores the functionality from 3.14 as follows:

/members/ -> (with no route) rendered 404 error
/members/ -> (with route) renders members template
/members/?token=invalidtoken&foo=bar -> redirects to /?foo=bar
/members/?token=validtoken&foo=bar -> redirects to /?foo=bar
2020-05-07 21:55:50 +01:00
Kevin Ansfield
0eec876cb1 Removed separate reset/forced-reset emails and updated email copy
refs https://github.com/TryGhost/Ghost/pull/11790

- reduced complexity by sticking to one email for both normal reset and forced reset (locked staff accounts)
- exposed `siteTitle` for use in any email templates
- updated email copy to be suitable for both types of password reset
2020-05-06 13:20:11 +01:00
Naz
c84866dda7
Improved password reset and session invalidation for "locked" users (#11790)
- Fixed session invalidation for "locked" user
  - Currently Ghost API was returning 404 for users having status set to "locked". This lead the user to be stuck in Ghost-Admin with "Rousource Not Found" error message.
  - By returning 401 for non-"active" users it allows for the Ghost-Admin to redirect the user to "signin" screen where they would be instructed to reset their password

- Fixed error message returned by session API
  - Instead of returning generic 'access' denied message when error happens during `User.check` we want to return more specific error thrown inside of the method, e.g.: 'accountLocked' or 'accountSuspended'
  - Fixed messaging for 'accountLocked' i18n, which not corresponds to the
actual UI available to the end user

- Added automatic password reset email to locked users on sign-in
  - uses alternative email for required password reset so it's clear that this is a security related reset and not a user-requested reset

- Backported the auto sending of required password reset email to v2 sign-in route
  - used by 3rd party clients where the email is necessary for users to know why login is failing

Co-authored-by: Kevin Ansfield <kevin@lookingsideways.co.uk>
2020-05-05 19:37:53 +01:00
Hannah Wolfe
8383b11d84 Cleaned up some weird require paths
- these require paths go back too far. They work but it's odd!
2020-05-01 18:00:57 +01:00
Kevin Ansfield
ee20efc971 Fixed Outlook not centring content column in member emails
refs https://github.com/TryGhost/Ghost/issues/11756

- we removed the fixed `width: 600px` to fix gmail scaling but that means we need a new way of creating a 600px centre column in Outlook
2020-05-01 13:40:02 +01:00
Kevin Ansfield
28b24d2095 Fixed video embed card fallback display across gmail apps
refs https://github.com/TryGhost/Ghost/issues/11756

- bumped kg-default-cards package to generate fixed html for video embed fallbacks
2020-05-01 13:22:52 +01:00
Kevin Ansfield
2404710e66 🐛 Fixed tiny font sizes sometimes seen in member emails on gmail mobile apps
refs https://github.com/TryGhost/Ghost/issues/11756

- fixed gmail scaling problems
  - the `width: 600px` on `.container` was forcing gmail to always render at 600px wide and then use scaling to resize the email to fit the device width
  - for most emails gmail would also apply their own font resizing to compensate so it didn't look _too_ bad
  - some emails however would not trigger the font resizing, most notably when posts contained a feature image, which would result in very small text
  - removing the fixed `width: 600px` resolves the scaling problem and lets the email be truly responsive
- removed attribute selectors in the media query CSS
  - gmail does not support attribute selectors
  - attribute selectors used to be necessary for Yahoo Mail but this is no longer the case
- tested using litmus.com for all popular email clients
2020-05-01 11:06:52 +01:00
Hannah Wolfe
baa8118893 Refactor common pattern in service files
- Use array destructuring
- Use @tryghost/errors
- Part of the big move towards decoupling, this gives visibility on what's being used where
- Biting off manageable chunks / fixing bits of code I'm refactoring for other reasons
2020-04-30 20:48:42 +01:00
Hannah Wolfe
c70c49258e Added new members/api/site endpoint
- easy way to access public settings needed for building members clients
- no auth means this is for public info only
2020-04-30 19:50:40 +01:00
Hannah Wolfe
5365522cf5 Removed dupe use of labs.members & leftover file
- Meant to cleanup the old api/canary/members earlier, removed now as it's unused
- Also removed all the duplicate references to labs.members in various places
2020-04-30 19:33:09 +01:00
Kevin Ansfield
81bf1667fa Fixed video embed card fallback display in Outlook
refs https://github.com/TryGhost/Ghost/issues/11756

- updates `@tryghost/kg-default-cards` which includes a VML version of video embed card fallbacks
- fixes play button styling for Yahoo Mail
- adds a minimum height to video embeds so they appear more reasonable when images are not loaded
2020-04-30 12:08:06 +01:00
Rish
e54a8b5112 🐛 Fixed next middleware call after magic link redirect
no issue

We changed the magic link route handling from setting global value to just redirecting to frontend in [this](d8d5d6b7d0 (diff-0d54454fd954b0203a71ec52df4bd4c0R96-R98)) commit, but missed removing `next()` call which attempts to send response again causing Unhandled rejection error. This change simply removes the extra `next()` call
2020-04-30 13:47:20 +05:30
Hannah Wolfe
d8d5d6b7d0 Moved magiclink handling to /members/ + added redirect
- Magic link token handling doesn't need to be global, this couples the system to the frontend, which isn't necessary
- Instead, we create a session from the token, and redirect to the frontend
- Move res.locals.members setting into existing middleware function instead of having it separate
2020-04-29 19:35:41 +01:00
Hannah Wolfe
0e1ae7c2af Separated members token mw from members session mw
- The existing createSessionFromToken was actually doing two things behind the scenes
   1. Handling the ?token from the magic link and creating an actual session (mounted globally, which is not necessary)
   2. Loading an existing session so that a member is logged in to the frontent
- IMO 1. is part of members, and doesn't need to be global
- IMO 2. is part of the frontend. It does need to be global but should NOT be hidden away behind the token middleware, as it wasn't clear what this was doing
2020-04-29 19:19:19 +01:00
Daniel Lockyer
7fe5bacada Changed bulk-email error to EmailError
no issue

- this error is more suitable than the generic GhostError
2020-04-29 17:20:04 +01:00
Hannah Wolfe
22e13acd65 Updated var declarations to const/let and no lists
- All var declarations are now const or let as per ES6
- All comma-separated lists / chained declarations are now one declaration per line
- This is for clarity/readability but also made running the var-to-const/let switch smoother
- ESLint rules updated to match

How this was done:

- npm install -g jscodeshift
- git clone https://github.com/cpojer/js-codemod.git
- git clone git@github.com:TryGhost/Ghost.git shallow-ghost
- cd shallow-ghost
- jscodeshift -t ../js-codemod/transforms/unchain-variables.js . -v=2
- jscodeshift -t ../js-codemod/transforms/no-vars.js . -v=2
- yarn
- yarn test
- yarn lint / fix various lint errors (almost all indent) by opening files and saving in vscode
- grunt test-regression
- sorted!
2020-04-29 16:51:13 +01:00
Kevin Ansfield
d255d98bbb Improved display of video embed cards in member emails
refs core/server/api/canary/oembed.js

- updated `kg-default-cards` to a version that will render a thumbnail and play button overlay for video embed cards when rendering to an email target
- added styling for video embed play button overlays to members email template
2020-04-29 16:44:20 +01:00
Hannah Wolfe
0fe0e09d62 Moved express init + sentry to a shared util
- added core/shared to watched folders in grunt
- moved sentry to shared
- moved express initialisation to a shared file
- always set trust proxy + sentry error handler
- use this new express init everywhere, and remove duplicate trust proxy and sentry error handler code
2020-04-27 18:17:50 +01:00
Kevin Ansfield
cd04262889 🐛 Fixed publish date in emails not respecting site's configured timezone
closes https://github.com/TryGhost/Ghost/issues/11659

- default `moment()` timezone is UTC and we store the `published_at` value in UTC
- fetch the configured timezone and convert the date into that timezone before formatting for inclusion in the email template
2020-04-27 11:38:11 +01:00
Rish
d0a16112f5 Fixed incorrect member first name in session data
no issue

Fixes a copy bug on how member's first name is calculated while getting member's session data in theme
2020-04-22 19:28:43 +05:30
Rish
29bc241cf6 Exposed member session data on site
refs https://github.com/TryGhost/members.js/issues/6

This exposes an endpoint on site url (`/members/ssr/member`) to get member's data in exchange for their session/identity on a theme when they are logged in. It essentially uses the same logic and data which is passed down to theme through handlebar helpers, and is used by members.js script to load member data.
2020-04-21 23:35:16 +05:30
Rish
4b654aaaf6 Added method to fetch public membership plans
no issue

This allows anyone using members service to fetch public membership plans for a site including currency and monthly/yearly charges. This is currently duplicated from theme service where we create the price helper, but will be cleaned up to keep logic in one single place.
2020-04-21 23:35:16 +05:30
Hannah Wolfe
0897b0ef3c Unhooked shared mw from members service 2020-04-21 17:04:20 +01:00
Kevin Ansfield
c5f7adf917 Fixed "view sent email" showing mailgun template variables
no issue

- the `email.{html,plaintext}` fields are only used to display what was sent in the email so it doesn't make sense to store the mailgun-specific content which can be confusing when viewing in the admin area
- store the raw serialized post content with a basic no-data replacement of replacement strings rather than the output of full data fetching and mailgun transformation
2020-04-20 15:35:33 +01:00
Kevin Ansfield
9981ea336c Changed {subscriber_firstname} replacement to {first_name}
no issue

- easier to remember and type
- removes need to remove the `subscriber_` prefix when accessing member properties
2020-04-20 14:25:58 +01:00
Kevin Ansfield
a09a6caf5f Fixed in-browser email preview showing raw replacement strings
no issue

- fixed plaintext templates being word wrapped and breaking across replacement strings
- updated `postEmailSerializer.serialize` to return the email template plus a replacements array that can be used for creating Mailgun-like recipient variable objects or more straight forward replacement
- updated email-preview API to work with the replacements data to show fallback data when previewing
2020-04-20 12:24:05 +01:00
Kevin Ansfield
e0e0a85a32 Updated test emails to fetch member data if email matches
no issue

- with the email replacements feature it's useful to have real member data when sending test emails from the PSM
- if the supplied email address matches a member then that member's data will be used for any replacements
2020-04-17 12:15:39 +01:00
Kevin Ansfield
d0393b6223 Fixed {subscriber_firstname} not picking up member's name in emails
no issue

- in our replacements the member properties are prefixed with `subscriber_` but this wasn't taken into account when requesting data from the member object
2020-04-17 12:15:39 +01:00
Kevin Ansfield
374b43ceab Fixed linting error 2020-04-17 11:32:29 +01:00
Kevin Ansfield
a801352c7f Added email card and replacement handling to member emails
no issue

- adjusted mega's post serializer to get full email contents
  - fetch `mobiledoc` from the API rather than the pre-rendered `html` and `plaintext`
  - re-generate `html` using the mobiledoc renderer with an "email" target so that the email-only card content is included
  - re-generate `plaintext` from the newly generated email html

- added replacement handling to mega's `getEmailData` function
  - find all of our `%%{replacement "fallback"}%%` instances in the html template and push them into a replacements array with the respective property on the member instance and desired fallback
  - transform the replacement for Mailgun compatibility. Mailgun uses `%recipient.variable_name%` for its template variables so we need to replace our custom replacement string with the compatible version. Our replacements system allows for the same replacement (`{subscriber_name}`) to be used multiple times and have different fallbacks, Mailgun doesn't support fallbacks so for each replacement we also need an indexed `variable_name` part so that we can put our fallbacks in the correct place
  - perform the same Mailgun template transformation for the plaintext version except we re-use the replacements array to avoid bloating the API request to Mailgun with duplicate template variables for every recipient
  - swapped `reduce` for a plain loop for easier readability
2020-04-17 10:23:03 +01:00
Fabien O'Carroll
a701ee7023
Added support for token session to /ghost (#11709)
no-issue

* Added default for getting origin of request

This function is used to attach the origin of the request to the
session, and later check that requests using the session are coming from
the same origin. This protects us against CSRF attacks as requests in
the browser MUST originate from the same origin on which the user
logged in.

Previously, when we could not determine the origin we would return
null, as a "safety" net.

This updates the function to use a secure and sensible default - which
is the origin of the Ghost-Admin application, and if that's not set -
the origin of the Ghost application.

This will make dealing with magic links simpler as you can not always
guaruntee the existence of these headers when visiting via a hyperlink

* Removed init fns and getters from session service

This simplifies the code here, making it easier to read and maintain

* Moved express-session initialisation to own file

This is complex enough that it deserves its own module

* Added createSessionFromToken to session service

* Wired up the createSessionFromToken middleware
2020-04-06 11:49:14 +02:00
Fabien O'Carroll
d0bb8c3333 Added base and default SSO Adapter
no-issue
2020-04-05 21:13:47 +02:00
Fabien O'Carroll
fb942af1db Added adapter-manager service
no-issue

This services handles the registration and retrieval of adapters,
it normalises the config to look like:

{
    [adapterType]: {
        active: adapterName,
        [adapterName]: adapterConfig
    }
}
2020-04-05 21:13:47 +02:00
Fabien O'Carroll
23154f0739
Refactored session service (#11701)
* Refactored SessionStore to use @tryghost/errors

no-issue

* Updated tests to test exposed API

no-issue

This will make refactoring easier, as we only have the "public" contract to maintain

* Refactored session functionality to SessionService

no-issue

This splits the session logic away from the HTTP responding logic,
which will allows us to decouple session creation/modification from the
API. Eventually this can be used to create sessions based on magiclink
style tokens.

* Instantiated and exported the new SessionService

no-issue

* Refactored session middleware to take session service

no-issue

This removes duplication of code and makes the middleware more explicit
that it's just a wrapper around the session service.

* Updated to use external @tryghost/session-service

no-issue
2020-04-02 16:27:31 +02:00
Daniel Lockyer
23eb3e7c14 Added missing semicolon
no issue
2020-03-26 16:45:33 +00:00
Daniel Lockyer
8f935fe8ae Fixed Slack service throwing error when post is empty
fixes #11694

- if the post contained no body, the `.replace` would throw an error
- converted to an if-statement instead of doing `|| ''` because there
  would be a floating full-stop
2020-03-26 16:38:30 +00:00
Hannah Wolfe
7e0c71509b Moved apps service to frontend
- App service is for our internal frontend apps
- This is a very straightforward move as this truly belongs to frontend
2020-03-23 19:43:01 +00:00
Hannah Wolfe
8c1a0b8d0c Remove External Apps
- Apps are marked as removed in 3.0, never officially launched and have been deprecated for at least 2 years.
- We've slowly removed bits that got in our way or were insecure over time meaning they mostly didn't work
- This cleans up the remainder of the logic
- The tables should be cleaned up in a future major
2020-03-20 10:40:22 +00:00
Hannah Wolfe
bc7906a7b2 Revert "Remove Apps"
This reverts commit cbb59a57db.
2020-03-20 08:58:26 +00:00
Hannah Wolfe
cbb59a57db Remove Apps
- Apps are marked as removed in 3.0, never officially launched and have been deprecated for at least 2 years.
- We've slowly removed bits that got in our way or were insecure over time meaning they mostly didn't work
- This cleans up the remainder of the logic
- The tables should be cleaned up in a future major
2020-03-19 19:06:17 +00:00
Rish
5f349b3ef7 🐛 Fixed missing publication icon in newsletter emails
no issue

Email template was incorrectly setting up publication icon url in case of subdirectory setup, leading to missing publication logo from newsletter emails in such cases. This adds the fix to use correct absolute url for publication icons in all setups.
2020-03-12 09:52:54 +05:30
Fabien O'Carroll
801608e077
Fixed permission to only fetch for active users (#11641)
no-issue

Essentially only active users should have their permissions loaded, this
means that suspended or inactive users are stripped of all permissions
until their status is changed.
2020-03-05 12:22:50 +02:00
Daniel Lockyer
edfc07b9c8 Captured bulk-email errors in Sentry
no issue
2020-03-04 13:44:23 +00:00
Nazar Gargol
258bcc71bf Added minified members.js file handling
refs 91984b54ca

- For request effieciency we should be using a minified file just like we did previously with `ghost-sdk.js`
- Modified 'max-age' caching header to 1 year  for both minified and non-minified files as thay won't affect dev environment and should be beneficial for self-hosting instances that don't use minification
- Along the way corrected an extra 301 redirect because `/public/member.js` path wasn't using a bakslach in the end.
2020-02-26 14:08:10 +08:00
Naz
3af621ea9a
Added handling allowing members to edit their billing info (#11571)
no issue

- This functionality allows member to update their billing information, like credit card information.
- Adds handler to update Stripe billing when element with `data-members-edit-billing` attribute is present on the page. Additional `data-members-success` and `data-members-cancel` attributes could be used to control the redirects on billing update success or failure. They work in the same fission as for 'members-plan' (https://ghost.org/docs/members/checkout-buttons/#redirects)
2020-02-26 12:42:41 +08:00
Rishabh Garg
3815c0769a
🐛 Fixed incorrect email count on post publish (#11616)
no issue

The email data attached to a post when published with send email flag was not filtered on member access, and picked up the whole member list for email data. This resulted in incorrect data stored in emails table even in case of paid-members-only publish, and also incorrect count of "emails sent" being displayed on Admin.

NOTE: The actual emails being sent are still gated by member access, so no emails were sent to anyone without access, this only affected the associated email data and count. Also, the fix here will show correct email sent status for any future post, but will still show incorrect data for any already published posts as the email data in DB is already wrong and will probably need a migration
2020-02-24 16:34:07 +05:30
Rishabh Garg
9c1aa07ea8
Added host limit check for members email publish (#11534)
no issue
2020-02-13 10:43:36 +05:30
Nazar Gargol
51c2b22e9f 🐛 Fixed order for "Complimentary" plan creation
no issue

- When new Ghost instance is initialized "Complimentary" plan doesn't have to wait for the rest of plans to be configured.
- Without configured plans the admin would still be able  to assign "Complimentary" plan to members or import same kind of members.
- There is no error handling at the moment when plan initialization fails, that's why it was very confusing when all of the sudden it wasn't possible to create a member record
2020-02-11 17:14:41 +08:00