From 4d2f30711c0631c223824308a4b26a85f6bb056e Mon Sep 17 00:00:00 2001 From: sauls8t Date: Wed, 19 Jun 2019 12:46:05 +0100 Subject: [PATCH] Accept activation key during setup process Enterprise edition only. --- core/database/setup_endpoint.go | 76 ++++++++++++++----- gui/app/components/setup/first-run.js | 34 +++++++++ gui/app/index.html | 1 + gui/app/pods/auth/sso/route.js | 6 +- gui/app/pods/auth/sso/template.hbs | 2 +- gui/app/pods/setup/controller.js | 8 +- gui/app/pods/setup/route.js | 4 +- gui/app/services/app-meta.js | 4 +- gui/app/services/local-storage.js | 37 +++++---- .../components/setup/documize-setup.hbs | 28 ++++--- .../templates/components/setup/first-run.hbs | 13 ++++ 11 files changed, 161 insertions(+), 52 deletions(-) create mode 100644 gui/app/components/setup/first-run.js create mode 100644 gui/app/templates/components/setup/first-run.hbs diff --git a/core/database/setup_endpoint.go b/core/database/setup_endpoint.go index 6a9de6aa..9b329abe 100644 --- a/core/database/setup_endpoint.go +++ b/core/database/setup_endpoint.go @@ -12,6 +12,8 @@ package database import ( + "encoding/json" + "encoding/xml" "errors" "net/http" "time" @@ -21,6 +23,7 @@ import ( "github.com/documize/community/core/secrets" "github.com/documize/community/core/stringutil" "github.com/documize/community/core/uniqueid" + "github.com/documize/community/domain" "github.com/documize/community/domain/store" "github.com/documize/community/server/web" ) @@ -65,15 +68,16 @@ func (h *Handler) Setup(w http.ResponseWriter, r *http.Request) { } details := onboardRequest{ - URL: "", - Company: r.Form.Get("title"), - CompanyLong: r.Form.Get("title"), - Message: r.Form.Get("message"), - Email: r.Form.Get("email"), - Password: r.Form.Get("password"), - Firstname: r.Form.Get("firstname"), - Lastname: r.Form.Get("lastname"), - Revised: time.Now().UTC(), + URL: "", + Company: r.Form.Get("title"), + CompanyLong: r.Form.Get("title"), + Message: r.Form.Get("message"), + Email: r.Form.Get("email"), + Password: r.Form.Get("password"), + Firstname: r.Form.Get("firstname"), + Lastname: r.Form.Get("lastname"), + ActivationKey: r.Form.Get("activationKey"), + Revised: time.Now().UTC(), } if details.Company == "" || @@ -108,15 +112,16 @@ func (h *Handler) Setup(w http.ResponseWriter, r *http.Request) { // The result of completing the onboarding process. type onboardRequest struct { - URL string - Company string - CompanyLong string - Message string - Email string - Password string - Firstname string - Lastname string - Revised time.Time + URL string + Company string + CompanyLong string + Message string + Email string + Password string + Firstname string + Lastname string + ActivationKey string + Revised time.Time } // setupAccount prepares the database for a newly onboard customer. @@ -132,10 +137,14 @@ func setupAccount(rt *env.Runtime, completion onboardRequest, serial string) (er salt := secrets.GenerateSalt() password := secrets.GeneratePassword(completion.Password, salt) + // Process activation key if we have one. + activationKey := processActivationKey(rt, completion) + // Allocate organization to the user. orgID := uniqueid.Generate() - _, err = tx.Exec(RebindParams("INSERT INTO dmz_org (c_refid, c_company, c_title, c_message, c_domain, c_email, c_serial) VALUES (?, ?, ?, ?, ?, ?, ?)", rt.StoreProvider.Type()), - orgID, completion.Company, completion.CompanyLong, completion.Message, completion.URL, completion.Email, serial) + _, err = tx.Exec(RebindParams("INSERT INTO dmz_org (c_refid, c_company, c_title, c_message, c_domain, c_email, c_serial, c_sub) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + rt.StoreProvider.Type()), + orgID, completion.Company, completion.CompanyLong, completion.Message, completion.URL, completion.Email, serial, activationKey) if err != nil { rt.Log.Error("INSERT INTO dmz_org failed", err) tx.Rollback() @@ -243,3 +252,30 @@ func setupAccount(rt *env.Runtime, completion onboardRequest, serial string) (er return } + +func processActivationKey(rt *env.Runtime, or onboardRequest) (key string) { + key = "{}" + if len(or.ActivationKey) == 0 { + return + } + + j := domain.SubscriptionData{} + x := domain.SubscriptionXML{Key: "", Signature: ""} + + err1 := xml.Unmarshal([]byte(or.ActivationKey), &x) + if err1 == nil { + j.Key = x.Key + j.Signature = x.Signature + } else { + rt.Log.Error("failed to XML unmarshal subscription XML", err1) + } + + d, err2 := json.Marshal(j) + if err2 == nil { + key = string(d) + } else { + rt.Log.Error("failed to JSON marshal subscription XML", err2) + } + + return +} diff --git a/gui/app/components/setup/first-run.js b/gui/app/components/setup/first-run.js new file mode 100644 index 00000000..b0d6e42d --- /dev/null +++ b/gui/app/components/setup/first-run.js @@ -0,0 +1,34 @@ +// Copyright 2016 Documize Inc. . All rights reserved. +// +// This software (Documize Community Edition) is licensed under +// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html +// +// You can operate outside the AGPL restrictions by purchasing +// Documize Enterprise Edition and obtaining a commercial license +// by contacting . +// +// https://documize.com + +import { inject as service } from '@ember/service'; +import Modals from '../../mixins/modal'; +import Component from '@ember/component'; + +export default Component.extend(Modals, { + localStorage: service(), + + didReceiveAttrs() { + this._super(...arguments); + + let firstRun = this.get('localStorage').isFirstRun(); + + if (firstRun) { + this.modalOpen('#first-run-modal', {'show': true}); + } + }, + + actions: { + onCloseModal() { + this.modalClose('#first-run-modal'); + } + } +}); diff --git a/gui/app/index.html b/gui/app/index.html index 7f2dd508..836bd5b7 100644 --- a/gui/app/index.html +++ b/gui/app/index.html @@ -7,6 +7,7 @@ Documize + diff --git a/gui/app/pods/auth/sso/route.js b/gui/app/pods/auth/sso/route.js index b3d8c416..7224d0db 100644 --- a/gui/app/pods/auth/sso/route.js +++ b/gui/app/pods/auth/sso/route.js @@ -16,8 +16,12 @@ export default Route.extend({ session: service(), localStorage: service(), - beforeModel() { + beforeModel(transition) { this.get('localStorage').clearAll(); + + if (!_.isUndefined(transition.to.queryParams.fr)) { + this.get('localStorage').setFirstRun(); + } }, model({ token }) { diff --git a/gui/app/pods/auth/sso/template.hbs b/gui/app/pods/auth/sso/template.hbs index 374e0457..53b98c3d 100644 --- a/gui/app/pods/auth/sso/template.hbs +++ b/gui/app/pods/auth/sso/template.hbs @@ -1,4 +1,4 @@

Signing in...

- + busy
diff --git a/gui/app/pods/setup/controller.js b/gui/app/pods/setup/controller.js index 3a0bfdfc..87a2caad 100644 --- a/gui/app/pods/setup/controller.js +++ b/gui/app/pods/setup/controller.js @@ -23,10 +23,10 @@ export default Controller.extend({ data: this.model, dataType: "text", }).then(() => { - let dom = ""; // supports http://localhost:5001 installations (which is the default for all self-installs) - var credentials = Encoding.Base64.encode(dom + ":" + this.model.email + ":" + this.model.password); - window.location.href = "/auth/sso/" + encodeURIComponent(credentials); - }).catch((error) => { // eslint-disable-line no-unused-vars + let dom = ""; // supports http://localhost:5001 installs (which is the default for all self-installs) + let credentials = Encoding.Base64.encode(dom + ":" + this.model.email + ":" + this.model.password); + window.location.href = "/auth/sso/" + encodeURIComponent(credentials) + '?fr=1'; + }).catch((/*error*/) => { // TODO notify user of the error within the GUI }); } diff --git a/gui/app/pods/setup/route.js b/gui/app/pods/setup/route.js index f2f7f071..7af5a5dd 100644 --- a/gui/app/pods/setup/route.js +++ b/gui/app/pods/setup/route.js @@ -33,7 +33,9 @@ export default Route.extend({ firstname: "", lastname: "", email: "", - password: pwd + password: pwd, + activationKey: '', + edition: document.head.querySelector("[property=edition]").content }; }, diff --git a/gui/app/services/app-meta.js b/gui/app/services/app-meta.js index 1fe1a51c..889efa79 100644 --- a/gui/app/services/app-meta.js +++ b/gui/app/services/app-meta.js @@ -59,10 +59,12 @@ export default Service.extend({ let isInSetupMode = dbhash && dbhash !== "{{.DBhash}}"; if (isInSetupMode) { + let edition = document.head.querySelector("[property=edition]"); this.setProperties({ title: htmlSafe("Documize Setup"), allowAnonymousAccess: true, - setupMode: true + setupMode: true, + edition: !_.isNull(edition) ? edition : 'Community' }); this.get('localStorage').clearAll(); diff --git a/gui/app/services/local-storage.js b/gui/app/services/local-storage.js index 70b07736..4f335ec4 100644 --- a/gui/app/services/local-storage.js +++ b/gui/app/services/local-storage.js @@ -12,22 +12,23 @@ import Service from '@ember/service'; export default Service.extend({ - storeSessionItem: function (key, data) { - localStorage[key] = data; - }, - - getSessionItem: function (key) { - return localStorage[key]; - }, - - clearSessionItem: function (key) { - delete localStorage[key]; - }, - + // Remove all items from storage. clearAll() { localStorage.clear(); }, + // Generic session item CRUD methods. + storeSessionItem: function (key, data) { + localStorage[key] = data; + }, + getSessionItem: function (key) { + return localStorage[key]; + }, + clearSessionItem: function (key) { + delete localStorage[key]; + }, + + // Per document expand/collapse state. getDocSectionHide(docId) { let state = localStorage[`doc-hide-${docId}`]; if (_.isUndefined(state) || _.isEmpty(state)) { @@ -36,7 +37,6 @@ export default Service.extend({ return _.split(state, '|'); }, - setDocSectionHide(docId, state) { let key = `doc-hide-${docId}`; @@ -46,4 +46,15 @@ export default Service.extend({ localStorage[key] = _.join(state, '|'); } }, + + // First run wizard. + setFirstRun() { + localStorage['firstRun'] = true; + }, + isFirstRun() { + return !_.isUndefined(localStorage['firstRun']); + }, + unsetFirstRun() { + delete localStorage['firstRun']; + } }); diff --git a/gui/app/templates/components/setup/documize-setup.hbs b/gui/app/templates/components/setup/documize-setup.hbs index 999b38c0..f9e3e1c6 100644 --- a/gui/app/templates/components/setup/documize-setup.hbs +++ b/gui/app/templates/components/setup/documize-setup.hbs @@ -1,7 +1,7 @@
Documize Setup -

Installation Guide

+

Setup

Review the installation instructions and recommended database tuning guide @@ -11,27 +11,33 @@

- {{focus-input id="siteTitle" type="text" value=model.title class=(if hasEmptyTitleError "form-control is-invalid" "form-control")}} + {{focus-input id="setup-title" type="text" value=model.title class=(if hasTitleError "form-control is-invalid" "form-control")}} Usually your company or team name
- - {{input id="adminFirstname" type="text" value=model.firstname class=(if hasEmptyFirstnameError "form-control is-invalid" "form-control")}} + + {{input id="setup-firstname" type="text" value=model.firstname class=(if hasFirstnameError "form-control is-invalid" "form-control")}}
- - {{input id="adminLastname" type="text" value=model.lastname class=(if hasEmptyLastnameError "form-control is-invalid" "form-control")}} + + {{input id="setup-lastname" type="text" value=model.lastname class=(if hasLastnameError "form-control is-invalid" "form-control")}}
- - {{input id="adminEmail" type="email" value=model.email class=(if hasEmptyEmailError "form-control is-invalid" "form-control")}} - No spam. Ever. + + {{input id="setup-email" type="email" value=model.email class=(if hasEmailError "form-control is-invalid" "form-control")}}
- - {{input id="adminPassword" type="password" value=model.password class=(if hasEmptyPasswordError "form-control is-invalid" "form-control")}} + + {{input id="new-password" type="password" value=model.password class=(if hasPasswordError "form-control is-invalid" "form-control")}} Pick something strong and unique that you don't use anywhere else
+ {{#if (eq model.edition constants.Product.EnterpriseEdition)}} +
+ + {{textarea id="activation-key" value=model.activationKey rows="5" class=(if hasKeyError "form-control is-invalid" "form-control")}} + You can get it from https://www.documize.com/downloads +
+ {{/if}} {{ui/ui-button submit=true color=constants.Color.Green light=true label=buttonLabel onClick=(action "save")}}
diff --git a/gui/app/templates/components/setup/first-run.hbs b/gui/app/templates/components/setup/first-run.hbs new file mode 100644 index 00000000..44b7f926 --- /dev/null +++ b/gui/app/templates/components/setup/first-run.hbs @@ -0,0 +1,13 @@ +