mirror of
https://github.com/documize/community.git
synced 2025-07-19 21:29:42 +02:00
Accept activation key during setup process
Enterprise edition only.
This commit is contained in:
parent
887c999a1e
commit
4d2f30711c
11 changed files with 161 additions and 52 deletions
|
@ -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"
|
||||||
)
|
)
|
||||||
|
@ -73,6 +76,7 @@ func (h *Handler) Setup(w http.ResponseWriter, r *http.Request) {
|
||||||
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"),
|
||||||
|
ActivationKey: r.Form.Get("activationKey"),
|
||||||
Revised: time.Now().UTC(),
|
Revised: time.Now().UTC(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +120,7 @@ type onboardRequest struct {
|
||||||
Password string
|
Password string
|
||||||
Firstname string
|
Firstname string
|
||||||
Lastname string
|
Lastname string
|
||||||
|
ActivationKey string
|
||||||
Revised time.Time
|
Revised time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
|
34
gui/app/components/setup/first-run.js
Normal file
34
gui/app/components/setup/first-run.js
Normal 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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -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" />
|
||||||
|
|
|
@ -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 }) {
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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'];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
13
gui/app/templates/components/setup/first-run.hbs
Normal file
13
gui/app/templates/components/setup/first-run.hbs
Normal 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>
|
Loading…
Add table
Add a link
Reference in a new issue