2020-03-02 08:06:54 +03:00
import Component from '@ember/component' ;
2022-02-01 12:34:03 +03:00
import classic from 'ember-classic-decorator' ;
2021-09-30 15:54:54 +03:00
import { htmlSafe } from '@ember/template' ;
2020-03-02 08:06:54 +03:00
import { inject as service } from '@ember/service' ;
2022-02-01 12:34:03 +03:00
@ classic
export default class GhBillingIframe extends Component {
2022-02-01 20:03:45 +03:00
@ service billing ;
@ service config ;
@ service ghostPaths ;
@ service ajax ;
@ service notifications ;
2022-02-01 12:34:03 +03:00
isOwner = null ;
fetchingSubscription = false ;
2021-10-22 13:29:55 +03:00
2020-05-22 05:44:37 +03:00
didInsertElement ( ) {
2022-02-01 12:34:03 +03:00
super . didInsertElement ( ... arguments ) ;
2021-07-15 17:27:29 +03:00
2020-05-22 05:44:37 +03:00
this . billing . getBillingIframe ( ) . src = this . billing . getIframeURL ( ) ;
2020-03-02 08:06:54 +03:00
window . addEventListener ( 'message' , ( event ) => {
2022-10-26 18:48:52 +03:00
// only process messages coming from the billing iframe
if ( event ? . data && this . billing . getIframeURL ( ) . includes ( event ? . origin ) ) {
2021-10-26 15:06:15 +03:00
if ( event . data ? . request === 'token' ) {
this . _handleTokenRequest ( ) ;
2020-05-22 05:44:37 +03:00
}
2021-10-26 15:06:15 +03:00
if ( event . data ? . request === 'forceUpgradeInfo' ) {
this . _handleForceUpgradeRequest ( ) ;
}
2021-10-22 13:29:55 +03:00
2021-10-26 15:06:15 +03:00
if ( event . data ? . subscription ) {
this . _handleSubscriptionUpdate ( event . data ) ;
2021-10-22 13:29:55 +03:00
}
2021-10-26 15:06:15 +03:00
}
} ) ;
2022-02-01 12:34:03 +03:00
}
2021-10-26 15:06:15 +03:00
_handleTokenRequest ( ) {
this . set ( 'fetchingSubscription' , false ) ;
let token ;
const ghostIdentityUrl = this . get ( 'ghostPaths.url' ) . api ( 'identities' ) ;
this . ajax . request ( ghostIdentityUrl ) . then ( ( response ) => {
token = response && response . identities && response . identities [ 0 ] && response . identities [ 0 ] . token ;
this . billing . getBillingIframe ( ) . contentWindow . postMessage ( {
request : 'token' ,
response : token
} , '*' ) ;
this . set ( 'isOwner' , true ) ;
} ) . catch ( ( error ) => {
if ( error . payload ? . errors && error . payload . errors [ 0 ] ? . type === 'NoPermissionError' ) {
// no permission means the current user requesting the token is not the owner of the site.
this . set ( 'isOwner' , false ) ;
// Avoid letting the BMA waiting for a message and send an empty token response instead
2021-10-22 13:29:55 +03:00
this . billing . getBillingIframe ( ) . contentWindow . postMessage ( {
2021-10-26 15:06:15 +03:00
request : 'token' ,
response : null
2021-10-22 13:29:55 +03:00
} , '*' ) ;
2021-10-26 15:06:15 +03:00
} else {
throw error ;
2021-10-22 13:29:55 +03:00
}
2021-10-26 15:06:15 +03:00
} ) ;
2021-10-22 13:29:55 +03:00
2021-10-26 15:06:15 +03:00
// NOTE: the handler is placed here to avoid additional logic to check if iframe has loaded
// receiving a 'token' request is an indication that page is ready
if ( ! this . fetchingSubscription && ! this . billing . get ( 'subscription' ) && token ) {
this . set ( 'fetchingSubscription' , true ) ;
this . billing . getBillingIframe ( ) . contentWindow . postMessage ( {
query : 'getSubscription' ,
response : 'subscription'
} , '*' ) ;
}
2022-02-01 12:34:03 +03:00
}
2021-09-30 15:54:54 +03:00
2021-10-26 15:06:15 +03:00
_handleForceUpgradeRequest ( ) {
// Send BMA requested information about forceUpgrade and owner name/email
let ownerUser = null ;
const owner = this . billing . ownerUser ;
if ( owner ) {
ownerUser = {
name : owner ? . name ,
email : owner ? . email
} ;
}
this . billing . getBillingIframe ( ) . contentWindow . postMessage ( {
request : 'forceUpgradeInfo' ,
response : {
2022-10-07 17:24:03 +03:00
forceUpgrade : this . config . hostSettings ? . forceUpgrade ,
2021-10-26 15:06:15 +03:00
isOwner : this . isOwner ,
ownerUser
2020-03-02 08:06:54 +03:00
}
2021-10-26 15:06:15 +03:00
} , '*' ) ;
2022-02-01 12:34:03 +03:00
}
2021-10-26 15:06:15 +03:00
_handleSubscriptionUpdate ( data ) {
this . billing . set ( 'subscription' , data . subscription ) ;
this . billing . set ( 'checkoutRoute' , data ? . checkoutRoute || '/plans' ) ;
2022-10-07 17:24:03 +03:00
if ( data . subscription . status === 'active' && this . config . hostSettings ? . forceUpgrade ) {
2021-10-26 15:43:09 +03:00
// config might not be updated after a subscription has been set to active.
// Until then assume the forceUpgrade is over and the subscription
// was activated successfully.
2022-10-07 17:24:03 +03:00
this . config . hostSettings . forceUpgrade = false ;
2021-10-26 15:43:09 +03:00
}
2021-10-26 15:06:15 +03:00
// Detect if the current subscription is in a grace state and render a notification
if ( data . subscription . status === 'past_due' || data . subscription . status === 'unpaid' ) {
// This notification needs to be shown to every user regardless their permissions to see billing
this . notifications . showAlert ( 'Billing error: This site is queued for suspension. The owner of this site must update payment information.' , { type : 'error' , key : 'billing.overdue' } ) ;
} else {
this . notifications . closeAlerts ( 'billing.overdue' ) ;
}
// Detect if the current member limits are exceeded and render a notification
if (
data ? . exceededLimits
&& data ? . exceededLimits . length
&& data ? . exceededLimits . indexOf ( 'members' ) >= 0
&& data ? . checkoutRoute
) {
// The action param will be picked up on a transition from the router and can
// then send the destination route as a message to the BMA, which then handles the redirect.
const checkoutAction = this . billing . get ( 'billingRouteRoot' ) + '?action=checkout' ;
this . notifications . showAlert ( htmlSafe ( ` Your audience has grown! To continue publishing, the site owner must confirm pricing for this number of members <a href=" ${ checkoutAction } ">here</a> ` ) , { type : 'warn' , key : 'billing.exceeded' } ) ;
} else {
this . notifications . closeAlerts ( 'billing.exceeded' ) ;
}
2020-03-02 08:06:54 +03:00
}
2022-02-01 12:34:03 +03:00
}