ghost 5.65.1 → 5.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/{tryghost-adapter-cache-memory-ttl-5.65.1.tgz → tryghost-adapter-cache-memory-ttl-5.66.0.tgz} +0 -0
- package/components/{tryghost-adapter-cache-redis-5.65.1.tgz → tryghost-adapter-cache-redis-5.66.0.tgz} +0 -0
- package/components/{tryghost-adapter-manager-5.65.1.tgz → tryghost-adapter-manager-5.66.0.tgz} +0 -0
- package/components/{tryghost-announcement-bar-settings-5.65.1.tgz → tryghost-announcement-bar-settings-5.66.0.tgz} +0 -0
- package/components/tryghost-api-framework-5.66.0.tgz +0 -0
- package/components/{tryghost-api-version-compatibility-service-5.65.1.tgz → tryghost-api-version-compatibility-service-5.66.0.tgz} +0 -0
- package/components/{tryghost-audience-feedback-5.65.1.tgz → tryghost-audience-feedback-5.66.0.tgz} +0 -0
- package/components/tryghost-bookshelf-repository-5.66.0.tgz +0 -0
- package/components/tryghost-bootstrap-socket-5.66.0.tgz +0 -0
- package/components/tryghost-collections-5.66.0.tgz +0 -0
- package/components/tryghost-constants-5.66.0.tgz +0 -0
- package/components/{tryghost-custom-theme-settings-service-5.65.1.tgz → tryghost-custom-theme-settings-service-5.66.0.tgz} +0 -0
- package/components/{tryghost-data-generator-5.65.1.tgz → tryghost-data-generator-5.66.0.tgz} +0 -0
- package/components/{tryghost-domain-events-5.65.1.tgz → tryghost-domain-events-5.66.0.tgz} +0 -0
- package/components/tryghost-donations-5.66.0.tgz +0 -0
- package/components/{tryghost-dynamic-routing-events-5.65.1.tgz → tryghost-dynamic-routing-events-5.66.0.tgz} +0 -0
- package/components/tryghost-email-analytics-provider-mailgun-5.66.0.tgz +0 -0
- package/components/{tryghost-email-analytics-service-5.65.1.tgz → tryghost-email-analytics-service-5.66.0.tgz} +0 -0
- package/components/tryghost-email-content-generator-5.66.0.tgz +0 -0
- package/components/tryghost-email-events-5.66.0.tgz +0 -0
- package/components/{tryghost-email-service-5.65.1.tgz → tryghost-email-service-5.66.0.tgz} +0 -0
- package/components/tryghost-email-suppression-list-5.66.0.tgz +0 -0
- package/components/tryghost-event-aware-cache-wrapper-5.66.0.tgz +0 -0
- package/components/tryghost-express-dynamic-redirects-5.66.0.tgz +0 -0
- package/components/tryghost-external-media-inliner-5.66.0.tgz +0 -0
- package/components/{tryghost-extract-api-key-5.65.1.tgz → tryghost-extract-api-key-5.66.0.tgz} +0 -0
- package/components/{tryghost-html-to-plaintext-5.65.1.tgz → tryghost-html-to-plaintext-5.66.0.tgz} +0 -0
- package/components/tryghost-i18n-5.66.0.tgz +0 -0
- package/components/tryghost-importer-handler-content-files-5.66.0.tgz +0 -0
- package/components/{tryghost-importer-revue-5.65.1.tgz → tryghost-importer-revue-5.66.0.tgz} +0 -0
- package/components/{tryghost-in-memory-repository-5.65.1.tgz → tryghost-in-memory-repository-5.66.0.tgz} +0 -0
- package/components/{tryghost-job-manager-5.65.1.tgz → tryghost-job-manager-5.66.0.tgz} +0 -0
- package/components/tryghost-link-redirects-5.66.0.tgz +0 -0
- package/components/tryghost-link-replacer-5.66.0.tgz +0 -0
- package/components/{tryghost-link-tracking-5.65.1.tgz → tryghost-link-tracking-5.66.0.tgz} +0 -0
- package/components/tryghost-magic-link-5.66.0.tgz +0 -0
- package/components/tryghost-mail-events-5.66.0.tgz +0 -0
- package/components/{tryghost-mailgun-client-5.65.1.tgz → tryghost-mailgun-client-5.66.0.tgz} +0 -0
- package/components/{tryghost-member-attribution-5.65.1.tgz → tryghost-member-attribution-5.66.0.tgz} +0 -0
- package/components/tryghost-member-events-5.66.0.tgz +0 -0
- package/components/tryghost-members-api-5.66.0.tgz +0 -0
- package/components/{tryghost-members-csv-5.65.1.tgz → tryghost-members-csv-5.66.0.tgz} +0 -0
- package/components/{tryghost-members-events-service-5.65.1.tgz → tryghost-members-events-service-5.66.0.tgz} +0 -0
- package/components/{tryghost-members-importer-5.65.1.tgz → tryghost-members-importer-5.66.0.tgz} +0 -0
- package/components/{tryghost-members-offers-5.65.1.tgz → tryghost-members-offers-5.66.0.tgz} +0 -0
- package/components/{tryghost-members-payments-5.65.1.tgz → tryghost-members-payments-5.66.0.tgz} +0 -0
- package/components/{tryghost-members-ssr-5.65.1.tgz → tryghost-members-ssr-5.66.0.tgz} +0 -0
- package/components/{tryghost-members-stripe-service-5.65.1.tgz → tryghost-members-stripe-service-5.66.0.tgz} +0 -0
- package/components/tryghost-mentions-email-report-5.66.0.tgz +0 -0
- package/components/{tryghost-milestones-5.65.1.tgz → tryghost-milestones-5.66.0.tgz} +0 -0
- package/components/{tryghost-minifier-5.65.1.tgz → tryghost-minifier-5.66.0.tgz} +0 -0
- package/components/tryghost-model-to-domain-event-interceptor-5.66.0.tgz +0 -0
- package/components/{tryghost-mw-api-version-mismatch-5.65.1.tgz → tryghost-mw-api-version-mismatch-5.66.0.tgz} +0 -0
- package/components/tryghost-mw-cache-control-5.66.0.tgz +0 -0
- package/components/{tryghost-mw-error-handler-5.65.1.tgz → tryghost-mw-error-handler-5.66.0.tgz} +0 -0
- package/components/tryghost-mw-session-from-token-5.66.0.tgz +0 -0
- package/components/tryghost-mw-update-user-last-seen-5.66.0.tgz +0 -0
- package/components/{tryghost-mw-version-match-5.65.1.tgz → tryghost-mw-version-match-5.66.0.tgz} +0 -0
- package/components/tryghost-mw-vhost-5.66.0.tgz +0 -0
- package/components/tryghost-nql-filter-expansions-5.66.0.tgz +0 -0
- package/components/tryghost-oembed-service-5.66.0.tgz +0 -0
- package/components/{tryghost-package-json-5.65.1.tgz → tryghost-package-json-5.66.0.tgz} +0 -0
- package/components/tryghost-post-events-5.66.0.tgz +0 -0
- package/components/{tryghost-post-revisions-5.65.1.tgz → tryghost-post-revisions-5.66.0.tgz} +0 -0
- package/components/{tryghost-posts-service-5.65.1.tgz → tryghost-posts-service-5.66.0.tgz} +0 -0
- package/components/tryghost-recommendations-5.66.0.tgz +0 -0
- package/components/tryghost-referrers-5.66.0.tgz +0 -0
- package/components/tryghost-security-5.66.0.tgz +0 -0
- package/components/tryghost-session-service-5.66.0.tgz +0 -0
- package/components/{tryghost-settings-path-manager-5.65.1.tgz → tryghost-settings-path-manager-5.66.0.tgz} +0 -0
- package/components/tryghost-slack-notifications-5.66.0.tgz +0 -0
- package/components/tryghost-staff-service-5.66.0.tgz +0 -0
- package/components/tryghost-stats-service-5.66.0.tgz +0 -0
- package/components/tryghost-tiers-5.66.0.tgz +0 -0
- package/components/tryghost-update-check-service-5.66.0.tgz +0 -0
- package/components/{tryghost-verification-trigger-5.65.1.tgz → tryghost-verification-trigger-5.66.0.tgz} +0 -0
- package/components/tryghost-version-notifications-data-service-5.66.0.tgz +0 -0
- package/components/tryghost-webmentions-5.66.0.tgz +0 -0
- package/core/built/admin/assets/admin-x-settings/{CodeEditorView-2b332315.mjs → CodeEditorView-b1c6a306.mjs} +424 -418
- package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +2 -2
- package/core/built/admin/assets/admin-x-settings/index-02567620.mjs +17406 -0
- package/core/built/admin/assets/admin-x-settings/{limit-service-7694c0d4.mjs → limit-service-bf02ec54.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{modals-2073207d.mjs → modals-d2fd552b.mjs} +4281 -4177
- package/core/built/admin/assets/{chunk.143.c7348acc96d1ce431133.js → chunk.143.f2758c8aac6998f30b19.js} +5 -5
- package/core/built/admin/assets/{chunk.178.287163c7606fb9fd3267.js → chunk.178.1dd5d9b6741e78efa75a.js} +4 -4
- package/core/built/admin/assets/{chunk.518.396deed1a0c759d1f403.js → chunk.555.ba02d5a0095b4c4a7700.js} +57 -54
- package/core/built/admin/assets/{ghost-38746349a72536a92f4d8235a582d716.js → ghost-56045473f2cfd232419a9d27bf8225a5.js} +174 -182
- package/core/built/admin/assets/ghost-dark-54c925ac8f527d36132c18af7bef116e.css +1 -0
- package/core/built/admin/assets/ghost-f1a535bfec933b08a7a45f607cc245b1.css +1 -0
- package/core/built/admin/assets/{vendor-240cd1dbd84a2e07709b867442c41840.js → vendor-5aa07b661eeb443bf7dd2c1de3b3f387.js} +22 -20
- package/core/built/admin/index.html +6 -6
- package/core/frontend/helpers/recommendations.js +116 -0
- package/core/frontend/helpers/tpl/recommendations.hbs +15 -0
- package/core/server/adapters/scheduling/scheduling-default.js +8 -8
- package/core/server/api/endpoints/recommendations-public.js +2 -1
- package/core/server/api/endpoints/utils/serializers/output/utils/clean.js +1 -0
- package/core/server/data/migrations/versions/5.66/2023-09-22-14-15-add-recommendation-notifications-column.js +7 -0
- package/core/server/data/schema/schema.js +1 -0
- package/core/server/lib/image/Gravatar.js +1 -1
- package/core/server/lib/image/ImageSize.js +7 -3
- package/core/server/lib/request-external.js +9 -0
- package/core/server/models/post.js +46 -0
- package/core/server/models/user.js +3 -0
- package/core/server/services/collections/PostsRepository.js +7 -2
- package/core/server/services/comments/CommentsServiceEmails.js +1 -1
- package/core/server/services/mentions/BookshelfMentionRepository.js +2 -1
- package/core/server/services/mentions/service.js +4 -0
- package/core/server/services/recommendations/RecommendationEnablerService.js +1 -1
- package/core/server/services/recommendations/RecommendationServiceWrapper.js +68 -8
- package/core/server/services/themes/installer.js +1 -1
- package/core/server/services/webhooks/WebhookTrigger.js +6 -2
- package/core/server/services/xmlrpc.js +3 -1
- package/core/shared/labs.js +5 -0
- package/package.json +149 -149
- package/yarn.lock +283 -158
- package/components/tryghost-api-framework-5.65.1.tgz +0 -0
- package/components/tryghost-bookshelf-repository-5.65.1.tgz +0 -0
- package/components/tryghost-bootstrap-socket-5.65.1.tgz +0 -0
- package/components/tryghost-collections-5.65.1.tgz +0 -0
- package/components/tryghost-constants-5.65.1.tgz +0 -0
- package/components/tryghost-donations-5.65.1.tgz +0 -0
- package/components/tryghost-email-analytics-provider-mailgun-5.65.1.tgz +0 -0
- package/components/tryghost-email-content-generator-5.65.1.tgz +0 -0
- package/components/tryghost-email-events-5.65.1.tgz +0 -0
- package/components/tryghost-email-suppression-list-5.65.1.tgz +0 -0
- package/components/tryghost-event-aware-cache-wrapper-5.65.1.tgz +0 -0
- package/components/tryghost-express-dynamic-redirects-5.65.1.tgz +0 -0
- package/components/tryghost-external-media-inliner-5.65.1.tgz +0 -0
- package/components/tryghost-i18n-5.65.1.tgz +0 -0
- package/components/tryghost-importer-handler-content-files-5.65.1.tgz +0 -0
- package/components/tryghost-link-redirects-5.65.1.tgz +0 -0
- package/components/tryghost-link-replacer-5.65.1.tgz +0 -0
- package/components/tryghost-magic-link-5.65.1.tgz +0 -0
- package/components/tryghost-mail-events-5.65.1.tgz +0 -0
- package/components/tryghost-member-events-5.65.1.tgz +0 -0
- package/components/tryghost-members-api-5.65.1.tgz +0 -0
- package/components/tryghost-mentions-email-report-5.65.1.tgz +0 -0
- package/components/tryghost-model-to-domain-event-interceptor-5.65.1.tgz +0 -0
- package/components/tryghost-mw-cache-control-5.65.1.tgz +0 -0
- package/components/tryghost-mw-session-from-token-5.65.1.tgz +0 -0
- package/components/tryghost-mw-update-user-last-seen-5.65.1.tgz +0 -0
- package/components/tryghost-mw-vhost-5.65.1.tgz +0 -0
- package/components/tryghost-nql-filter-expansions-5.65.1.tgz +0 -0
- package/components/tryghost-oembed-service-5.65.1.tgz +0 -0
- package/components/tryghost-post-events-5.65.1.tgz +0 -0
- package/components/tryghost-recommendations-5.65.1.tgz +0 -0
- package/components/tryghost-referrers-5.65.1.tgz +0 -0
- package/components/tryghost-security-5.65.1.tgz +0 -0
- package/components/tryghost-session-service-5.65.1.tgz +0 -0
- package/components/tryghost-slack-notifications-5.65.1.tgz +0 -0
- package/components/tryghost-staff-service-5.65.1.tgz +0 -0
- package/components/tryghost-stats-service-5.65.1.tgz +0 -0
- package/components/tryghost-tiers-5.65.1.tgz +0 -0
- package/components/tryghost-update-check-service-5.65.1.tgz +0 -0
- package/components/tryghost-version-notifications-data-service-5.65.1.tgz +0 -0
- package/components/tryghost-webmentions-5.65.1.tgz +0 -0
- package/core/built/admin/assets/admin-x-settings/index-4a560e9e.mjs +0 -19693
- package/core/built/admin/assets/ghost-761b67711827277b7095ebc7acc5c49f.css +0 -1
- package/core/built/admin/assets/ghost-dark-d3f636c30e80bdd7f21d3fb4770073c9.css +0 -1
- /package/core/built/admin/assets/{chunk.518.396deed1a0c759d1f403.js.LICENSE.txt → chunk.555.ba02d5a0095b4c4a7700.js.LICENSE.txt} +0 -0
|
@@ -3546,14 +3546,14 @@ n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Obj
|
|
|
3546
3546
|
for(var r=new Array(t),n=0;n<t;n++)r[n]=e[n]
|
|
3547
3547
|
return r}})),e("ember/index",["exports","require","@ember/-internals/environment","node-module","@ember/-internals/utils","@ember/-internals/container","@ember/instrumentation","@ember/-internals/meta","@ember/-internals/metal","@ember/canary-features","@ember/debug","backburner","@ember/-internals/console","@ember/controller","@ember/controller/lib/controller_mixin","@ember/string","@ember/service","@ember/object","@ember/object/compat","@ember/object/computed","@ember/-internals/runtime","@ember/-internals/glimmer","ember/version","@ember/-internals/views","@ember/-internals/routing","@ember/-internals/extension-support","@ember/error","@ember/runloop","@ember/-internals/error-handling","@ember/-internals/owner","@ember/application","@ember/application/globals-resolver","@ember/application/instance","@ember/engine","@ember/engine/instance","@ember/polyfills","@ember/deprecated-features","@ember/component/template-only","@glimmer/runtime","@ember/destroyable"],(function(e,t,r,n,i,o,a,s,l,u,c,d,h,p,f,m,g,b,v,y,_,k,E,w,x,O,C,T,S,P,M,A,R,j,D,I,N,L,F,z){"use strict"
|
|
3548
3548
|
Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
|
|
3549
|
-
var B="object"==typeof r.context.imports.Ember&&r.context.imports.Ember||{}
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
var
|
|
3553
|
-
if(
|
|
3554
|
-
|
|
3555
|
-
var
|
|
3556
|
-
e.default=
|
|
3549
|
+
var B=c,H="object"==typeof r.context.imports.Ember&&r.context.imports.Ember||{}
|
|
3550
|
+
H.isNamespace=!0,H.toString=function(){return"Ember"},Object.defineProperty(H,"ENV",{get:r.getENV,enumerable:!1}),Object.defineProperty(H,"lookup",{get:r.getLookup,set:r.setLookup,enumerable:!1}),N.EMBER_EXTEND_PROTOTYPES&&Object.defineProperty(H,"EXTEND_PROTOTYPES",{enumerable:!1,get:()=>r.ENV.EXTEND_PROTOTYPES}),H.getOwner=P.getOwner,H.setOwner=P.setOwner,H.Application=M.default,H.ApplicationInstance=R.default,Object.defineProperty(H,"Resolver",{get:()=>A.default}),Object.defineProperty(H,"DefaultResolver",{get:()=>H.Resolver}),H.Engine=j.default,H.EngineInstance=D.default,H.assign=I.assign,H.merge=I.merge,H.generateGuid=i.generateGuid,H.GUID_KEY=i.GUID_KEY,H.guidFor=i.guidFor,H.inspect=i.inspect,H.makeArray=i.makeArray,H.canInvoke=i.canInvoke,H.tryInvoke=i.tryInvoke,H.wrap=i.wrap,H.uuid=i.uuid,H.Container=o.Container,H.Registry=o.Registry,H.assert=B.assert,H.warn=B.warn,H.debug=B.debug,H.deprecate=B.deprecate
|
|
3551
|
+
H.deprecateFunc=B.deprecateFunc,H.runInDebug=B.runInDebug,H.Error=C.default,H.Debug={registerDeprecationHandler:B.registerDeprecationHandler,registerWarnHandler:B.registerWarnHandler,isComputed:l.isComputed},H.instrument=a.instrument,H.subscribe=a.subscribe,H.Instrumentation={instrument:a.instrument,subscribe:a.subscribe,unsubscribe:a.unsubscribe,reset:a.reset},H.run=T._globalsRun,H.run.backburner=T.backburner,H.run.begin=T.begin,H.run.bind=T.bind,H.run.cancel=T.cancel,H.run.debounce=T.debounce,H.run.end=T.end,H.run.hasScheduledTimers=T.hasScheduledTimers,H.run.join=T.join,H.run.later=T.later,H.run.next=T.next,H.run.once=T.once,H.run.schedule=T.schedule,H.run.scheduleOnce=T.scheduleOnce,H.run.throttle=T.throttle,H.run.cancelTimers=T.cancelTimers,Object.defineProperty(H.run,"currentRunLoop",{get:T.getCurrentRunLoop,enumerable:!1})
|
|
3552
|
+
var U=l._globalsComputed
|
|
3553
|
+
if(H.computed=U,H._descriptor=l.nativeDescDecorator,H._tracked=l.tracked,U.alias=l.alias,H.cacheFor=l.getCachedValueFor,H.ComputedProperty=l.ComputedProperty,H._setClassicDecorator=l.setClassicDecorator,H.meta=s.meta,H.get=l.get,H.getWithDefault=l.getWithDefault,H._getPath=l._getPath,H.set=l.set,H.trySet=l.trySet,H.FEATURES=(0,I.assign)({isEnabled:u.isEnabled},u.FEATURES),H._Cache=i.Cache,H.on=l.on,H.addListener=l.addListener,H.removeListener=l.removeListener,H.sendEvent=l.sendEvent,H.hasListeners=l.hasListeners,H.isNone=l.isNone,H.isEmpty=l.isEmpty,H.isBlank=l.isBlank,H.isPresent=l.isPresent,H.notifyPropertyChange=l.notifyPropertyChange,H.beginPropertyChanges=l.beginPropertyChanges,H.endPropertyChanges=l.endPropertyChanges,H.changeProperties=l.changeProperties,H.platform={defineProperty:!0,hasPropertyAccessors:!0},H.defineProperty=l.defineProperty,H.destroy=z.destroy,H.libraries=l.libraries,H.getProperties=l.getProperties,H.setProperties=l.setProperties,H.expandProperties=l.expandProperties,H.addObserver=l.addObserver,H.removeObserver=l.removeObserver,H.aliasMethod=l.aliasMethod,H.observer=l.observer,H.mixin=l.mixin,H.Mixin=l.Mixin,H._createCache=l.createCache,H._cacheGetValue=l.getValue,H._cacheIsConst=l.isConst,H._registerDestructor=z.registerDestructor,H._unregisterDestructor=z.unregisterDestructor,H._associateDestroyableChild=z.associateDestroyableChild,H._assertDestroyablesDestroyed=z.assertDestroyablesDestroyed,H._enableDestroyableTracking=z.enableDestroyableTracking,H._isDestroying=z.isDestroying,H._isDestroyed=z.isDestroyed,Object.defineProperty(H,"onerror",{get:S.getOnerror,set:S.setOnerror,enumerable:!1}),Object.defineProperty(H,"testing",{get:B.isTesting,set:B.setTesting,enumerable:!1}),H._Backburner=d.default,N.LOGGER&&(H.Logger=h.default),H.A=_.A,H.String={loc:m.loc,w:m.w,dasherize:m.dasherize,decamelize:m.decamelize,camelize:m.camelize,classify:m.classify,underscore:m.underscore,capitalize:m.capitalize},H.Object=_.Object,H._RegistryProxyMixin=_.RegistryProxyMixin,H._ContainerProxyMixin=_.ContainerProxyMixin,H.compare=_.compare,H.copy=_.copy,H.isEqual=_.isEqual,H.inject=function(){},H.inject.service=g.inject,H.inject.controller=p.inject,H.Array=_.Array,H.Comparable=_.Comparable,H.Enumerable=_.Enumerable,H.ArrayProxy=_.ArrayProxy,H.ObjectProxy=_.ObjectProxy,H.ActionHandler=_.ActionHandler,H.CoreObject=_.CoreObject,H.NativeArray=_.NativeArray,H.Copyable=_.Copyable,H.MutableEnumerable=_.MutableEnumerable,H.MutableArray=_.MutableArray,H.TargetActionSupport=_.TargetActionSupport,H.Evented=_.Evented,H.PromiseProxyMixin=_.PromiseProxyMixin,H.Observable=_.Observable,H.typeOf=_.typeOf,H.isArray=_.isArray,H.Object=_.Object,H.onLoad=M.onLoad,H.runLoadHooks=M.runLoadHooks,H.Controller=p.default,H.ControllerMixin=f.default,H.Service=g.default,H._ProxyMixin=_._ProxyMixin,H.RSVP=_.RSVP,H.Namespace=_.Namespace,H._action=b.action,H._dependentKeyCompat=v.dependentKeyCompat,U.empty=y.empty,U.notEmpty=y.notEmpty,U.none=y.none,U.not=y.not,U.bool=y.bool,U.match=y.match,U.equal=y.equal,U.gt=y.gt,U.gte=y.gte,U.lt=y.lt,U.lte=y.lte,U.oneWay=y.oneWay,U.reads=y.oneWay,U.readOnly=y.readOnly,U.deprecatingAlias=y.deprecatingAlias,U.and=y.and,U.or=y.or,U.sum=y.sum,U.min=y.min,U.max=y.max,U.map=y.map,U.sort=y.sort,U.setDiff=y.setDiff,U.mapBy=y.mapBy,U.filter=y.filter,U.filterBy=y.filterBy,U.uniq=y.uniq,U.uniqBy=y.uniqBy,U.union=y.union,U.intersect=y.intersect,U.collect=y.collect,Object.defineProperty(H,"STRINGS",{configurable:!1,get:m._getStrings,set:m._setStrings}),Object.defineProperty(H,"BOOTED",{configurable:!1,enumerable:!1,get:l.isNamespaceSearchDisabled,set:l.setNamespaceSearchDisabled}),H.Component=k.Component,k.Helper.helper=k.helper,H.Helper=k.Helper,H.Checkbox=k.Checkbox,H.TextField=k.TextField,H.TextArea=k.TextArea,H.LinkComponent=k.LinkComponent,H.TextSupport=w.TextSupport,H._setComponentManager=k.setComponentManager,H._componentManagerCapabilities=k.capabilities,H._setModifierManager=F.setModifierManager,H._modifierManagerCapabilities=k.modifierCapabilities,H._getComponentTemplate=F.getComponentTemplate,H._setComponentTemplate=F.setComponentTemplate,H._templateOnlyComponent=L.default,H._helperManagerCapabilities=k.helperCapabilities,H._setHelperManager=F.setHelperManager,H._invokeHelper=k.invokeHelper,H._captureRenderTree=c.captureRenderTree,H.Handlebars={template:k.template,Utils:{escapeExpression:k.escapeExpression}},H.HTMLBars={template:k.template},r.ENV.EXTEND_PROTOTYPES.String&&(String.prototype.htmlSafe=function(){return(0,k.htmlSafe)(this)}),H.String.htmlSafe=k.htmlSafe,H.String.isHTMLSafe=k.isHTMLSafe,Object.defineProperty(H,"TEMPLATES",{get:k.getTemplates,set:k.setTemplates,configurable:!1,enumerable:!1}),H.VERSION=E.default,N.JQUERY_INTEGRATION&&!w.jQueryDisabled&&Object.defineProperty(H,"$",{get:()=>w.jQuery,configurable:!0,enumerable:!0}),H.ViewUtils={isSimpleClick:w.isSimpleClick,getElementView:w.getElementView,getViewElement:w.getViewElement,getViewBounds:w.getViewBounds,getViewClientRects:w.getViewClientRects,getViewBoundingClientRect:w.getViewBoundingClientRect,getRootViews:w.getRootViews,getChildViews:w.getChildViews,isSerializationFirstNode:k.isSerializationFirstNode},H.ComponentLookup=w.ComponentLookup,H.EventDispatcher=w.EventDispatcher,H.Location=x.Location,H.AutoLocation=x.AutoLocation,H.HashLocation=x.HashLocation,H.HistoryLocation=x.HistoryLocation,H.NoneLocation=x.NoneLocation,H.controllerFor=x.controllerFor,H.generateControllerFactory=x.generateControllerFactory,H.generateController=x.generateController,H.RouterDSL=x.RouterDSL,H.Router=x.Router,H.Route=x.Route,(0,M.runLoadHooks)("Ember.Application",M.default),H.DataAdapter=O.DataAdapter,H.ContainerDebugAdapter=O.ContainerDebugAdapter,(0,t.has)("ember-template-compiler")&&(0,t.default)("ember-template-compiler"),(0,t.has)("ember-testing")){var V=(0,t.default)("ember-testing")
|
|
3554
|
+
H.Test=V.Test,H.Test.Adapter=V.Adapter,H.Test.QUnitAdapter=V.QUnitAdapter,H.setupForTesting=V.setupForTesting}(0,M.runLoadHooks)("Ember")
|
|
3555
|
+
var q=H
|
|
3556
|
+
e.default=q,n.IS_NODE?n.module.exports=H:r.context.exports.Ember=r.context.exports.Em=H})),e("ember/version",["exports"],(function(e){"use strict"
|
|
3557
3557
|
Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
|
|
3558
3558
|
e.default="3.24.0"})),e("node-module/index",["exports"],(function(e){"use strict"
|
|
3559
3559
|
Object.defineProperty(e,"__esModule",{value:!0}),e.require=e.module=e.IS_NODE=void 0
|
|
@@ -8878,20 +8878,22 @@ var t=Ember.HTMLBars.template({id:"g/nau/et",block:'{"symbols":["virtualComponen
|
|
|
8878
8878
|
e.default=t})),define("@sentry/ember/index",["exports","@sentry/browser","@sentry/utils"],(function(e,t,r){"use strict"
|
|
8879
8879
|
Object.defineProperty(e,"__esModule",{value:!0})
|
|
8880
8880
|
var n={InitSentryForEmber:!0,getActiveTransaction:!0,instrumentRoutePerformance:!0,init:!0}
|
|
8881
|
-
|
|
8881
|
+
e.InitSentryForEmber=o,e.instrumentRoutePerformance=e.init=e.getActiveTransaction=void 0
|
|
8882
|
+
var i=t
|
|
8883
|
+
function o(e){const n={disablePerformance:!0,sentry:{}}
|
|
8882
8884
|
n.sentry||(n.sentry={...e}),Object.assign(n.sentry,e||{})
|
|
8883
|
-
const
|
|
8884
|
-
|
|
8885
|
-
const
|
|
8885
|
+
const o=Object.assign({},n.sentry)
|
|
8886
|
+
o._metadata=o._metadata||{},o._metadata.sdk={name:"sentry.javascript.ember",packages:[{name:"npm:@sentry/ember",version:t.SDK_VERSION}],version:t.SDK_VERSION}
|
|
8887
|
+
const a=function(){const e=r.GLOBAL_OBJ
|
|
8886
8888
|
return e.__sentryEmberConfig=e.__sentryEmberConfig??{},e.__sentryEmberConfig}()
|
|
8887
|
-
Object.assign(o,i
|
|
8888
|
-
const
|
|
8889
|
-
e.getActiveTransaction=
|
|
8890
|
-
e.instrumentRoutePerformance=e=>{const t=async(e,t,n,i)=>{const
|
|
8891
|
-
return l?(l.startChild({op:e,description:t,origin:"auto.ui.ember",startTimestamp:
|
|
8889
|
+
Object.assign(a,o),i.init(o)}Object.keys(t).forEach((function(r){"default"!==r&&"__esModule"!==r&&(Object.prototype.hasOwnProperty.call(n,r)||r in e&&e[r]===t[r]||Object.defineProperty(e,r,{enumerable:!0,get:function(){return t[r]}}))}))
|
|
8890
|
+
const a=()=>i.getCurrentHub().getScope().getTransaction()
|
|
8891
|
+
e.getActiveTransaction=a
|
|
8892
|
+
e.instrumentRoutePerformance=e=>{const t=async(e,t,n,i)=>{const o=(0,r.timestampInSeconds)(),s=await n(...i),l=a()
|
|
8893
|
+
return l?(l.startChild({op:e,description:t,origin:"auto.ui.ember",startTimestamp:o}).finish(),s):s},n=e.name
|
|
8892
8894
|
return{[n]:class extends e{beforeModel(...e){return t("ui.ember.route.before_model",this.fullRouteName,super.beforeModel.bind(this),e)}async model(...e){return t("ui.ember.route.model",this.fullRouteName,super.model.bind(this),e)}afterModel(...e){return t("ui.ember.route.after_model",this.fullRouteName,super.afterModel.bind(this),e)}setupController(...e){return t("ui.ember.route.setup_controller",this.fullRouteName,super.setupController.bind(this),e)}}}[n]}
|
|
8893
|
-
const
|
|
8894
|
-
e.init=
|
|
8895
|
+
const s=o
|
|
8896
|
+
e.init=s})),define("@sentry/ember/instance-initializers/sentry-performance",["exports","@sentry/browser","@sentry/utils","@sentry/ember"],(function(e,t,r,n){"use strict"
|
|
8895
8897
|
function i(){const e=r.GLOBAL_OBJ
|
|
8896
8898
|
e.__sentryEmberConfig=e.__sentryEmberConfig??{}
|
|
8897
8899
|
const t={disablePerformance:!0,sentry:{}}
|
|
@@ -13616,4 +13618,4 @@ e.default=class{constructor(e){if(this._data=new t.default,e)for(let t=0;t<e.len
|
|
|
13616
13618
|
return this}get(e){let t=this._data[e]
|
|
13617
13619
|
return t===r.UNDEFINED_KEY?void 0:t}set(e,t){return this._data[e]=t,this}delete(e){return this._data[e]=r.UNDEFINED_KEY,!0}}}))
|
|
13618
13620
|
|
|
13619
|
-
//# sourceMappingURL=vendor-
|
|
13621
|
+
//# sourceMappingURL=vendor-5aa07b661eeb443bf7dd2c1de3b3f387.map
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<title>Ghost Admin</title>
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22cdnUrl%22%3A%22%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.
|
|
11
|
+
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22cdnUrl%22%3A%22%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.66%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22ember-websockets%22%3A%7B%22socketIO%22%3Atrue%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%7D" />
|
|
12
12
|
|
|
13
13
|
<meta name="HandheldFriendly" content="True" />
|
|
14
14
|
<meta name="MobileOptimized" content="320" />
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
</style>
|
|
38
38
|
|
|
39
39
|
<link integrity="" rel="stylesheet" href="assets/vendor-3e6947aa681f0fb82b193090e520dc73.css">
|
|
40
|
-
<link integrity="" rel="stylesheet" href="assets/ghost-
|
|
40
|
+
<link integrity="" rel="stylesheet" href="assets/ghost-f1a535bfec933b08a7a45f607cc245b1.css" title="light">
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
</head>
|
|
@@ -56,9 +56,9 @@
|
|
|
56
56
|
|
|
57
57
|
<div id="ember-basic-dropdown-wormhole"></div>
|
|
58
58
|
|
|
59
|
-
<script src="assets/vendor-
|
|
60
|
-
<script src="assets/chunk.
|
|
61
|
-
<script src="assets/chunk.143.
|
|
62
|
-
<script src="assets/ghost-
|
|
59
|
+
<script src="assets/vendor-5aa07b661eeb443bf7dd2c1de3b3f387.js"></script>
|
|
60
|
+
<script src="assets/chunk.555.ba02d5a0095b4c4a7700.js"></script>
|
|
61
|
+
<script src="assets/chunk.143.f2758c8aac6998f30b19.js"></script>
|
|
62
|
+
<script src="assets/ghost-56045473f2cfd232419a9d27bf8225a5.js"></script>
|
|
63
63
|
</body>
|
|
64
64
|
</html>
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/* Recommendations helper
|
|
2
|
+
* Usage: `{{recommendations}}`
|
|
3
|
+
*
|
|
4
|
+
* Renders the template defined in `tpl/recommendations.hbs`
|
|
5
|
+
* Can be overridden by themes by uploading a partial under `partials/recommendations.hbs`
|
|
6
|
+
*
|
|
7
|
+
* Available options: limit, order, filter, page
|
|
8
|
+
*/
|
|
9
|
+
const {config, api, prepareContextResource, settingsCache} = require('../services/proxy');
|
|
10
|
+
const {templates, hbs} = require('../services/handlebars');
|
|
11
|
+
|
|
12
|
+
const logging = require('@tryghost/logging');
|
|
13
|
+
const errors = require('@tryghost/errors');
|
|
14
|
+
|
|
15
|
+
const createFrame = hbs.handlebars.createFrame;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Call the Recommendation Content API's browse method
|
|
19
|
+
* @param {Object} apiOptions
|
|
20
|
+
* @returns {Promise<Object>}
|
|
21
|
+
*/
|
|
22
|
+
async function fetchRecommendations(apiOptions) {
|
|
23
|
+
let timer;
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const controller = api.recommendationsPublic;
|
|
27
|
+
let response;
|
|
28
|
+
|
|
29
|
+
const logLevel = config.get('optimization:getHelper:timeout:level') || 'error';
|
|
30
|
+
const threshold = config.get('optimization:getHelper:timeout:threshold') || 5000;
|
|
31
|
+
const apiResponse = controller.browse(apiOptions);
|
|
32
|
+
|
|
33
|
+
const timeout = new Promise((resolve) => {
|
|
34
|
+
timer = setTimeout(() => {
|
|
35
|
+
logging[logLevel](new errors.HelperWarning({
|
|
36
|
+
message: `{{#recommendations}} took longer than ${threshold}ms and was aborted`,
|
|
37
|
+
code: 'ABORTED_RECOMMENDATIONS_HELPER',
|
|
38
|
+
errorDetails: {
|
|
39
|
+
api: 'recommendationsPublic.browse',
|
|
40
|
+
apiOptions
|
|
41
|
+
}
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
resolve({recommendations: []});
|
|
45
|
+
}, threshold);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
response = await Promise.race([apiResponse, timeout]);
|
|
49
|
+
clearTimeout(timer);
|
|
50
|
+
|
|
51
|
+
return response;
|
|
52
|
+
} catch (err) {
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Parse Options
|
|
60
|
+
*
|
|
61
|
+
* @param {Object} options
|
|
62
|
+
* @returns {*}
|
|
63
|
+
*/
|
|
64
|
+
function parseOptions(options) {
|
|
65
|
+
let limit = options.limit ?? 5;
|
|
66
|
+
let order = options.order ?? 'createdAt desc';
|
|
67
|
+
let filter = options.filter ?? '';
|
|
68
|
+
let page = options.page ?? 1;
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
limit,
|
|
72
|
+
order,
|
|
73
|
+
filter,
|
|
74
|
+
page
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
*
|
|
80
|
+
* @param {object} options
|
|
81
|
+
* @returns {Promise<any>}
|
|
82
|
+
*/
|
|
83
|
+
module.exports = async function recommendations(options) {
|
|
84
|
+
const recommendationsEnabled = settingsCache.get('recommendations_enabled');
|
|
85
|
+
|
|
86
|
+
if (!recommendationsEnabled) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
options = options || {};
|
|
91
|
+
options.hash = options.hash || {};
|
|
92
|
+
options.data = options.data || {};
|
|
93
|
+
|
|
94
|
+
const data = createFrame(options.data);
|
|
95
|
+
let apiOptions = options.hash;
|
|
96
|
+
apiOptions = parseOptions(apiOptions);
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const response = await fetchRecommendations(apiOptions);
|
|
100
|
+
|
|
101
|
+
if (response.recommendations && response.recommendations.length) {
|
|
102
|
+
response.recommendations.forEach(prepareContextResource);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (response.meta && response.meta.pagination) {
|
|
106
|
+
response.pagination = response.meta.pagination;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return templates.execute('recommendations', response, {data});
|
|
110
|
+
} catch (error) {
|
|
111
|
+
logging.error(error);
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
module.exports.async = true;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{{#if recommendations}}
|
|
2
|
+
<ul class="recommendations">
|
|
3
|
+
{{#each recommendations as |rec|}}
|
|
4
|
+
<li class="recommendation">
|
|
5
|
+
<a href="{{rec.url}}">
|
|
6
|
+
<img class="recommendation-favicon" src="{{rec.favicon}}" alt="{{rec.title}}">
|
|
7
|
+
<div class="recommendation-content">
|
|
8
|
+
<h5 class="recommendation-title">{{rec.title}}</h5>
|
|
9
|
+
<p class="recommendation-reason">{{rec.reason}}</p>
|
|
10
|
+
</div>
|
|
11
|
+
</a>
|
|
12
|
+
</li>
|
|
13
|
+
{{/each}}
|
|
14
|
+
</ul>
|
|
15
|
+
{{/if}}
|
|
@@ -274,21 +274,21 @@ SchedulingDefault.prototype._pingUrl = function (object) {
|
|
|
274
274
|
const maxTries = 30;
|
|
275
275
|
|
|
276
276
|
const options = {
|
|
277
|
-
timeout:
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
277
|
+
timeout: {
|
|
278
|
+
request: requestTimeout
|
|
279
|
+
},
|
|
280
|
+
method: httpMethod,
|
|
281
|
+
retry: {
|
|
282
|
+
limit: 0
|
|
282
283
|
}
|
|
283
284
|
};
|
|
284
285
|
|
|
285
286
|
// CASE: If we detect to publish a post in the past (case blog is down), we add a force flag
|
|
286
287
|
if (moment(time).isBefore(moment())) {
|
|
287
288
|
if (httpMethod === 'GET') {
|
|
288
|
-
|
|
289
|
-
options.query = 'force=true';
|
|
289
|
+
options.searchParams = {force: true};
|
|
290
290
|
} else {
|
|
291
|
-
options.
|
|
291
|
+
options.json = {force: true};
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
|
|
@@ -36,6 +36,7 @@ const author = (attrs, frame) => {
|
|
|
36
36
|
delete attrs.paid_subscription_started_notification;
|
|
37
37
|
delete attrs.paid_subscription_canceled_notification;
|
|
38
38
|
delete attrs.mention_notifications;
|
|
39
|
+
delete attrs.recommendation_notifications;
|
|
39
40
|
delete attrs.milestone_notifications;
|
|
40
41
|
delete attrs.donation_notifications;
|
|
41
42
|
|
|
@@ -163,6 +163,7 @@ module.exports = {
|
|
|
163
163
|
paid_subscription_started_notification: {type: 'boolean', nullable: false, defaultTo: true},
|
|
164
164
|
paid_subscription_canceled_notification: {type: 'boolean', nullable: false, defaultTo: false},
|
|
165
165
|
mention_notifications: {type: 'boolean', nullable: false, defaultTo: true},
|
|
166
|
+
recommendation_notifications: {type: 'boolean', nullable: false, defaultTo: true},
|
|
166
167
|
milestone_notifications: {type: 'boolean', nullable: false, defaultTo: true},
|
|
167
168
|
donation_notifications: {type: 'boolean', nullable: false, defaultTo: true},
|
|
168
169
|
created_at: {type: 'dateTime', nullable: false},
|
|
@@ -33,7 +33,7 @@ class Gravatar {
|
|
|
33
33
|
const testUrl = this.url(userData.email, {default: 404, rating: 'x'});
|
|
34
34
|
const imageUrl = this.url(userData.email, {default: 'mp', rating: 'x'});
|
|
35
35
|
|
|
36
|
-
return Promise.resolve(this.request(testUrl, {timeout: timeout || 2 * 1000}))
|
|
36
|
+
return Promise.resolve(this.request(testUrl, {timeout: {request: timeout || 2 * 1000}}))
|
|
37
37
|
.then(function () {
|
|
38
38
|
return {
|
|
39
39
|
image: imageUrl
|
|
@@ -30,9 +30,13 @@ class ImageSize {
|
|
|
30
30
|
headers: {
|
|
31
31
|
'User-Agent': 'Mozilla/5.0 Safari/537.36'
|
|
32
32
|
},
|
|
33
|
-
timeout:
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
timeout: {
|
|
34
|
+
request: this.config.get('times:getImageSizeTimeoutInMS') || 10000
|
|
35
|
+
},
|
|
36
|
+
retry: {
|
|
37
|
+
limit: 0 // for `got`, used with image-size
|
|
38
|
+
},
|
|
39
|
+
responseType: 'buffer'
|
|
36
40
|
};
|
|
37
41
|
|
|
38
42
|
this.NEEDLE_OPTIONS = {
|
|
@@ -18,6 +18,11 @@ function isPrivateIp(addr) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
async function errorIfHostnameResolvesToPrivateIp(options) {
|
|
21
|
+
// Allow all requests if we are in development mode
|
|
22
|
+
if (config.get('env') === 'development') {
|
|
23
|
+
return Promise.resolve();
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
// allow requests through to local Ghost instance
|
|
22
27
|
const siteUrl = new URL(config.get('url'));
|
|
23
28
|
const requestUrl = new URL(options.url.href);
|
|
@@ -37,6 +42,10 @@ async function errorIfHostnameResolvesToPrivateIp(options) {
|
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
async function errorIfInvalidUrl(options) {
|
|
45
|
+
if (config.get('env') === 'development') {
|
|
46
|
+
return Promise.resolve();
|
|
47
|
+
}
|
|
48
|
+
|
|
40
49
|
if (!options.url.hostname || !validator.isURL(options.url.hostname)) {
|
|
41
50
|
throw new errors.InternalServerError({
|
|
42
51
|
message: 'URL invalid.',
|
|
@@ -1367,6 +1367,24 @@ Post = ghostBookshelf.Model.extend({
|
|
|
1367
1367
|
return editPost();
|
|
1368
1368
|
},
|
|
1369
1369
|
|
|
1370
|
+
bulkEdit: async function bulkEdit(ids, tableName, options) {
|
|
1371
|
+
if (tableName === this.prototype.tableName) {
|
|
1372
|
+
const result = await ghostBookshelf.Model.bulkEdit.call(this, ids, tableName, options);
|
|
1373
|
+
|
|
1374
|
+
if (labs.isSet('collectionsCard')) {
|
|
1375
|
+
// reset all page HTML so collection cards can be re-rendered with updated posts
|
|
1376
|
+
// NOTE: we can't check for only published edits here as we don't have access to previous values
|
|
1377
|
+
// to see if a previously published post has been unpublished, so we just reset all pages
|
|
1378
|
+
const pageResetQuery = ghostBookshelf.knex.raw('UPDATE posts set html = NULL WHERE type = "page" AND lexical IS NOT NULL');
|
|
1379
|
+
await (options.transacting ? pageResetQuery.transacting(options.transacting) : pageResetQuery);
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
return result;
|
|
1383
|
+
} else {
|
|
1384
|
+
return ghostBookshelf.Model.bulkEdit.call(this, ids, tableName, options);
|
|
1385
|
+
}
|
|
1386
|
+
},
|
|
1387
|
+
|
|
1370
1388
|
/**
|
|
1371
1389
|
* ### Add
|
|
1372
1390
|
* @extends ghostBookshelf.Model.add to handle returning the full object
|
|
@@ -1413,6 +1431,34 @@ Post = ghostBookshelf.Model.extend({
|
|
|
1413
1431
|
return destroyPost();
|
|
1414
1432
|
},
|
|
1415
1433
|
|
|
1434
|
+
bulkDestroy: async function bulkDestroy(ids, tableName, options) {
|
|
1435
|
+
if (tableName === this.prototype.tableName) {
|
|
1436
|
+
if (labs.isSet('collectionsCard')) {
|
|
1437
|
+
// get count of published posts to be destroyed before they no longer exist to count
|
|
1438
|
+
const deletedPublishedCount = await this.query((qb) => {
|
|
1439
|
+
qb.where('type', 'post')
|
|
1440
|
+
.where('status', 'published')
|
|
1441
|
+
.whereIn('id', ids);
|
|
1442
|
+
}).count({transacting: options.transacting});
|
|
1443
|
+
|
|
1444
|
+
const result = await ghostBookshelf.Model.bulkDestroy.call(this, ids, tableName, options);
|
|
1445
|
+
|
|
1446
|
+
// if we've deleted any published posts, we need to reset the html for all pages so dynamic collection
|
|
1447
|
+
// card content can be re-rendered
|
|
1448
|
+
if (deletedPublishedCount > 0) {
|
|
1449
|
+
const pageResetQuery = ghostBookshelf.knex.raw('UPDATE posts set html = NULL WHERE type = "page" AND lexical IS NOT NULL');
|
|
1450
|
+
await (options.transacting ? pageResetQuery.transacting(options.transacting) : pageResetQuery);
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
return result;
|
|
1454
|
+
} else {
|
|
1455
|
+
return ghostBookshelf.Model.bulkDestroy.call(this, ids, tableName, options);
|
|
1456
|
+
}
|
|
1457
|
+
} else {
|
|
1458
|
+
return ghostBookshelf.Model.bulkDestroy.call(this, ids, tableName, options);
|
|
1459
|
+
}
|
|
1460
|
+
},
|
|
1461
|
+
|
|
1416
1462
|
// NOTE: the `authors` extension is the parent of the post model. It also has a permissible function.
|
|
1417
1463
|
permissible: async function permissible(postModel, action, context, unsafeAttrs, loadedPermissions, hasUserPermission, hasApiKeyPermission) {
|
|
1418
1464
|
let isContributor;
|
|
@@ -69,6 +69,7 @@ User = ghostBookshelf.Model.extend({
|
|
|
69
69
|
paid_subscription_started_notification: true,
|
|
70
70
|
paid_subscription_canceled_notification: false,
|
|
71
71
|
mention_notifications: true,
|
|
72
|
+
recommendation_notifications: true,
|
|
72
73
|
milestone_notifications: true,
|
|
73
74
|
donation_notifications: true
|
|
74
75
|
};
|
|
@@ -512,6 +513,8 @@ User = ghostBookshelf.Model.extend({
|
|
|
512
513
|
filter += '+milestone_notifications:true';
|
|
513
514
|
} else if (type === 'donation') {
|
|
514
515
|
filter += '+donation_notifications:true';
|
|
516
|
+
} else if (type === 'recommendation-received') {
|
|
517
|
+
filter += '+recommendation_notifications:true';
|
|
515
518
|
}
|
|
516
519
|
const updatedOptions = _.merge({}, options, {filter, withRelated: ['roles']});
|
|
517
520
|
return this.findAll(updatedOptions).then((users) => {
|
|
@@ -4,8 +4,13 @@ class PostsRepository {
|
|
|
4
4
|
this.moment = moment;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* @param {Object} options
|
|
9
|
+
* @returns Promise<string[]>
|
|
10
|
+
*/
|
|
11
|
+
async getAllIds({transaction} = {}) {
|
|
12
|
+
const query = this.models.Post.query().select('id').where('type', 'post');
|
|
13
|
+
const rows = transaction ? await query.transacting(transaction) : await query;
|
|
9
14
|
|
|
10
15
|
return rows.map(row => row.id);
|
|
11
16
|
}
|
|
@@ -57,7 +57,8 @@ module.exports = class BookshelfMentionRepository {
|
|
|
57
57
|
sourceExcerpt: model.get('source_excerpt'),
|
|
58
58
|
sourceFavicon: model.get('source_favicon'),
|
|
59
59
|
sourceFeaturedImage: model.get('source_featured_image'),
|
|
60
|
-
verified: model.get('verified')
|
|
60
|
+
verified: model.get('verified'),
|
|
61
|
+
deleted: model.get('deleted')
|
|
61
62
|
});
|
|
62
63
|
}
|
|
63
64
|
|
|
@@ -27,6 +27,8 @@ function getPostUrl(post) {
|
|
|
27
27
|
module.exports = {
|
|
28
28
|
/** @type {import('@tryghost/webmentions/lib/MentionsAPI')} */
|
|
29
29
|
api: null,
|
|
30
|
+
/** @type {import('./BookshelfMentionRepository')} */
|
|
31
|
+
repository: null,
|
|
30
32
|
controller: new MentionController(),
|
|
31
33
|
metadata: new WebmentionMetadata(),
|
|
32
34
|
/** @type {import('@tryghost/webmentions/lib/MentionSendingService')} */
|
|
@@ -41,6 +43,8 @@ module.exports = {
|
|
|
41
43
|
MentionModel: models.Mention,
|
|
42
44
|
DomainEvents
|
|
43
45
|
});
|
|
46
|
+
this.repository = repository;
|
|
47
|
+
|
|
44
48
|
const webmentionMetadata = this.metadata;
|
|
45
49
|
const discoveryService = new MentionDiscoveryService({externalRequest});
|
|
46
50
|
const resourceService = new ResourceService({
|