1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-20 13:49:42 +02:00

Accept activation key during setup process

Enterprise edition only.
This commit is contained in:
sauls8t 2019-06-19 12:46:05 +01:00
parent 887c999a1e
commit 4d2f30711c
11 changed files with 161 additions and 52 deletions

View file

@ -12,6 +12,8 @@
package database package database
import ( import (
"encoding/json"
"encoding/xml"
"errors" "errors"
"net/http" "net/http"
"time" "time"
@ -21,6 +23,7 @@ import (
"github.com/documize/community/core/secrets" "github.com/documize/community/core/secrets"
"github.com/documize/community/core/stringutil" "github.com/documize/community/core/stringutil"
"github.com/documize/community/core/uniqueid" "github.com/documize/community/core/uniqueid"
"github.com/documize/community/domain"
"github.com/documize/community/domain/store" "github.com/documize/community/domain/store"
"github.com/documize/community/server/web" "github.com/documize/community/server/web"
) )
@ -65,15 +68,16 @@ func (h *Handler) Setup(w http.ResponseWriter, r *http.Request) {
} }
details := onboardRequest{ details := onboardRequest{
URL: "", URL: "",
Company: r.Form.Get("title"), Company: r.Form.Get("title"),
CompanyLong: r.Form.Get("title"), CompanyLong: r.Form.Get("title"),
Message: r.Form.Get("message"), Message: r.Form.Get("message"),
Email: r.Form.Get("email"), Email: r.Form.Get("email"),
Password: r.Form.Get("password"), Password: r.Form.Get("password"),
Firstname: r.Form.Get("firstname"), Firstname: r.Form.Get("firstname"),
Lastname: r.Form.Get("lastname"), Lastname: r.Form.Get("lastname"),
Revised: time.Now().UTC(), ActivationKey: r.Form.Get("activationKey"),
Revised: time.Now().UTC(),
} }
if details.Company == "" || if details.Company == "" ||
@ -108,15 +112,16 @@ func (h *Handler) Setup(w http.ResponseWriter, r *http.Request) {
// The result of completing the onboarding process. // The result of completing the onboarding process.
type onboardRequest struct { type onboardRequest struct {
URL string URL string
Company string Company string
CompanyLong string CompanyLong string
Message string Message string
Email string Email string
Password string Password string
Firstname string Firstname string
Lastname string Lastname string
Revised time.Time ActivationKey string
Revised time.Time
} }
// setupAccount prepares the database for a newly onboard customer. // 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() salt := secrets.GenerateSalt()
password := secrets.GeneratePassword(completion.Password, salt) password := secrets.GeneratePassword(completion.Password, salt)
// Process activation key if we have one.
activationKey := processActivationKey(rt, completion)
// Allocate organization to the user. // Allocate organization to the user.
orgID := uniqueid.Generate() 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()), _, 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 (?, ?, ?, ?, ?, ?, ?, ?)",
orgID, completion.Company, completion.CompanyLong, completion.Message, completion.URL, completion.Email, serial) rt.StoreProvider.Type()),
orgID, completion.Company, completion.CompanyLong, completion.Message, completion.URL, completion.Email, serial, activationKey)
if err != nil { if err != nil {
rt.Log.Error("INSERT INTO dmz_org failed", err) rt.Log.Error("INSERT INTO dmz_org failed", err)
tx.Rollback() tx.Rollback()
@ -243,3 +252,30 @@ func setupAccount(rt *env.Runtime, completion onboardRequest, serial string) (er
return 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
}

View file

@ -0,0 +1,34 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. 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 <sales@documize.com>.
//
// 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');
}
}
});

View file

@ -7,6 +7,7 @@
<title>Documize</title> <title>Documize</title>
<meta property="dbname" content="{{.DBname}}" /> <meta property="dbname" content="{{.DBname}}" />
<meta property="dbhash" content="{{.DBhash}}" /> <meta property="dbhash" content="{{.DBhash}}" />
<meta property="edition" content="{{.Edition}}" />
<meta name="author" content="Documize" /> <meta name="author" content="Documize" />
<meta name="description" content="Documize"> <meta name="description" content="Documize">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />

View file

@ -16,8 +16,12 @@ export default Route.extend({
session: service(), session: service(),
localStorage: service(), localStorage: service(),
beforeModel() { beforeModel(transition) {
this.get('localStorage').clearAll(); this.get('localStorage').clearAll();
if (!_.isUndefined(transition.to.queryParams.fr)) {
this.get('localStorage').setFirstRun();
}
}, },
model({ token }) { model({ token }) {

View file

@ -1,4 +1,4 @@
<div class="sso-box"> <div class="sso-box">
<p>Signing in...</p> <p>Signing in...</p>
<img src="/assets/img/busy-gray.gif"> <img src="/assets/img/busy-gray.gif" alt="busy">
</div> </div>

View file

@ -23,10 +23,10 @@ export default Controller.extend({
data: this.model, data: this.model,
dataType: "text", dataType: "text",
}).then(() => { }).then(() => {
let dom = ""; // supports http://localhost:5001 installations (which is the default for all self-installs) let dom = ""; // supports http://localhost:5001 installs (which is the default for all self-installs)
var credentials = Encoding.Base64.encode(dom + ":" + this.model.email + ":" + this.model.password); let credentials = Encoding.Base64.encode(dom + ":" + this.model.email + ":" + this.model.password);
window.location.href = "/auth/sso/" + encodeURIComponent(credentials); window.location.href = "/auth/sso/" + encodeURIComponent(credentials) + '?fr=1';
}).catch((error) => { // eslint-disable-line no-unused-vars }).catch((/*error*/) => {
// TODO notify user of the error within the GUI // TODO notify user of the error within the GUI
}); });
} }

View file

@ -33,7 +33,9 @@ export default Route.extend({
firstname: "", firstname: "",
lastname: "", lastname: "",
email: "", email: "",
password: pwd password: pwd,
activationKey: '',
edition: document.head.querySelector("[property=edition]").content
}; };
}, },

View file

@ -59,10 +59,12 @@ export default Service.extend({
let isInSetupMode = dbhash && dbhash !== "{{.DBhash}}"; let isInSetupMode = dbhash && dbhash !== "{{.DBhash}}";
if (isInSetupMode) { if (isInSetupMode) {
let edition = document.head.querySelector("[property=edition]");
this.setProperties({ this.setProperties({
title: htmlSafe("Documize Setup"), title: htmlSafe("Documize Setup"),
allowAnonymousAccess: true, allowAnonymousAccess: true,
setupMode: true setupMode: true,
edition: !_.isNull(edition) ? edition : 'Community'
}); });
this.get('localStorage').clearAll(); this.get('localStorage').clearAll();

View file

@ -12,22 +12,23 @@
import Service from '@ember/service'; import Service from '@ember/service';
export default Service.extend({ export default Service.extend({
storeSessionItem: function (key, data) { // Remove all items from storage.
localStorage[key] = data;
},
getSessionItem: function (key) {
return localStorage[key];
},
clearSessionItem: function (key) {
delete localStorage[key];
},
clearAll() { clearAll() {
localStorage.clear(); 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) { getDocSectionHide(docId) {
let state = localStorage[`doc-hide-${docId}`]; let state = localStorage[`doc-hide-${docId}`];
if (_.isUndefined(state) || _.isEmpty(state)) { if (_.isUndefined(state) || _.isEmpty(state)) {
@ -36,7 +37,6 @@ export default Service.extend({
return _.split(state, '|'); return _.split(state, '|');
}, },
setDocSectionHide(docId, state) { setDocSectionHide(docId, state) {
let key = `doc-hide-${docId}`; let key = `doc-hide-${docId}`;
@ -46,4 +46,15 @@ export default Service.extend({
localStorage[key] = _.join(state, '|'); localStorage[key] = _.join(state, '|');
} }
}, },
// First run wizard.
setFirstRun() {
localStorage['firstRun'] = true;
},
isFirstRun() {
return !_.isUndefined(localStorage['firstRun']);
},
unsetFirstRun() {
delete localStorage['firstRun'];
}
}); });

View file

@ -1,7 +1,7 @@
<div class="installer"> <div class="installer">
<img src="/assets/img/setup/logo-purple.png" srcset="/assets/img/setup/logo-purple@2x.png" alt="Documize Setup" style="width: 250px; height: 76px;"> <img src="/assets/img/setup/logo-purple.png" srcset="/assets/img/setup/logo-purple@2x.png" alt="Documize Setup" style="width: 250px; height: 76px;">
<Ui::UiSpacer @size="300" /> <Ui::UiSpacer @size="300" />
<h1 class="color-theme-700">Installation Guide</h1> <h1 class="color-theme-700">Setup</h1>
<p class="color-gray-800"> <p class="color-gray-800">
Review the <a href="https://docs.documize.com/s/VzO9ZqMOCgABGyfW/installation-guides/d/V16L08ucxwABhZF6/installation-guide">installation instructions</a> Review the <a href="https://docs.documize.com/s/VzO9ZqMOCgABGyfW/installation-guides/d/V16L08ucxwABhZF6/installation-guide">installation instructions</a>
and recommended <a href="https://docs.documize.com/s/VzO9ZqMOCgABGyfW/installation-guides/d/V2KuM8ICcQABagM5/mysql-specific-database-tuning">database tuning guide</a> and recommended <a href="https://docs.documize.com/s/VzO9ZqMOCgABGyfW/installation-guides/d/V2KuM8ICcQABagM5/mysql-specific-database-tuning">database tuning guide</a>
@ -11,27 +11,33 @@
<form {{action "save" on="submit"}}> <form {{action "save" on="submit"}}>
<div class="form-group"> <div class="form-group">
<label>Site name</label> <label>Site name</label>
{{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")}}
<small class="form-text text-muted">Usually your company or team name</small> <small class="form-text text-muted">Usually your company or team name</small>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="adminFirstname">Firstname</label> <label for="setup-firstname">Firstname</label>
{{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")}}
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="adminLastname">Lastname</label> <label for="setup-lastname">Lastname</label>
{{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")}}
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="adminEmail">Email</label> <label for="setup-email">Email</label>
{{input id="adminEmail" type="email" value=model.email class=(if hasEmptyEmailError "form-control is-invalid" "form-control")}} {{input id="setup-email" type="email" value=model.email class=(if hasEmailError "form-control is-invalid" "form-control")}}
<small class="form-text text-muted">No spam. Ever.</small>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="adminPassword">Password</label> <label for="new-password">Password</label>
{{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")}}
<small class="form-text text-muted">Pick something strong and unique that you don't use anywhere else</small> <small class="form-text text-muted">Pick something strong and unique that you don't use anywhere else</small>
</div> </div>
{{#if (eq model.edition constants.Product.EnterpriseEdition)}}
<div class="form-group">
<label for="activation-key">Activation Key</label>
{{textarea id="activation-key" value=model.activationKey rows="5" class=(if hasKeyError "form-control is-invalid" "form-control")}}
<small class="form-text text-muted">You can get it from <a href="https://www.documize.com/downloads" target="_blank">https://www.documize.com/downloads</a></small>
</div>
{{/if}}
{{ui/ui-button submit=true color=constants.Color.Green light=true label=buttonLabel onClick=(action "save")}} {{ui/ui-button submit=true color=constants.Color.Green light=true label=buttonLabel onClick=(action "save")}}
</form> </form>

View file

@ -0,0 +1,13 @@
<div id="first-run-modal" class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">Getting Started</div>
<div class="modal-body">
<p>dfdfdf</p>
</div>
<div class="modal-footer">
{{ui/ui-button color=constants.Color.Yellow light=true label="Got it!" dismiss=true}}
</div>
</div>
</div>
</div>