-
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. 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
3 changed files
with
501 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,199 @@ | ||
<!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 or disables the provided form element, depending on its current state. | ||
* | ||
* In this case we disable a form by adding the "disabled" class and setting the `disabled` | ||
* property to `true` on all its child form elements, and enable by doing the opposite. | ||
* | ||
* @param {HTMLElement} $form The form element to toggle. | ||
*/ | ||
const toggleForm = ($form) => { | ||
const $formElements = $form.querySelectorAll('input, textarea, select, button') | ||
if ($form.classList.contains('disabled')) { | ||
$form.classList.remove('disabled') | ||
$formElements.forEach(($el) => $el.disabled = false) | ||
} else { | ||
$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 | ||
} | ||
|
||
/** | ||
* Validates that the required settings exist and aren't falsey. | ||
* | ||
* @param {Object} settings An object containing the settings. | ||
*/ | ||
const areValidSettings = (settings) => { | ||
return settings | ||
&& settings.authApi | ||
&& settings.authApi.domain | ||
&& settings.authApi.clientId | ||
} | ||
|
||
/** | ||
* Prefills the settings form with the provided values, if they're set. | ||
* | ||
* @param {Object} settings An object containing the settings. | ||
*/ | ||
const prefillApiSettingsForm = (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) => { | ||
toggleForm($apiSettingsForm) | ||
buildfire.datastore.save(settings, 'settings', (err, status) => { | ||
toggleForm($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() | ||
|
||
// Clear the alert message | ||
alertMessage('') | ||
|
||
const settings = { | ||
authApi: { | ||
domain: $apiSettingsFieldDomain.value, | ||
clientId: $apiSettingsFieldClientId.value, | ||
}, | ||
} | ||
|
||
if (areValidSettings(settings)) saveSettings(settings) | ||
else alertMessage('❌ Please provide a valid domain and client ID.', 'error') | ||
} | ||
|
||
// ============================================================================================ | ||
// INIT/START | ||
// ============================================================================================ | ||
|
||
ready(() => { | ||
$apiSettingsForm.addEventListener('submit', handleSettingsFormSubmit) | ||
|
||
// Fetch and prefill the existing auth API settings. | ||
buildfire.datastore.get('settings', (err, data) => { | ||
// An error here means interacting with BuildFire failed, not just that data doesn't exist. | ||
if (err) alertMessage('Error fetching existing API settings from BuildFire.', 'error') | ||
else if (data.data && data.data.authApi) prefillApiSettingsForm(data.data.authApi) | ||
}) | ||
}) | ||
</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"] | ||
} |
Oops, something went wrong.