Last active
June 1, 2022 13:07
-
-
Save jbandura/78f79c72126b2d978bd100605bf7d2be to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface Capability { | |
isAllowed(args: Record<string, any>): boolean; | |
get disallowReason(): string; | |
get name(): string; | |
get accountId(): string; | |
} | |
class CapabilityService extends Service { | |
capabilities: Capability[]; | |
constructor() { | |
super(); | |
this._registerCapabilities(); | |
} | |
// the main method for checking the capability | |
hasCapability(capabilityName: string, args?: Record<string, any>) { | |
const capability = this.capabilities.findBy('name', capabilityName); | |
if (!capability) return false; | |
return capability.isAllowed(args); | |
} | |
// in case user does not have a capability this method can be additonally used to display a message | |
getDisallowReason(capabilityName: string) { | |
return this.capabilities.findBy('name', capabilityName).disallowReason; | |
} | |
// main place to register capabilities that need to be calculated on the frontend | |
private _registerCapabilities() { | |
const capabilitiesToRegister = [ | |
new CanStartTrialCapability(getOwner(this)) | |
]; | |
this.capabilities = [...this.capabilities, ...capabilitiesToRegister]; | |
} | |
// main method for fetching capabilities by name, called in one of top-level routes | |
async fetchCapabilities(capabilityNames: string[]) { | |
// fetching from backend goes here | |
const capabilitiesFromBackend = [ | |
{ | |
name: 'can_start_trial', | |
// this is ED's model method that would just alias to 'allowed' attribute returned from backend | |
isAllowed() { return true; }, | |
disallowReason: null | |
}, | |
]; | |
this.capabilities = [...this.capabilities, ...capabilitiesFromBackend]; | |
} | |
// main method for fetching single capability, useful for computationally heavy logic | |
async fetchCapability(capabilityName: string) { | |
// fetching from backend goes here | |
const capability = { name: 'can_see_trial_ended_banner', isAllowed: () => true, disallowReason: null }; | |
this.capabilities = [...this.capabilities, capability]; | |
} | |
} | |
// example of capability logic implemented on the frontend | |
class CanStartTrialCapability implements Capability { | |
@service declare session: Service['session']; | |
get accountId() { return this.session.currentAccount.id } | |
name: 'can_start_trial'; | |
constructor(owner: EmberOwner) { | |
setOwner(this, owner); | |
} | |
isAllowed(args: Record<string, any>) { | |
return this.session.currentAccount.isPremium; | |
} | |
get disallowReason(): string { | |
if(!this.isAllowed) return 'Not a premium account'; | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment