Commit Graph

53 Commits

Author SHA1 Message Date
Naz
05105e1173 Updated method signatures and added JSDocs
refs https://github.com/TryGhost/Team/issues/1674

- While preparing the changes had a look around and made small refactors to understand the codebase a little better. In general it's best to keep the method parameters as small and precise as possible instead of passing around a "bag-of-all-the-things" like "data" around
2022-07-14 12:54:58 +01:00
Naz
2a7166ffc3 Fixed typo 2022-07-14 12:10:18 +01:00
Simon Backx
011c7cb0a2 Added support for updating member enable_comment_notifications
refs https://github.com/TryGhost/Team/issues/1664

This makes it possible for members to update their comment notification preferences
2022-07-07 14:14:02 +02:00
Simon Backx
9b0259dc6f Removed usage of dashboardV5 feature flag
refs https://github.com/TryGhost/Team/issues/1616
2022-05-25 10:29:55 +02:00
Simon Backx
62c992c8e3 Improved bulk unsubscribe operation to use member_id column (#400)
refs https://ghost.slack.com/archives/C02G9E68C/p1652980792270029

When bulk unsubscribing members, the number of deleted newsletter relations are returned instead of the number of members with newsletters that were cleared. This update deletes newsletter relations on member_id, so we can return the count of members instead of newsletter relations that were deleted.

Tests in https://github.com/TryGhost/Ghost/pull/14871
2022-05-20 12:25:58 +02:00
Matt Hanley
f0798578c4 Fixed issue with filter transform not applying to bulk operations 2022-05-12 09:44:30 +01:00
Aileen Nowak
376db4d085 Removed duplicate usage of importer source
no issue

- Setting a dedicated source for imported members was already done with 455778662c
- This unifies the same source but keeps the usage of context setting on init alive
2022-05-10 10:53:19 -04:00
Simon Backx
eb8cf49f40 Fixed updating non-existing member internal error (#395)
refs https://github.com/TryGhost/Team/issues/1580

- When you tried to update a member that doesn't exist, an internal error was thrown
- It should throw a 'not found' error instead
- Optimized when to fetch the initialMember

Tests for 4.x in https://github.com/TryGhost/Ghost/pull/14657
Tests for 5.x in https://github.com/TryGhost/Ghost/pull/14658
2022-05-03 16:38:55 +02:00
Simon Backx
8a40d8e76b Fixed member webhooks (#394)
refs https://github.com/TryGhost/Team/issues/1577

The call to `edit` was not loading the newsletter relations which is needed
by the serializer used by the webhooks service.

Co-authored-by: Fabien "egg" O'Carroll <fabien@allou.is>
2022-05-02 19:07:30 +01:00
Simon Backx
3cb138ea25 Fixed events not having same created_at as members
refs https://github.com/TryGhost/Ghost/pull/14621
refs https://ghost.slack.com/archives/C02G9E68C/p1651126990299689?thread_ts=1651072733.859939&cid=C02G9E68C

- Events didn't always have the same created_at as created members
- This caused a test to fail randomly in the main repo
2022-04-28 09:29:41 +02:00
Aileen Nowak
ea237ebcee Used designated source importer for members event table
no issue

Using a designated source for members being added within the `importer` context will better describe the source in our members event table. It's more consistent with the usage of the other possible sources.
2022-04-27 15:27:19 -04:00
Aileen Nowak
dd702f6ef8 Allow setting context for members importer and use correct source
no issue

When importing members, the members-importer isn't aware of the context and therefore falls back to use `member` as a source in members event table. This makes it impossible to determine imported members from others.
- Added an `context` property to the options in the members-importer constructor
- Checked for `importer` context when creating member events and assigned the source `admin` to it
2022-04-27 15:27:19 -04:00
Simon Backx
f051f9aeeb Fixed bulk unsubscribe
refs https://github.com/TryGhost/Team/issues/1567

- Deletes the newsletter relations instead of setting subscribed to false
- Depends on these changes: https://github.com/TryGhost/Ghost/pull/14610
2022-04-27 19:03:33 +02:00
Simon Backx
27f48e743b Fixed linting error 2022-04-26 19:33:12 +02:00
Simon Backx
a82d0f499d Added mapping from member subscribed to newsletters on edit/create
refs https://github.com/TryGhost/Team/issues/1545

- When editing or creating a member with the subscribed property, it is mapped to the corresponding newletters value
- Defaults to all active newsletters with visibility = members and subscribe_on_signup = true
- Tests in https://github.com/TryGhost/Ghost/pull/14583
2022-04-26 19:28:05 +02:00
Simon Backx
6a6cc28e3d Added newsletter information in member subscribe events
refs https://github.com/TryGhost/Team/issues/1478

- When creating or editing a member, we'll add the newsletter ids to the subscribe events
- When susbcribing to multiple newsletters, we'll create multiple subscribe events
- When removing newsletters from a member, we'll create one or more subscribe events
- Tests in https://github.com/TryGhost/Ghost/pull/14579
2022-04-26 08:59:59 +02:00
Simon Backx
41e0aa17ff Updated offer_id matching logic to use stripe_coupon_id instead of metadata (#390)
refs https://github.com/TryGhost/Team/issues/1519

- Removed offer metadata again from offer (added in one of the previous commits)
- Added `getByStripeCouponId` method in offer repository (required to find an offer based on the stripe_coupon_id)
- Match discounts from Stripe based on the stripe_coupon_id instead of metadata
2022-04-19 11:21:48 +02:00
Simon Backx
f74b00fea6 Stored offer_id in subscriptions (#389)
refs https://github.com/TryGhost/Team/issues/1519

- Added offer repository dependency to member repository (offerAPI didn't work because it creates a new transaction that resulted in a deadlock during tests)
- Store the offer id from the Stripe subscription metadata in the subscription (only if the discount is still active)
- Also added the offer id to the metadata for a Stripe coupon, this will make adding and removing coupons a bit more foolproof
- Prefer the usage of the offer metadata from a coupon if it is present
- When no discount is applied to a subscription, it always sets the offer id to null, even when the metadata still contains the offer
- The offer_id remains stored when a subscription is canceled/expired
2022-04-19 09:15:33 +02:00
Rishabh
f9ce2d9064 Updated default newsletter subscriptions for member
refs https://github.com/TryGhost/Team/issues/1469

Previously, members were subscribed to all available newsletters by default when added. This change updates the default newsletters subscription for member to take into account newsletter preferences for auto opt-in as well as visibility.
2022-04-14 21:10:58 +05:30
Sam Lord
455778662c Email verification for imports based on 30 days of import
refs: https://github.com/TryGhost/Toolbox/issues/293

Things needed to create this:
* MemberSubscriptionEvent now has an import source
* Importer now creates events with this type
* Verification trigger logic changed to use 30 day window of imports
2022-04-13 17:35:30 +01:00
Simon Backx
fab8a182d1 Updated mrr_delta to use stored mrr and consider forever offers (#387)
* Updated member mrr_delta calculation to use stored mrr

refs https://github.com/TryGhost/Team/issues/1456

Simplifies the calculation of MRR deltas, which will make it easier to update MRR to include offers and cancellations in the future.

* Adjusted MRR and MRR delta calculation to consider "forever" duration offers

refs https://github.com/TryGhost/Team/issues/1451

Uses the discount information from Stripe to calculate the MRR (this was the easiest way to include it + also supports manually created discounts from users)
2022-04-13 15:46:43 +02:00
Fabien "egg" O'Carroll
4c7a7027a9 Fixed storage of MRR Events type
This was incorrectly attempting to store the `name` column which was
renamed to `type`
2022-04-12 11:17:39 +01:00
Simon Backx
da4df59ba9 Save MRR to subscriptions (#386)
refs https://github.com/TryGhost/Team/issues/1456

- Sets the `mrr` column correctly when updating a subscription
- We can use this value in the future to have an improved calculation of mrr_delta, but we first need to have the migration in place
- Updated missing cancelled -> canceled
2022-04-12 11:19:09 +02:00
Fabien 'egg' O'Carroll
027332b80e Updated MRR events (#385)
refs https://github.com/TryGhost/Team/issues/1454

Updates the MRR events to store the type column for existing events, this
includes expired events.

---

refs https://github.com/TryGhost/Team/issues/1302

Creates MRR events when the cancelled status of a subscription has changes

---

refs https://github.com/TryGhost/Team/issues/1453

Updates the cancelled MRR Event logic to make a negative MRR delta, this
is behind a flag so everything can be release at once

Co-authored-by: Simon Backx <simon@ghost.org>
2022-04-12 11:06:11 +02:00
Fabien 'egg' O'Carroll
1c017c7b7d Used FOR UPDATE lock for linkSubscription reads (#383)
refs https://github.com/TryGhost/Team/issues/1248
refs https://github.com/TryGhost/Team/issues/1302

This fixes the issue with duplicate subscriptions being inserted because
concurrent calls to linkSubscription did not have rows locked.

It is also required to make sure we do not create duplicate cancellation events.
2022-04-07 15:12:55 +01:00
Rishabh
45080a0ab2 Handled default newsletter subscription for new members
refs https://github.com/TryGhost/Team/issues/1469

When a new member signs up on the site, by default they should get subscribed to all newsletters. A new member can get added via different ways (stripe webhook, admin add, free signup), so this change updates the base member repository which gets used irrespective of how member is added to ensure default newsletters are always included for new member.
If a member already has a custom newsletters list attached, we don't change anything.
2022-04-06 15:41:02 +05:30
Rishabh
b3ed042265 Allowed updating newsletter data for a member
refs https://github.com/TryGhost/Team/issues/1469

- allows editing multiple newsletter subscriptions for a member
2022-04-04 20:07:37 +05:30
Thibaut Patel
8b7d9281d3 Added MemberCancelEvent
refs https://github.com/TryGhost/Team/issues/1302

- This event is triggered on subscription cancellation
2022-03-11 22:44:28 +01:00
Hannah Wolfe
3dcf85d5e4 Ensured correct usage of @tryghost/errors everywhere
refs: 23b383bedf

- @tryghost/error constructors take an object, not a string - the expectation is that message, context & help should all be set
- This does the bare minimum and just ensures message is set correctly
2022-02-15 12:30:36 +00:00
Fabien "egg" O'Carroll
d7d7806dcf Protected against null value for subscription.plan
no-issue

This will only occur when Subscriptions have manually been modified in
Stripe to no longer have a single price.
2022-02-09 11:28:26 +02:00
Fabien 'egg' O'Carroll
73418e8749 Ran Comped subscriptions in transaction (#360)
no-issue

We were incorrectly mixing transactional and non-transactional
operations. An e2e test in Ghost will be merged shortly which caught
this problem.
2022-02-01 17:05:22 +02:00
Sam Lord
3c5cf21274 Added email verification trigger package
refs: https://github.com/TryGhost/Toolbox/issues/166

New package handles the email verification workflow to prevent spammers. It currently handles MembersSubscribeEvent to detect potential abuse of the API to add members, and exposes methods for checking the threshold / starting the verification process for use by other areas of the code (at the moment - just member imports).

The import package no longer needs to handle anything related to verification since it can be handled in the wrapper function in Ghost, and the API package doesn't need to do anything other than dispatch the new event.
2022-01-27 10:57:51 +00:00
Fabien "egg" O'Carroll
73f8db0e37 Restricted Members from being given archived Tiers
refs https://github.com/TryGhost/Team/issues/1252
2022-01-24 11:45:54 +02:00
Rishabh Garg
ca18f140c4 Handled new type column for tiers (#356)
refs https://github.com/TryGhost/Team/issues/1037

Tiers have a new `type` column to differentiate between `free` and `paid` tiers. This change -

- sets type as paid for all new tiers created, as `free` tier is created by default
- excludes any price/stripe data change for free tier
- updates all usages of default product to fetch the first paid product from the products list in DB instead of just the first product it finds.
2022-01-17 23:02:02 +05:30
Fabien "egg" O'Carroll
cacc74f3b4 Added "api" source to MemberSubscribedEvents
refs https://github.com/TryGhost/Team/issues/1275

We want to be able to track where member subscriptions came from, so
that we can use the information to reduce spam imports of members.

We were missing information when members were uploaded via the Admin
API, and setting the source to 'member' be default - this fixes that
both when creating members and when updating their subscription status.
2022-01-14 12:19:43 +02:00
Fabien "egg" O'Carroll
a7588e3c6b Fixed transactions for linkSubscription
no-issue

This was missed when transactions were implemented for this method.
2022-01-10 17:53:30 +02:00
Sam Lord
ba2c0818e0 Use @tryghost/logging instead of injected argument 2021-12-02 14:46:58 +00:00
Fabien O'Carroll
b20f5a8b1f Updated linkSubscription to call method in transaction
no-issue

This was missing the options object which would force the DB call to be
run inside the same transaction as the rest
2021-11-09 11:19:05 +02:00
Fabien O'Carroll
2fcafcc8dc Removed coupons from subscriptions when the price changes
refs https://github.com/TryGhost/Team/issues/1092
refs https://github.com/TryGhost/Team/issues/1135

This was missed in the initial due to the issue tracking the task being
superceded, and the task not being copied across to the superceding
issue.

A new method to remove coupons has been added, as opposed to updating
the existing change subscription price method, because the removal of a
coupon is not the concern of an auxillary stripe service, but a busines
concern that should be explicit in the members-api codebase.
2021-11-09 11:12:13 +02:00
Fabien O'Carroll
8051015bb8 Fixed race condition when linking subscriptions
no-issue

Without forcing linkSubscription to run inside a transaction - it's
possible to have race conditions where it is called twice, and attempt
to insert duplicate rows into the database.
2021-10-18 17:26:34 +02:00
Fabien O'Carroll
c58e83c9d7 Wired up OfferRedemption storage
refs https://github.com/TryGhost/Team/issues/1132

We have to include the Offer on the metadata for the Stripe Checkout -
as Offers with a duration of 'once' will not always be present on the
Subscription after fetching it.

Once we receive the Stripe Checkout webhook we emit an event for
subscription created - the reason we use an event is because this logic
should eventually live in a Payments/Stripe module - and we'd want to
decouple it from the Members module.

The Members module is in charge of writing Offer Redemptions - rather
than the Offers module - because Offer Redemptions are "owned" by a
Member - and merely reference and Offer. Eventually Offer Redemptions
could be replaced by Subscriptions.
2021-10-18 17:26:34 +02:00
Fabien 'egg' O'Carroll
9e3136cdbc Fixed incomplete subscription flow (#341)
refs https://github.com/TryGhost/Team/issues/1156

Because we were only attempting to add the product to the members if the
subscription was new AND active - we would not add it for incomplete
subscriptions transitioning to active.

Instead we always attempt to add the product to a member for an active
subscription - it doesn't matter if it's a new one. We later have logic
to filter out duplicate products if the member already has access to the
product.
2021-10-18 14:25:28 +02:00
Fabien 'egg' O'Carroll
528fd23874 Added ability to fetch member by identity token (#329)
refs https://github.com/TryGhost/Team/issues/1057

This method will validate a token, and then return the member associated
with it. Rather than exposing token validation and coupling consumers to
the structure of the token response data.
2021-09-17 11:25:57 +02:00
Fabien O'Carroll
b6e4eae272 Fixed comped members having a status of 'paid'
refs https://github.com/TryGhost/Team/issues/995

Since we reintroduced the comped status, we did not update the
subscription handling to correctly set members to a status of comped
when they were on a 'Complimentary' plan.
2021-09-06 13:06:30 +02:00
Fabien O'Carroll
d3b1283241 Removed old product when subscription is updated
refs https://github.com/TryGhost/Team/issues/979

This correctly handles updates to subscriptions so that if the product a
subscription is for has changed, we will remove the previous product, if
and only if there is not another subscription which gives access to it.
2021-08-26 15:53:38 +02:00
Fabien O'Carroll
d55e828b34 Wired up MemberProductEvents to MemberRepository
refs https://github.com/TryGhost/Team/issues/873

This handles the creation of product events when a members access to
products is changed. This can happen on creation, update, and any
changes to stripe subscriptions.

We manually workout the difference between the current products and the
new products, and add the events accordingly.
2021-08-24 14:57:04 +02:00
Fabien O'Carroll
4b219626eb Fixed usage of bson-objectid
no-issue

Calling ObjectId doesn't return a string a but an ObjectId object.
Whilst this object is cast to a string via the toJSON and toString
methods, this is not enough for MySQL. Instead we should explicitly cast
this to a string ourselves and the application level.
2021-08-23 14:46:53 +02:00
Fabien 'egg' O'Carroll
4a8ec62317 Added bulkEdit method to MemberRepository
refs https://github.com/TryGhost/Team/issues/946

This adds the bulk edit method which handles bulk edit operations to members
to be used by the filtering feature. They have been combined into a single method
as that is how they are exposed to the API. This is definitely a candidate for a
refactor in the form of a service in front of the repository.
2021-08-16 19:05:48 +01:00
Fabien O'Carroll
6540fd0cd0 Updated bulkDestroy method to handle model updates
refs https://github.com/TryGhost/Ghost/commit/1dd52075

- Fixes bulkDestroy being passed the context
- Fixes passing options.search to the model layer
- Updates return value since the changes in referenced commit
2021-08-13 13:23:01 +02:00
Fabien O'Carroll
6bb3407725 Added bulkDestroy method to Member Repository
no-issue

The logic for bulk destroy is currently incorrectly inside of the
members api controller in Ghost core. Moving it out to here allows us to
simplify the controller to rely on the service, rather than implement
the logic.
2021-08-12 13:57:45 +02:00