-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit adds the first version of the SSO Plugin, including: - A settings control for app owners to set the Auth0 API credentials (domain and client ID). - A plugin widget for negotiating with the Auth0 API, determining authentication status, offering the user the ability to login via popup, saving the resulting user object to local storage, and instructing the user to go to the RSS plugin. - Image resources required by BuildFire to upload plugins. It does not yet automatically forward the user to the RSS plugin automatically. Also, the plugin.json file may need further tweaking as we understand its intended contents. Affects #3
- Loading branch information
Showing
6 changed files
with
523 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<!-- The BuildFire JS library is required. --> | ||
<script src="../../../../scripts/buildfire.min.js"></script> | ||
<style type="text/css"> | ||
#bif-sso__wrapper { | ||
padding: 1em; | ||
} | ||
|
||
.form-control-group { | ||
margin: 0.5em 0; | ||
} | ||
.form-control-group label { | ||
font-weight: bold; | ||
display: inline-block; | ||
text-align: right; | ||
width: 7em; | ||
margin-right: 0.25em | ||
} | ||
.form-control-group.align-with-labels { | ||
padding-left: 7.25em; | ||
} | ||
|
||
form.disabled { | ||
opacity: 0.5; | ||
cursor: not-allowed; | ||
} | ||
|
||
.bif-sso__auth-api-settings__alert-message--success { | ||
color: #00b500; | ||
} | ||
.bif-sso__auth-api-settings__alert-message--error { | ||
color: #ec0000; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
|
||
<div id="bif-sso__wrapper"> | ||
<form id="bif-sso__auth-api-settings"> | ||
<fieldset> | ||
<legend>Auth0 API Settings</legend> | ||
<div class="form-control-group"> | ||
<label for="bif-sso__auth-api-settings__domain">Domain</label> | ||
<input id="bif-sso__auth-api-settings__domain" type="text"> | ||
</div> | ||
<div class="form-control-group"> | ||
<label for="bif-sso__auth-api-settings__client-id">Client ID</label> | ||
<input id="bif-sso__auth-api-settings__client-id" type="text"> | ||
</div> | ||
<div class="form-control-group align-with-labels"> | ||
<button type="submit">Save settings</button> | ||
<span id="bif-sso__auth-api-settings__alert-message"></span> | ||
</div> | ||
</fieldset> | ||
</form> | ||
</div> | ||
|
||
<script type="text/javascript"> | ||
// ============================================================================================ | ||
// UTILITY METHODS | ||
// ============================================================================================ | ||
|
||
/** | ||
* Runs the provided function when the document is fully loaded. | ||
* | ||
* @param {Function} fn The function to be run. | ||
*/ | ||
const ready = (fn) => { | ||
if (document.readyState != 'loading') fn() | ||
else document.addEventListener('DOMContentLoaded', fn) | ||
} | ||
|
||
/** | ||
* Enables the provided form element and all its form element children. | ||
* | ||
* Forms themselves can't be "disabled", so we just remove any previously-set `disabled` class. | ||
* Form element children have their `disabled` property set to `false`. | ||
* | ||
* @param {HTMLElement} $form The form element to enable. | ||
*/ | ||
const enableForm = ($form) => { | ||
const $formElements = $form.querySelectorAll('input, textarea, select, button') | ||
$form.classList.remove('disabled') | ||
$formElements.forEach(($el) => $el.disabled = false) | ||
} | ||
|
||
/** | ||
* Disables the provided form element and all its form element children. | ||
* | ||
* Forms themselves can't be "disabled", so we just add a `disabled` class. Form element | ||
* children actually their `disabled` property set to `true`. | ||
* | ||
* @param {HTMLElement} $form The form element to disable. | ||
*/ | ||
const disableForm = ($form) => { | ||
const $formElements = $form.querySelectorAll('input, textarea, select, button') | ||
$form.classList.add('disabled') | ||
$formElements.forEach(($el) => $el.disabled = true) | ||
} | ||
|
||
// ============================================================================================ | ||
// APPLICATION METHODS | ||
// ============================================================================================ | ||
|
||
// Set DOM variables that we'll reference in the following methods thanks to lexical scoping. | ||
const $apiSettingsForm = document.getElementById('bif-sso__auth-api-settings') | ||
const $apiSettingsFieldDomain = document.getElementById('bif-sso__auth-api-settings__domain') | ||
const $apiSettingsFieldClientId = document.getElementById('bif-sso__auth-api-settings__client-id') | ||
const $apiSettingsAlertMessage = document.getElementById('bif-sso__auth-api-settings__alert-message') | ||
|
||
/** | ||
* Updates the alert message placeholder with the provided message and type. | ||
* | ||
* Expected types are "error" or "success". Default is "notification" and has no special style. | ||
* | ||
* @param {String} message The message that should be displayed. | ||
* @param {String} messageType? The message type, from the list above. | ||
*/ | ||
const alertMessage = (message, messageType = 'notification') => { | ||
const filteredClassNames = $apiSettingsAlertMessage.className | ||
.split(' ') | ||
.filter((className) => !className.startsWith('bif-sso__auth-api-settings__alert-message--')) | ||
if (message) filteredClassNames.push(`bif-sso__auth-api-settings__alert-message--${messageType}`) | ||
$apiSettingsAlertMessage.className = filteredClassNames.join(' ').trim() | ||
$apiSettingsAlertMessage.innerHTML = message | ||
} | ||
|
||
/** | ||
* Syntactic sugar for clearing any existing alert message by setting it to blank. | ||
*/ | ||
const clearAlertMessage = () => alertMessage('') | ||
|
||
/** | ||
* Validates that the required settings exist and aren't falsey. | ||
* | ||
* @param {Object} settings An object containing the settings. | ||
*/ | ||
const areValidSettings = (settings) => { | ||
return settings && settings.domain && settings.clientId | ||
} | ||
|
||
/** | ||
* Prefills the settings form with the provided values, if they're set. | ||
* | ||
* @param {Object} settings An object containing the settings. | ||
*/ | ||
const prefillSettingsForm = (settings) => { | ||
$apiSettingsFieldDomain.value = settings.domain || '' | ||
$apiSettingsFieldClientId.value = settings.clientId || '' | ||
} | ||
|
||
/** | ||
* Saves the settings to the remote BuildFire datastore. | ||
* | ||
* TODO: Make this a Promise, probably. | ||
* | ||
* @param {Object} settings An object containing the settings. | ||
*/ | ||
const saveSettings = (settings) => { | ||
disableForm($apiSettingsForm) | ||
buildfire.datastore.save(settings, 'bif__sso__auth_api_settings', (err, status) => { | ||
enableForm($apiSettingsForm) | ||
if (err || !status) alertMessage('Unable to save settings', 'error') | ||
else alertMessage('Settings saved!', 'success') | ||
}) | ||
} | ||
|
||
/** | ||
* Handler for the form submission that saves to the BuildFire datastore. | ||
* | ||
* @param {SubmitEvent} e The native submit event fired by the browser. | ||
*/ | ||
const handleSettingsFormSubmit = (e) => { | ||
// Stop the native form submission | ||
e.preventDefault() | ||
|
||
clearAlertMessage() | ||
|
||
const settings = { | ||
domain: $apiSettingsFieldDomain.value, | ||
clientId: $apiSettingsFieldClientId.value, | ||
} | ||
|
||
if (areValidSettings(settings)) saveSettings(settings) | ||
else alertMessage('Please provide a valid domain and client ID.', 'error') | ||
} | ||
|
||
/** | ||
* Gets the authentication API settings from the BuildFire datastore. | ||
* | ||
* Unlike the widget version, we don't validate the settings here. If they're invalid, we just | ||
* won't prefill the form; we don't need to reject the Promise because of it. | ||
* | ||
* @returns {Promise} Resolves with the settings object, rejects with an error message. | ||
*/ | ||
const getAuthApiSettings = () => new Promise((resolve, reject) => { | ||
buildfire.datastore.get('bif__sso__auth_api_settings', (err, data) => { | ||
if (err) reject('Could not fetch auth API settings.') | ||
else resolve(data.data) | ||
}) | ||
}) | ||
|
||
|
||
// ============================================================================================ | ||
// INIT/START | ||
// ============================================================================================ | ||
|
||
ready(() => { | ||
$apiSettingsForm.addEventListener('submit', handleSettingsFormSubmit) | ||
|
||
getAuthApiSettings() | ||
.then((settings) => { | ||
// If the settings are valid, we'll prefill the form. If they aren't, we don't need to do | ||
// anything, because most likely they've just never been set. | ||
if (areValidSettings(settings)) prefillSettingsForm(settings) | ||
}) | ||
.catch((error) => alertMessage(error, 'error')) | ||
}) | ||
</script> | ||
</body> | ||
</html> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"author": "Bad Idea Factory", | ||
"pluginName": "SSO Management", | ||
"pluginDescription": "Allow users to sign into your application.", | ||
"supportEmail": "[email protected]", | ||
"control": { | ||
"content": { | ||
"enabled": false | ||
}, | ||
"design": { | ||
"enabled": false | ||
}, | ||
"settings": { | ||
"enabled": true | ||
} | ||
}, | ||
"widget": { | ||
}, | ||
"features": [], | ||
"languages": ["en"] | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Resources | ||
|
||
This directory should only contain the two images that BuildFire requires for our plugin. Do not add any other project dependencies to this directory; they will not be available to the plugin. | ||
|
||
- `image.png` (400x400): Hero image shown to app owners who install the plugin into their Plugin Manager. | ||
- `icon.png` (200x200): Icon shown to plugin users in the emulator and "on the actual device". (Unsure what that quoted bit means; it's from the BuildFire docs.) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.