refs https://github.com/TryGhost/Team/issues/694
- The controller code is not meant to contain complex business logic.
- Kept the pattern used in all modules under services/themes. The install module shold be refactored into a class with DI pattern when touched next.
refs https://github.com/TryGhost/Team/issues/694
- Additional try/catch block needed in async/await implementation increased method complexity and broke the complexity linting rule. This is a dirty way to fix the warning. Ideally the implementation should stay with async/await syntax and instead move the custom error handling logic into some different layer. For example we could introduce a separate "stage" in the API framework's "pipeline" where we'd catch and handle in a generic way all of the "unique" types of errors. It would make sense to have a generic handler because this same code happens in labels, member and few more places.
refs baccbb4942
refs https://github.com/TryGhost/Team/issues/694
- The change is here to remove yet another ESLint method complexity error
- The custom error handling complexity was introduced here in a referenced commit without an obvious reason. The specifics of how the "sendTestEmail" method handles errors should not leak out from the method, if there are errors in the response they should be handled internally and the method would uniformly reject with a single error.
refs https://github.com/TryGhost/Team/issues/694
- The code complexity in the email preview's read controller method was breaking the complexity rule in ESLint. To reduce the complexity extracted common parts into mega service
no refs
- adds refinements to change plan UI in Portal
- adds other UI refinements to Portal for multiple tiers
- updates scrolling behavior in Portal in preview mode
- bumps `@tryghost/portal` to `1.9`
refs https://github.com/TryGhost/Team/issues/694
- async/await has been a standard way to handle async code throughout the codebase. Refactoring it before moving code makes it way easier to reason about similarities between multiple controllers
refs https://github.com/TryGhost/Team/issues/947
- During the work of the UI and moving `email_only` flag to publish menu it created the situation where the publishing of the post was at the same time as adding `email_only` flag, resulted in not picking up teh `sent` status as the `posts_meta` model and record were's available during save.
- Adding the incoming attribute check for email_only flag covers this situation
no-issue
Writing code outside of Ghost which deals with the models is currently
done by passing the models which are needed to the external module,
rather than the instance of ghostBookshelf. This does not give us a way
to create transaction to run queries in. This method is designed as a
simple way to give all models the power to create a transaction for
themselves.
This will be used in @tryghost/members-api for example to ensure that
failures in communication with the Stripe API will rollback the related
inserts in the database.
refs https://github.com/TryGhost/Team/issues/873
This includes the update to @tryghost/members-api which includes the new
MemberBREADService which is used to handle the logic for controller
methods outside of the controller.
With it, we've introduced the concept of a dummy subscription for comped
members. This gives API consumers a way to get the created_at date for a
comped members access to a product.
no-issue
The @tryghost/members-api module is being updated to export a BREAD
service which will be used to move the logic from the controller into.
This service is currently designed to returns objects rather than
models, as it has to do manipulation of the returned data at the object
level. This update to the serializer will allow a seamless transition to
the use of the BREAD service and allow us to pull out the logic from the
controller sooner!
refs 3f0bab4389
- the internal `request` lib we had was replaced with `@tryghost/request` in
the referenced commit
- this lib was not deleted, so it's still lingering around
- this commit deletes that file to clean it up
no-issue
The bluebird library is unecessary in this module, as all uses of it
were wrapped in `async` functions which will return a native Promise
rather than a bluebird one.
refs https://ghost.slack.com/archives/C02G9E68C/p1629822160273500
refs https://github.com/TryGhost/Team/issues/1007
- `:root` selector wasn't working as expected and ended up matching HRs within content
- switched to wrapping the post html inside a `<body>` element before parsing so that we have a proper top-level element for direct child selectors to match against
refs https://github.com/TryGhost/Team/issues/1007
- the new `email-cta` card allows surrounding dividers to be added when rendering, however if the card is at the beginning or end of the post then these would double-up with the already existing dividers at the beginning and end of the post content in the email template
- not wanting leading/trailing HR's is specific to the email template so it made sense to adjust the renderer output in Ghost's email generating rather than forcing all mobiledoc->html rendering to remove leading/trailing HR's
refs https://github.com/TryGhost/Team/issues/873
The @tryghost/members-api module needs access to this model in order to
create events when members access to products are updated.
refs https://github.com/TryGhost/Team/issues/873
We need a relation between members and their product events so that we
can pull out the events for a particular member to generate the start
date of their comped access to a product.
refs https://github.com/TryGhost/Team/issues/946
This adds the initial bulk actions endpoint used for the members
filtering feature. The idea is to eventually move bulk destroy into this
endpoint to and provide a consistent interface for applying bulk actions
to members.
The @tryghost/members-api package has been bumped to include the new
bulkEdit method.
The sinon.restore in tests was moved to an afterEach so that stubs did
not effect other tests.
refs https://github.com/TryGhost/Team/issues/946
In order to bulk remove relations between members and labels we need a
way to get hold of all of the existing relations between a label and a
set of members.
refs https://github.com/TryGhost/Team/issues/873
This table is to track events related to members be given or having
removed access to products. It will allow us to provide start dates for
access for complimentary members, as well as being able to track access
to products over time, either for individual members or for aggregates.
no issue
- The method was super hard to read with unintuitive catches in multiple places and lots of conditional logic. There's still more to reshuffle here, but that would be for the next time. At least now the data flow is clear within the method
no issue
- Logic with slightly more complex structure belongs to the service. Extracting it there also show's how little of an API the oembed service should actually expose
refs https://github.com/TryGhost/Team/issues/906
- The feature has moved to GA from behind alpha flag. It's skipping the beta phase as it's not needed in this specific situation
refs https://github.com/TryGhost/Team/issues/714
In order to order products by their monthly price we need to apply a
join with the stripe_prices table when querying so we have access to the
amount column of stripe_prices.
As this ordering is core to how the tiers feature is intended to work,
we have added it as the default order. But this can be overriden by
manually passing the order option.
Also ensured that we do not create duplicate products in test fixtures
refs https://github.com/TryGhost/Team/issues/990
- Relying on uuid instead of slug makes the posts less discoverable and partially soves discoverability through overriden robots.txt files
refs https://github.com/TryGhost/Team/issues/958
- The module contains a service class and not an api index as index.js file should. This rename also fixes an ESLint warning around index.js file being too complicated.
- The serivice should ideally be extracted into the member repository in the future iteration
refs https://github.com/TryGhost/Team/issues/973
- alpha flag for Admin feature that allows for replacing a snippet's content without having to delete and recreate it manually
refs 9e2b21578a
Since the ref'd commit the labs middleware was moved to the shared labs module
and this require path no longer exists. This does not break anything as any module
still using this would error when reading the labs property
- Unquestionably, at some point we need to rework the API code so that we have less stuff everywhere
- However, the max-lines index.js rule exists as a proxy to find index.js files which are not exposing Public API, but rather contain logic
- These 6 cases are all valid index.js files as the expose the Public API of the module
- Therefore, I've added an override and an override notice explaining.
refs https://github.com/TryGhost/Team/issues/946
This refactor pulls out the core logic so that we can easily add other
bulk operations without having to duplicate even more logic.
It also gives a consistent return value between bulk operations, renaming
`unsuccessfulIds` and `unsuccessfulRecords` to `unsuccessfulData`
We also add a bulkEdit method which will be used to bulk unsubscribe members
from the newsletter.
refs https://github.com/TryGhost/Team/issues/959
Since we had a bug where members with a canceled subscription would have
a status of 'comped' we must fix any existing members in this state.
We update all members which have no products to a status of 'free',
which is the definition of a 'free' member.
refs https://github.com/TryGhost/Team/issues/953
- Emails posts should be not explorable by the rest of the frontend similarly to the draft or scheduled posts. Email posts should also keep the content gating, so that specific parts of content can still be gated based on the post's visibility setup
- A separate frontend router was chosen to implement this part of the system instead of a moutable express app due to increased complexity to introduce the latter approach.
- All "sent" email-only posts will be accessible through the `/email/:slug/` route
refs https://github.com/TryGhost/Team/issues/899
- The internal API is needed to be able to fetch email-only posts through email router. The concept is similar to Preview API with a difference that only posts with `sent` status are accessible and there is content-gating present.
refs https://github.com/TryGhost/Team/issues/953
- We need to track email-only posts that have been sent out. New status was chosen as a way to differenciate such posts.
- Introducing a new "email post" type, conceptually like "page", was considered. Because there is no clear roadmap for "email post" becoming a bigger part of the product yet and a lot of uncertainty around this concept, overhead needed to introduce a new type was just too much to do at this moment. It's still a possibility in the future
no-issue
This moves the logic out of the controller and into the members-api
member repository. Removing complexity from the controllers and
out into services is desirable to reduce code in the Ghost codebase
and move logic into modules which can be tested easier.
closes https://github.com/TryGhost/Team/issues/952
- The `/email/` route will be a home for email only posts. We are adding the route preemptively to have the crowlers update their caches before the feature sees the light of The Internet
refs https://github.com/TryGhost/Team/issues/948
- The frontend route `/email/:uuid` is aliased to the preview as a temporary solution. It fulfills the premise of the email-only post anyway - not being accessible publicly and only shared through email.
- The tests for the new route are missing as adding them was way more problematic than I envisoned. They are in the works and will be added as a follow up commit next.
refs https://github.com/TryGhost/Team/issues/949
- When post is marked as "email-only" we can send it out to the selected audience when publishing without making the post publicly available
- The feature is available for experimentation behind "email only" alpha flag available in labs
refs https://github.com/TryGhost/Team/issues/949
- Initializing PostsService with almost identical parameters is burdensome, having a single factory method in create instances is far more maintainable
refs https://github.com/TryGhost/Team/issues/949
- It's relly hard to grasp what's going on in ifs with multiple conditions that are written down in a signle, gazzilion-line format. Having a nice column as way more readable
refs https://github.com/TryGhost/Team/issues/949
- The post model handling related to newsletter sending and email recipient filter logic were duplicating across v3/v4(canary) APIs and it made sense to extract it into a posts service.
- This will allow for a central place to handle about to land logic for email_only newsletter handling.
refs https://github.com/TryGhost/Team/issues/949
- The code is exactly the same in six (!) places. It's beyond unmaintainable to add another line to any of these place, which will be needed for `email_only` handling.
- The newly created posts service is a temporary, slightly better solution that complies with codebase's best practice of extracting new services using class with DI pattern
refs https://github.com/TryGhost/Team/issues/949
refs e64274bb45
- This refactor is needed to bring the code in line with the rest of pages API controllers
- Next step will extract shared code patterns into a separate module
refs https://github.com/TryGhost/Team/issues/949
refs e64274bb45
- This refactor is needed to bring the code in line with the rest of pages API controllers
- Next step will extract shared code patterns into a separate module
refs https://github.com/TryGhost/Team/issues/949
- This refactor is needed to bring the code in line with the rest of post API controllers
- Next step will extract shared code patterns into a separate module
https://github.com/TryGhost/Team/issues/893
- The assignment is not that obvious and might be confusing without wider context, which is why it warrants to have a clarifying comment. This became apparent during code review
refs https://github.com/TryGhost/framework/pull/19
The @tryghost/bookshelf-filter plugin no longer bundles hardcoded
relations and expansion definitions, instead leaving it up to the
library consumer to implement.
This PR adds the preexisting relations and expansions to the relevant
models, in order to preserve our existing filtering functionality.
refs https://github.com/TryGhost/Team/issues/902
- The flag will be controlling upcoming feature with the same name enabling exactly how it reads - ability to create posts available through the newsletter only
refs https://github.com/TryGhost/Team/issues/560
refs 69b773d112
The endpoint `/members/api/session/` is used by Portal for fetching member session while setting up and redirecting to Stripe Checkout flow. The status code returned by API for logged out member is changed from 4xx Unauthorized to 204 No Content, which is consistent with the status code returned while fetching member data when logged out. This API is made just before initiating the checkout session, and is not noticable in most cases due to redirect to Stripe Checkout and got missed.
refs https://github.com/TryGhost/Team/issues/928
- applied same darkening of accent color in emails as we use in editor when there's insufficient contrast of accent color against a white background
refs https://github.com/TryGhost/Team/issues/928
- duplicated email template so email-cta changes can go into the labs version
- added `accentContrastColor` to template settings for using white/black depending on the accent color
- added `.gh-btn-accent` styles to the email template (email-cta card already uses those for the button)
refs https://github.com/TryGhost/Team/issues/912
- When the improt acceedes the threshold for the first time we need a way to notify configured escalationAddress to verify the instance owner's email address.
closes https://github.com/TryGhost/Team/issues/913
- Having a limit service rule triggered was a temporary hack to get a basic email blocking version working
- As the freeze value is now persisted in the DB it's possible to read and rely on it to throw an error straight from MEGA.
refs https://github.com/TryGhost/Team/issues/912
- Previous logic was a bit misleading because it prevented from reading the real threshold configured with an instance once the verified flag was present in the config.
- The reshuffle made here allows to check the freeze logic based on the threshold and then process the returned result accordingly instead of having hidden logic behind "importThreshold" config value
refs https://github.com/TryGhost/Team/issues/912
- The email freeze state has to be stored somewhere to make it through the instance restart and settings table is the best place for it.
refs https://github.com/TryGhost/Team/issues/912
- We need a place to persist the email freeze state between instance restarts - settings table record is the best place for it
refs https://github.com/TryGhost/Team/issues/927
- the `email-cta` card can be segmented so only free or paid members can see the content, it should be possible for authors to preview what that will look like in either case
refs https://github.com/TryGhost/Team/issues/912
- The membersApi variable can be in uninitialized state. It should be accessed through membersService getter to make sure it's always correctly referenced
refs https://github.com/TryGhost/Team/issues/935
The problem was incorrect operator precedence when multiple statements existed in the filter original filter when we transform it to enforce `subscribed:true` before sending.
- free only - subscribed:true+status:free - no issue
- paid only - subscribed:true+status:-free - no issue
- all - subscribed:true+status:-free,status:free - the ,status:free part is treated as a separate OR statement meaning the subscribed:true is not applied to it and free members that are unsubscribed will receive the email
- extracted the filter transform into a separate function so it can be unit tested
- updated the transform to use `()` for operator precedence, eg: `subscribed:true+(status:-free,status:free)`
- used transform function in `addEmail()` and `getEmailMemberRows()`
- fixed `sent/send` typo in error message