-
Notifications
You must be signed in to change notification settings - Fork 442
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Website: Add admin tool for generating Fleet Premium licenses. (#8478)
* create admin/generate-license page * create generate-license-key action, update routes, policies, importer, regenerate cloud-sdk * update layouts * use moment * Update view-generate-license.js * Fixing lint errors * Update generate-license-key.js * Update redirects in is-super-admin policy * redirect super admins to the license generator * Update login form * requested changes from mike-j-thomas * Update generate-license.page.js * Update is-super-admin.js * Update view-login.js * Update generate-license-key.js * Update generate-license-key.js * use naming convention for js timestamps * validTo » expiresAt Co-authored-by: Mike McNeil <[email protected]>
- Loading branch information
1 parent
d92d998
commit 48f86b2
Showing
21 changed files
with
352 additions
and
15 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,49 @@ | ||
module.exports = { | ||
|
||
|
||
friendlyName: 'Generate license key',// FUTURE: Rename this to avoid confusion w/ generators. For example: 'Build license key' | ||
|
||
|
||
description: 'Generate and return a Fleet Premium license key.', | ||
|
||
|
||
inputs: { | ||
numberOfHosts: { | ||
type: 'number', | ||
required: true, | ||
}, | ||
|
||
organization: { | ||
type: 'string', | ||
required: true, | ||
}, | ||
|
||
expiresAt: { | ||
type: 'number', | ||
required: true, | ||
description: 'A JS timestamp representing when this license will expire.' | ||
} | ||
}, | ||
|
||
|
||
exits: { | ||
success: { | ||
outputFriendlyName: 'License key', | ||
outputType: 'string', | ||
}, | ||
}, | ||
|
||
|
||
fn: async function ({numberOfHosts, organization, expiresAt}) { | ||
|
||
let licenseKey = await sails.helpers.createLicenseKey.with({ | ||
numberOfHosts: numberOfHosts, | ||
organization: organization, | ||
expiresAt: expiresAt | ||
}); | ||
|
||
return licenseKey; | ||
} | ||
|
||
|
||
}; |
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,35 @@ | ||
module.exports = { | ||
|
||
|
||
friendlyName: 'View generate license', | ||
|
||
|
||
description: 'Display "Generate license" page, an admin tool for generating Fleet Premium licenses', | ||
|
||
|
||
exits: { | ||
|
||
success: { | ||
viewTemplatePath: 'pages/admin/generate-license' | ||
}, | ||
|
||
}, | ||
|
||
|
||
fn: async function () { | ||
|
||
// Throw an error if the licenseKeyGeneratorPrivateKey or licenseKeyGeneratorPassphrase are missing. | ||
if(!sails.config.custom.licenseKeyGeneratorPrivateKey) { | ||
throw new Error('Missing config variable: The license key generator private key missing (sails.config.custom.licenseKeyGeneratorPrivateKey)! To use this tool, a license key generator private key is required.'); | ||
} | ||
|
||
if(!sails.config.custom.licenseKeyGeneratorPassphrase) { | ||
throw new Error('Missing config variable: The license key generator passphrase missing(sails.config.custom.licenseKeyGeneratorPassphrase)! To use this tool, a license key generator passphrase is required.'); | ||
} | ||
|
||
// Respond with view. | ||
return {}; | ||
} | ||
|
||
|
||
}; |
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
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
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
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
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,73 @@ | ||
parasails.registerPage('generate-license', { | ||
// ╦╔╗╔╦╔╦╗╦╔═╗╦ ╔═╗╔╦╗╔═╗╔╦╗╔═╗ | ||
// ║║║║║ ║ ║╠═╣║ ╚═╗ ║ ╠═╣ ║ ║╣ | ||
// ╩╝╚╝╩ ╩ ╩╩ ╩╩═╝ ╚═╝ ╩ ╩ ╩ ╩ ╚═╝ | ||
data: { | ||
// Form data | ||
formData: {}, | ||
// For tracking client-side validation errors in our form. | ||
// > Has property set to `true` for each invalid property in `formData`. | ||
formErrors: {}, | ||
// Form rules | ||
formRules: { | ||
numberOfHosts: {required: true}, | ||
organization: {required: true}, | ||
expiresAt: {required: true}, | ||
}, | ||
// Syncing / loading state | ||
syncing: false, | ||
// Server error state | ||
cloudError: '', | ||
generatedLicenseKey: '', | ||
showResult: false, | ||
}, | ||
|
||
// ╦ ╦╔═╗╔═╗╔═╗╦ ╦╔═╗╦ ╔═╗ | ||
// ║ ║╠╣ ║╣ ║ ╚╦╝║ ║ ║╣ | ||
// ╩═╝╩╚ ╚═╝╚═╝ ╩ ╚═╝╩═╝╚═╝ | ||
beforeMount: function() { | ||
// Get a formatted date string for year from today's date. | ||
let oneYearFromNowDateString = moment(Date.now() + (365*24*60*60*1000)).format('YYYY-MM-DD'); | ||
// Set the starting value for the validTo input | ||
this.formData.expiresAt = oneYearFromNowDateString; | ||
}, | ||
mounted: async function() { | ||
//… | ||
}, | ||
|
||
// ╦╔╗╔╔╦╗╔═╗╦═╗╔═╗╔═╗╔╦╗╦╔═╗╔╗╔╔═╗ | ||
// ║║║║ ║ ║╣ ╠╦╝╠═╣║ ║ ║║ ║║║║╚═╗ | ||
// ╩╝╚╝ ╩ ╚═╝╩╚═╩ ╩╚═╝ ╩ ╩╚═╝╝╚╝╚═╝ | ||
methods: { | ||
handleSubmittingForm: async function() { | ||
let validToDate = new Date(this.formData.expiresAt); | ||
let validToTimestamp = validToDate.getTime(); | ||
this.generatedLicenseKey = await Cloud.generateLicenseKey.with({ | ||
numberOfHosts: this.formData.numberOfHosts, | ||
organization: this.formData.organization, | ||
expiresAt: validToTimestamp | ||
}); | ||
}, | ||
|
||
submittedQuoteForm: async function() { | ||
this.syncing = false; | ||
this.showResult = true; | ||
}, | ||
|
||
clickCopyLicenseKey: function(){ | ||
$('[purpose="copied-notification"]').finish(); | ||
$('[purpose="copied-notification"]').fadeIn(100).delay(2000).fadeOut(500); | ||
// https://caniuse.com/mdn-api_clipboard_writetext | ||
navigator.clipboard.writeText(this.generatedLicenseKey); | ||
}, | ||
|
||
clickClearFormFields: async function() { | ||
this.generatedLicenseKey = ''; | ||
this.showResult = false; | ||
this.formErrors = {}; | ||
this.formData = {}; | ||
this.formData.validTo = moment(Date.now() + (365*24*60*60*1000)).format('YYYY-MM-DD'); | ||
await this.forceRender(); | ||
} | ||
} | ||
}); |
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
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
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,79 @@ | ||
#generate-license { | ||
padding-top: 80px; | ||
|
||
h1 { | ||
font-size: 28px; | ||
line-height: 38px; | ||
} | ||
[purpose='form'] { | ||
max-width: 480px; | ||
input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { | ||
-webkit-appearance: none; | ||
margin: 0; | ||
} | ||
input[type='number'] { | ||
-moz-appearance: textfield; | ||
} | ||
label { | ||
font-weight: 400; | ||
margin-bottom: 4px; | ||
} | ||
.form-control { | ||
height: 40px; | ||
border-radius: 6px; | ||
} | ||
.card { | ||
border-radius: 6px; | ||
} | ||
.card-body { | ||
padding: 2em; | ||
} | ||
} | ||
[purpose='cloud-error'] { | ||
max-width: fit-content; | ||
} | ||
[purpose='submit-button'] { | ||
margin-left: auto; | ||
margin-right: auto; | ||
border-radius: 4px; | ||
padding-top: 10px; | ||
padding-bottom: 10px; | ||
display: flex; | ||
span { | ||
display: inline; | ||
margin-left: auto; | ||
margin-right: auto; | ||
font-size: 16px; | ||
line-height: 20px; | ||
text-align: center; | ||
font-weight: 400; | ||
} | ||
|
||
} | ||
|
||
[purpose='result'] { | ||
border: 1px solid @bg-lt-gray; | ||
padding: 4px 6px; | ||
border-radius: 4px; | ||
position: relative; | ||
code { | ||
font: @code-font; | ||
color: @core-fleet-black; | ||
} | ||
} | ||
[purpose='copy-button'] { | ||
cursor: pointer; | ||
color: @core-vibrant-blue; | ||
} | ||
[purpose='copied-notification'] { | ||
display: none; | ||
font-weight: 400; | ||
position: absolute; | ||
top: -30px; | ||
right: 0px; | ||
font-size: 16px; | ||
line-height: 20px; | ||
white-space: nowrap; | ||
color: @core-vibrant-blue; | ||
} | ||
} |
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
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
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
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
Oops, something went wrong.