diff --git a/website/api/controllers/admin/get-llm-generated-sql.js b/website/api/controllers/query-generator/get-llm-generated-sql.js similarity index 100% rename from website/api/controllers/admin/get-llm-generated-sql.js rename to website/api/controllers/query-generator/get-llm-generated-sql.js diff --git a/website/api/controllers/admin/view-query-generator.js b/website/api/controllers/query-generator/view-query-generator.js similarity index 100% rename from website/api/controllers/admin/view-query-generator.js rename to website/api/controllers/query-generator/view-query-generator.js diff --git a/website/api/models/User.js b/website/api/models/User.js index 7f325e3ffaf4..abad1efddf23 100644 --- a/website/api/models/User.js +++ b/website/api/models/User.js @@ -271,6 +271,12 @@ without necessarily having a billing card.` description: 'A JS timestamp of when this user\'s Fleet Premium trial license key expires.', }, + canUseQueryGenerator: { + type: 'boolean', + description: 'Whether or not this user can access the query generator page', + defaultsTo: false, + }, + // ╔═╗╔╦╗╔╗ ╔═╗╔╦╗╔═╗ // ║╣ ║║║╠╩╗║╣ ║║╚═╗ // ╚═╝╩ ╩╚═╝╚═╝═╩╝╚═╝ diff --git a/website/api/policies/has-query-generator-access.js b/website/api/policies/has-query-generator-access.js new file mode 100644 index 000000000000..572db7db1d4a --- /dev/null +++ b/website/api/policies/has-query-generator-access.js @@ -0,0 +1,37 @@ +/** + * has-query-generator-access + * + * A simple policy that blocks requests from users who have not been granted access to the query generator. + * + * For more about how to use policies, see: + * https://sailsjs.com/config/policies + * https://sailsjs.com/docs/concepts/policies + * https://sailsjs.com/docs/concepts/policies/access-control-and-permissions + */ +module.exports = async function (req, res, proceed) { + + // First, check whether the request comes from a logged-in user. + // > For more about where `req.me` comes from, check out this app's + // > custom hook (`api/hooks/custom/index.js`). + if (!req.me) { + // Rather than use the standard res.unauthorized(), if the request did not come from a logged-in user, + // we'll redirect them to an generic version of the customer login page. + if (req.wantsJSON) { + return res.sendStatus(401); + } else { + return res.redirect('/login'); + } + }//• + + // Check if this user can access the query generator. + if (!req.me.canUseQueryGenerator) { + return res.forbidden(); + // Then check that this user is a "super admin". + } else if (!req.me.canUseQueryGenerator && !req.me.isSuperAdmin) { + return res.forbidden(); + } + + // IWMIH, this user can access the query generator. + return proceed(); + +}; diff --git a/website/assets/js/cloud.setup.js b/website/assets/js/cloud.setup.js index a8c3aaac405a..fd306f81fa6e 100644 --- a/website/assets/js/cloud.setup.js +++ b/website/assets/js/cloud.setup.js @@ -13,7 +13,7 @@ Cloud.setup({ /* eslint-disable */ - methods: {"redirectToStripeBillingPortal":{"verb":"GET","url":"/customers/update-subscription","args":[]},"downloadSitemap":{"verb":"GET","url":"/sitemap.xml","args":[]},"downloadRssFeed":{"verb":"GET","url":"/rss/:categoryName","args":["categoryName"]},"receiveUsageAnalytics":{"verb":"POST","url":"/api/v1/webhooks/receive-usage-analytics","args":["anonymousIdentifier","fleetVersion","licenseTier","numHostsEnrolled","numUsers","numTeams","numPolicies","numLabels","softwareInventoryEnabled","vulnDetectionEnabled","systemUsersEnabled","hostsStatusWebHookEnabled","numWeeklyActiveUsers","numWeeklyPolicyViolationDaysActual","numWeeklyPolicyViolationDaysPossible","hostsEnrolledByOperatingSystem","hostsEnrolledByOrbitVersion","hostsEnrolledByOsqueryVersion","storedErrors","numHostsNotResponding","organization","mdmMacOsEnabled","mdmWindowsEnabled","liveQueryDisabled","hostExpiryEnabled","numSoftwareVersions","numHostSoftwares","numSoftwareTitles","numHostSoftwareInstalledPaths","numSoftwareCPEs","numSoftwareCVEs","aiFeaturesDisabled","maintenanceWindowsEnabled","maintenanceWindowsConfigured","numHostsFleetDesktopEnabled","numQueries"]},"receiveFromGithub":{"verb":"GET","url":"/api/v1/webhooks/github","args":["botSignature","action","sender","repository","changes","issue","comment","pull_request","label","release"]},"receiveFromStripe":{"verb":"POST","url":"/api/v1/webhooks/receive-from-stripe","args":["id","type","data","webhookSecret"]},"getEstDeviceCertificate":{"verb":"POST","url":"/api/v1/get-est-device-certificate","args":["csrData","authToken"]},"deliverContactFormMessage":{"verb":"POST","url":"/api/v1/deliver-contact-form-message","args":["emailAddress","firstName","lastName","message"]},"sendPasswordRecoveryEmail":{"verb":"POST","url":"/api/v1/entrance/send-password-recovery-email","args":["emailAddress"]},"signup":{"verb":"POST","url":"/api/v1/customers/signup","args":["emailAddress","password","organization","firstName","lastName","signupReason"]},"updateProfile":{"verb":"POST","url":"/api/v1/account/update-profile","args":["firstName","lastName","organization","emailAddress"]},"updatePassword":{"verb":"POST","url":"/api/v1/account/update-password","args":["oldPassword","newPassword"]},"updateBillingCard":{"verb":"POST","url":"/api/v1/account/update-billing-card","args":["stripeToken","billingCardLast4","billingCardBrand","billingCardExpMonth","billingCardExpYear"]},"login":{"verb":"POST","url":"/api/v1/customers/login","args":["emailAddress","password","rememberMe"]},"logout":{"verb":"GET","url":"/api/v1/account/logout","args":[]},"createQuote":{"verb":"POST","url":"/api/v1/customers/create-quote","args":["numberOfHosts"]},"saveBillingInfoAndSubscribe":{"verb":"POST","url":"/api/v1/customers/save-billing-info-and-subscribe","args":["quoteId","organization","firstName","lastName","paymentSource"]},"updatePasswordAndLogin":{"verb":"POST","url":"/api/v1/entrance/update-password-and-login","args":["password","token"]},"deliverDemoSignup":{"verb":"POST","url":"/api/v1/deliver-demo-signup","args":["emailAddress"]},"createOrUpdateOneNewsletterSubscription":{"verb":"POST","url":"/api/v1/create-or-update-one-newsletter-subscription","args":["emailAddress"]},"unsubscribeFromAllNewsletters":{"verb":"GET","url":"/api/v1/unsubscribe-from-all-newsletters","args":["emailAddress"]},"buildLicenseKey":{"verb":"POST","url":"/api/v1/admin/build-license-key","args":["numberOfHosts","organization","expiresAt","partnerName"]},"createVantaAuthorizationRequest":{"verb":"POST","url":"/api/v1/create-vanta-authorization-request","args":["emailAddress","fleetInstanceUrl","fleetApiKey","redirectToExternalPageAfterAuthorization","sharedSecret"]},"redirectVantaAuthorizationRequest":{"verb":"GET","url":"/redirect-vanta-authorization-request","args":["vantaSourceId","state","vantaAuthorizationRequestURL","redirectAfterSetup"]},"deliverMdmBetaSignup":{"verb":"POST","url":"/api/v1/deliver-mdm-beta-signup","args":["emailAddress","fullName","jobTitle","numberOfHosts"]},"getHumanInterpretationFromOsquerySql":{"verb":"POST","url":"/api/v1/get-human-interpretation-from-osquery-sql","args":["sql"]},"deliverAppleCsr":{"verb":"POST","url":"/api/v1/deliver-apple-csr","args":["unsignedCsrData","deliveryMethod"]},"deliverMdmDemoEmail":{"verb":"POST","url":"/api/v1/deliver-mdm-demo-email","args":["emailAddress"]},"provisionSandboxInstanceAndDeliverEmail":{"verb":"POST","url":"/api/v1/admin/provision-sandbox-instance-and-deliver-email","args":["userId"]},"deliverTalkToUsFormSubmission":{"verb":"POST","url":"/api/v1/deliver-talk-to-us-form-submission","args":["emailAddress","firstName","lastName","organization","numberOfHosts","primaryBuyingSituation"]},"saveQuestionnaireProgress":{"verb":"POST","url":"/api/v1/save-questionnaire-progress","args":["currentStep","formData"]},"updateStartCtaVisibility":{"verb":"POST","url":"/api/v1/account/update-start-cta-visibility","args":[]},"deliverDealRegistrationSubmission":{"verb":"POST","url":"/api/v1/deliver-deal-registration-submission","args":["submittersFirstName","submittersLastName","submittersEmailAddress","submittersOrganization","customersFirstName","customersLastName","customersEmailAddress","linkedinUrl","customersOrganization","customersCurrentMdm","otherMdmEvaluated","preferredHosting","expectedDealSize","expectedCloseDate","notes"]},"unsubscribeFromMarketingEmails":{"verb":"GET","url":"/api/v1/unsubscribe-from-marketing-emails","args":["emailAddress"]},"getStripeCheckoutSessionUrl":{"verb":"POST","url":"/api/v1/customers/get-stripe-checkout-session-url","args":["quoteId"]},"getLlmGeneratedSql":{"verb":"POST","url":"/api/v1/admin/get-llm-generated-sql","args":["naturalLanguageQuestion"]}} + methods: {"redirectToStripeBillingPortal":{"verb":"GET","url":"/customers/update-subscription","args":[]},"downloadSitemap":{"verb":"GET","url":"/sitemap.xml","args":[]},"downloadRssFeed":{"verb":"GET","url":"/rss/:categoryName","args":["categoryName"]},"receiveUsageAnalytics":{"verb":"POST","url":"/api/v1/webhooks/receive-usage-analytics","args":["anonymousIdentifier","fleetVersion","licenseTier","numHostsEnrolled","numUsers","numTeams","numPolicies","numLabels","softwareInventoryEnabled","vulnDetectionEnabled","systemUsersEnabled","hostsStatusWebHookEnabled","numWeeklyActiveUsers","numWeeklyPolicyViolationDaysActual","numWeeklyPolicyViolationDaysPossible","hostsEnrolledByOperatingSystem","hostsEnrolledByOrbitVersion","hostsEnrolledByOsqueryVersion","storedErrors","numHostsNotResponding","organization","mdmMacOsEnabled","mdmWindowsEnabled","liveQueryDisabled","hostExpiryEnabled","numSoftwareVersions","numHostSoftwares","numSoftwareTitles","numHostSoftwareInstalledPaths","numSoftwareCPEs","numSoftwareCVEs","aiFeaturesDisabled","maintenanceWindowsEnabled","maintenanceWindowsConfigured","numHostsFleetDesktopEnabled","numQueries"]},"receiveFromGithub":{"verb":"GET","url":"/api/v1/webhooks/github","args":["botSignature","action","sender","repository","changes","issue","comment","pull_request","label","release"]},"receiveFromStripe":{"verb":"POST","url":"/api/v1/webhooks/receive-from-stripe","args":["id","type","data","webhookSecret"]},"getEstDeviceCertificate":{"verb":"POST","url":"/api/v1/get-est-device-certificate","args":["csrData","authToken"]},"deliverContactFormMessage":{"verb":"POST","url":"/api/v1/deliver-contact-form-message","args":["emailAddress","firstName","lastName","message"]},"sendPasswordRecoveryEmail":{"verb":"POST","url":"/api/v1/entrance/send-password-recovery-email","args":["emailAddress"]},"signup":{"verb":"POST","url":"/api/v1/customers/signup","args":["emailAddress","password","organization","firstName","lastName","signupReason"]},"updateProfile":{"verb":"POST","url":"/api/v1/account/update-profile","args":["firstName","lastName","organization","emailAddress"]},"updatePassword":{"verb":"POST","url":"/api/v1/account/update-password","args":["oldPassword","newPassword"]},"updateBillingCard":{"verb":"POST","url":"/api/v1/account/update-billing-card","args":["stripeToken","billingCardLast4","billingCardBrand","billingCardExpMonth","billingCardExpYear"]},"login":{"verb":"POST","url":"/api/v1/customers/login","args":["emailAddress","password","rememberMe"]},"logout":{"verb":"GET","url":"/api/v1/account/logout","args":[]},"createQuote":{"verb":"POST","url":"/api/v1/customers/create-quote","args":["numberOfHosts"]},"saveBillingInfoAndSubscribe":{"verb":"POST","url":"/api/v1/customers/save-billing-info-and-subscribe","args":["quoteId","organization","firstName","lastName","paymentSource"]},"updatePasswordAndLogin":{"verb":"POST","url":"/api/v1/entrance/update-password-and-login","args":["password","token"]},"deliverDemoSignup":{"verb":"POST","url":"/api/v1/deliver-demo-signup","args":["emailAddress"]},"createOrUpdateOneNewsletterSubscription":{"verb":"POST","url":"/api/v1/create-or-update-one-newsletter-subscription","args":["emailAddress"]},"unsubscribeFromAllNewsletters":{"verb":"GET","url":"/api/v1/unsubscribe-from-all-newsletters","args":["emailAddress"]},"buildLicenseKey":{"verb":"POST","url":"/api/v1/admin/build-license-key","args":["numberOfHosts","organization","expiresAt","partnerName"]},"createVantaAuthorizationRequest":{"verb":"POST","url":"/api/v1/create-vanta-authorization-request","args":["emailAddress","fleetInstanceUrl","fleetApiKey","redirectToExternalPageAfterAuthorization","sharedSecret"]},"redirectVantaAuthorizationRequest":{"verb":"GET","url":"/redirect-vanta-authorization-request","args":["vantaSourceId","state","vantaAuthorizationRequestURL","redirectAfterSetup"]},"deliverMdmBetaSignup":{"verb":"POST","url":"/api/v1/deliver-mdm-beta-signup","args":["emailAddress","fullName","jobTitle","numberOfHosts"]},"getHumanInterpretationFromOsquerySql":{"verb":"POST","url":"/api/v1/get-human-interpretation-from-osquery-sql","args":["sql"]},"deliverAppleCsr":{"verb":"POST","url":"/api/v1/deliver-apple-csr","args":["unsignedCsrData","deliveryMethod"]},"deliverMdmDemoEmail":{"verb":"POST","url":"/api/v1/deliver-mdm-demo-email","args":["emailAddress"]},"provisionSandboxInstanceAndDeliverEmail":{"verb":"POST","url":"/api/v1/admin/provision-sandbox-instance-and-deliver-email","args":["userId"]},"deliverTalkToUsFormSubmission":{"verb":"POST","url":"/api/v1/deliver-talk-to-us-form-submission","args":["emailAddress","firstName","lastName","organization","numberOfHosts","primaryBuyingSituation"]},"saveQuestionnaireProgress":{"verb":"POST","url":"/api/v1/save-questionnaire-progress","args":["currentStep","formData"]},"updateStartCtaVisibility":{"verb":"POST","url":"/api/v1/account/update-start-cta-visibility","args":[]},"deliverDealRegistrationSubmission":{"verb":"POST","url":"/api/v1/deliver-deal-registration-submission","args":["submittersFirstName","submittersLastName","submittersEmailAddress","submittersOrganization","customersFirstName","customersLastName","customersEmailAddress","linkedinUrl","customersOrganization","customersCurrentMdm","otherMdmEvaluated","preferredHosting","expectedDealSize","expectedCloseDate","notes"]},"unsubscribeFromMarketingEmails":{"verb":"GET","url":"/api/v1/unsubscribe-from-marketing-emails","args":["emailAddress"]},"getStripeCheckoutSessionUrl":{"verb":"POST","url":"/api/v1/customers/get-stripe-checkout-session-url","args":["quoteId"]},"getLlmGeneratedSql":{"verb":"POST","url":"/api/v1/query-generator/get-llm-generated-sql","args":["naturalLanguageQuestion"]}} /* eslint-enable */ }); diff --git a/website/config/policies.js b/website/config/policies.js index 1da8cfff6397..ed7b3b0cba7f 100644 --- a/website/config/policies.js +++ b/website/config/policies.js @@ -12,6 +12,7 @@ module.exports.policies = { '*': 'is-logged-in', 'admin/*': 'is-super-admin', + 'query-generator/*': 'has-query-generator-access', // Bypass the `is-logged-in` policy for: 'entrance/*': true, diff --git a/website/config/routes.js b/website/config/routes.js index df3b53383709..69ed15f22d57 100644 --- a/website/config/routes.js +++ b/website/config/routes.js @@ -448,7 +448,12 @@ module.exports.routes = { } }, - 'GET /admin/query-generator': { action: 'admin/view-query-generator' }, + 'GET /query-generator': { + action: 'query-generator/view-query-generator', + locals: { + showAdminLinks: true, + } + }, // ╦ ╔═╗╔═╗╔═╗╔═╗╦ ╦ ╦═╗╔═╗╔╦╗╦╦═╗╔═╗╔═╗╔╦╗╔═╗ // ║ ║╣ ║ ╦╠═╣║ ╚╦╝ ╠╦╝║╣ ║║║╠╦╝║╣ ║ ║ ╚═╗ @@ -908,5 +913,5 @@ module.exports.routes = { 'POST /api/v1/deliver-deal-registration-submission': { action: 'deliver-deal-registration-submission' }, '/api/v1/unsubscribe-from-marketing-emails': { action: 'unsubscribe-from-marketing-emails' }, 'POST /api/v1/customers/get-stripe-checkout-session-url': { action: 'customers/get-stripe-checkout-session-url' }, - 'POST /api/v1/admin/get-llm-generated-sql': { action: 'admin/get-llm-generated-sql' }, + 'POST /api/v1/query-generator/get-llm-generated-sql': { action: 'query-generator/get-llm-generated-sql' }, }; diff --git a/website/views/layouts/layout.ejs b/website/views/layouts/layout.ejs index de22654b3b4a..47f35ebc6371 100644 --- a/website/views/layouts/layout.ejs +++ b/website/views/layouts/layout.ejs @@ -206,6 +206,7 @@
+ Generate queries License generator HTML Email preview tool
@@ -289,7 +290,7 @@ Admin pages
- Generate queries + Generate queries License generator HTML Email preview tool