1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-23 15:19:42 +02:00

support for license keys

This commit is contained in:
Harvey Kandola 2017-02-22 20:03:40 -08:00
parent b0d70e2657
commit 3f87401d49
10 changed files with 252 additions and 35 deletions

View file

@ -16,14 +16,14 @@ const {
} = Ember; } = Ember;
export default Ember.Component.extend({ export default Ember.Component.extend({
SMTPHostEmptyError: computed.empty('model.global.host'), SMTPHostEmptyError: computed.empty('model.smtp.host'),
SMTPPortEmptyError: computed.empty('model.global.port'), SMTPPortEmptyError: computed.empty('model.smtp.port'),
SMTPSenderEmptyError: computed.empty('model.global.sender'), SMTPSenderEmptyError: computed.empty('model.smtp.sender'),
SMTPUserIdEmptyError: computed.empty('model.global.userid'), SMTPUserIdEmptyError: computed.empty('model.smtp.userid'),
SMTPPasswordEmptyError: computed.empty('model.global.password'), SMTPPasswordEmptyError: computed.empty('model.smtp.password'),
actions: { actions: {
save() { saveSMTP() {
if (this.get('SMTPHostEmptyError')) { if (this.get('SMTPHostEmptyError')) {
$("#smtp-host").focus(); $("#smtp-host").focus();
return; return;
@ -45,7 +45,12 @@ export default Ember.Component.extend({
return; return;
} }
this.get('save')().then(() => { this.get('saveSMTP')().then(() => {
});
},
saveLicense() {
this.get('saveLicense')().then(() => {
}); });
} }
} }

View file

@ -16,9 +16,17 @@ export default Ember.Controller.extend(NotifierMixin, {
global: Ember.inject.service(), global: Ember.inject.service(),
actions: { actions: {
save() { saveSMTP() {
if(this.get('session.isGlobalAdmin')) { if(this.get('session.isGlobalAdmin')) {
return this.get('global').saveConfig(this.model.global).then(() => { return this.get('global').saveSMTPConfig(this.model.smtp).then(() => {
this.showNotification('Saved');
});
}
},
saveLicense() {
if(this.get('session.isGlobalAdmin')) {
return this.get('global').saveLicense(this.model.license).then(() => {
this.showNotification('Saved'); this.showNotification('Saved');
}); });
} }

View file

@ -26,7 +26,8 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, {
model() { model() {
return RSVP.hash({ return RSVP.hash({
global: this.get('global').getConfig() smtp: this.get('global').getSMTPConfig(),
license: this.get('global').getLicense()
}); });
}, },

View file

@ -1 +1 @@
{{global-settings model=model save=(action 'save')}} {{global-settings model=model saveSMTP=(action 'saveSMTP') saveLicense=(action 'saveLicense')}}

View file

@ -21,10 +21,10 @@ export default Ember.Service.extend({
appMeta: service(), appMeta: service(),
store: service(), store: service(),
// Returns global configuration. // Returns SMTP configuration.
getConfig() { getSMTPConfig() {
if(this.get('sessionService.isGlobalAdmin')) { if(this.get('sessionService.isGlobalAdmin')) {
return this.get('ajax').request(`global`, { return this.get('ajax').request(`global/smtp`, {
method: 'GET' method: 'GET'
}).then((response) => { }).then((response) => {
return response; return response;
@ -32,13 +32,36 @@ export default Ember.Service.extend({
} }
}, },
// Saves global configuration. // Saves SMTP configuration.
saveConfig(config) { saveSMTPConfig(config) {
if(this.get('sessionService.isGlobalAdmin')) { if(this.get('sessionService.isGlobalAdmin')) {
return this.get('ajax').request(`global`, { return this.get('ajax').request(`global/smtp`, {
method: 'PUT', method: 'PUT',
data: JSON.stringify(config) data: JSON.stringify(config)
}); });
} }
},
// Returns product license.
getLicense() {
if(this.get('sessionService.isGlobalAdmin')) {
return this.get('ajax').request(`global/license`, {
method: 'GET',
dataType: "text"
}).then((response) => {
return response;
});
}
},
// Saves product license
saveLicense(license) {
if(this.get('sessionService.isGlobalAdmin')) {
return this.get('ajax').request(`global/license`, {
method: 'PUT',
dataType: 'text',
data: license
});
}
} }
}); });

View file

@ -1,32 +1,48 @@
<form class="form-bordered"> <form class="form-bordered">
<div class="form-header"> <div class="form-header">
<div class="title">Global Settings</div> <div class="title">Mail Server Settings</div>
<div class="tip">Settings applicable for all tenants</div> <div class="tip">Used for sending email notifications</div>
</div> </div>
<div class="input-control"> <div class="input-control">
<label>SMTP Host</label> <label>SMTP Host</label>
<div class="tip">e.g. my.host.com</div> <div class="tip">e.g. my.host.com</div>
{{focus-input id="smtp-host" type="text" value=model.global.host class=(if SMTPHostEmptyError 'error')}} {{focus-input id="smtp-host" type="text" value=model.smtp.host class=(if SMTPHostEmptyError 'error')}}
</div> </div>
<div class="input-control"> <div class="input-control">
<label>SMTP Port</label> <label>SMTP Port</label>
<div class="tip">e.g. 587</div> <div class="tip">e.g. 587</div>
{{input id="smtp-port" type="text" value=model.global.port class=(if SMTPPortEmptyError 'error')}} {{input id="smtp-port" type="text" value=model.smtp.port class=(if SMTPPortEmptyError 'error')}}
</div> </div>
<div class="input-control"> <div class="input-control">
<label>SMTP Sender</label> <label>SMTP Sender</label>
<div class="tip">e.g. noreply@documize.com</div> <div class="tip">e.g. noreply@documize.com</div>
{{input id="smtp-sender" type="text" value=model.global.sender class=(if SMTPSenderEmptyError 'error')}} {{input id="smtp-sender" type="text" value=model.smtp.sender class=(if SMTPSenderEmptyError 'error')}}
</div> </div>
<div class="input-control"> <div class="input-control">
<label>SMTP User ID</label> <label>SMTP User ID</label>
<div class="tip">Your credentials</div> <div class="tip">Your credentials</div>
{{input id="smtp-userid" type="text" value=model.global.userid class=(if SMTPUserIdEmptyError 'error')}} {{input id="smtp-userid" type="text" value=model.smtp.userid class=(if SMTPUserIdEmptyError 'error')}}
</div> </div>
<div class="input-control"> <div class="input-control">
<label>SMTP Password</label> <label>SMTP Password</label>
<div class="tip">Your credentials</div> <div class="tip">Your credentials</div>
{{input id="smtp-password" type="text" value=model.global.password class=(if SMTPPasswordEmptyError 'error')}} {{input id="smtp-password" type="text" value=model.smtp.password class=(if SMTPPasswordEmptyError 'error')}}
</div> </div>
<div class="regular-button button-blue" {{ action 'save' }}>save</div> <div class="regular-button button-blue" {{ action 'saveSMTP' }}>save</div>
</form>
<div class="margin-top-50">
</div>
<form class="form-bordered">
<div class="form-header">
<div class="title">Edition License</div>
<div class="tip">Product license</div>
</div>
<div class="input-control">
<label>License XML</label>
<div class="tip">Please provide valid XML</div>
{{textarea value=model.license rows="5"}}
</div>
<div class="regular-button button-blue" {{ action 'saveLicense' }}>save</div>
</form> </form>

View file

@ -16,13 +16,15 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"encoding/xml"
"fmt"
"github.com/documize/community/core/api/request" "github.com/documize/community/core/api/request"
"github.com/documize/community/core/api/util" "github.com/documize/community/core/api/util"
) )
// GetGlobalConfig returns installation-wide settings // GetSMTPConfig returns installation-wide SMTP settings
func GetGlobalConfig(w http.ResponseWriter, r *http.Request) { func GetSMTPConfig(w http.ResponseWriter, r *http.Request) {
method := "GetGlobalConfig" method := "GetSMTPConfig"
p := request.GetPersister(r) p := request.GetPersister(r)
if !p.Context.Global { if !p.Context.Global {
@ -39,16 +41,16 @@ func GetGlobalConfig(w http.ResponseWriter, r *http.Request) {
json, err := json.Marshal(y) json, err := json.Marshal(y)
if err != nil { if err != nil {
writeJSONMarshalError(w, method, "GetGlobalConfig", err) writeJSONMarshalError(w, method, "SMTP", err)
return return
} }
util.WriteSuccessBytes(w, json) util.WriteSuccessBytes(w, json)
} }
// SaveGlobalConfig persists global configuration. // SaveSMTPConfig persists global SMTP configuration.
func SaveGlobalConfig(w http.ResponseWriter, r *http.Request) { func SaveSMTPConfig(w http.ResponseWriter, r *http.Request) {
method := "SaveGlobalConfig" method := "SaveSMTPConfig"
p := request.GetPersister(r) p := request.GetPersister(r)
if !p.Context.Global { if !p.Context.Global {
@ -79,3 +81,110 @@ func SaveGlobalConfig(w http.ResponseWriter, r *http.Request) {
util.WriteSuccessEmptyJSON(w) util.WriteSuccessEmptyJSON(w)
} }
// GetLicense returns product license
func GetLicense(w http.ResponseWriter, r *http.Request) {
// method := "GetLicense"
p := request.GetPersister(r)
if !p.Context.Global {
writeForbiddenError(w)
return
}
// SMTP settings
config := request.ConfigString("EDITION-LICENSE", "")
if len(config) == 0 {
config = "{}"
}
x := &licenseXML{Key: "", Signature: ""}
lj := licenseJSON{}
err := json.Unmarshal([]byte(config), &lj)
if err == nil {
x.Key = lj.Key
x.Signature = lj.Signature
} else {
fmt.Println(err)
}
output, err := xml.MarshalIndent(x, " ", " ")
if err != nil {
fmt.Printf("error: %v\n", err)
}
w.WriteHeader(http.StatusOK)
w.Write(output)
// // marshal as JSON
// var y map[string]interface{}
// json.Unmarshal([]byte(config), &y)
// json, err := json.Marshal(y)
// if err != nil {
// writeJSONMarshalError(w, method, "EDITION-LICENSE", err)
// return
// }
// util.WriteSuccessBytes(w, json)
}
// SaveLicense persists product license
func SaveLicense(w http.ResponseWriter, r *http.Request) {
method := "SaveLicense"
p := request.GetPersister(r)
if !p.Context.Global {
writeForbiddenError(w)
return
}
defer r.Body.Close()
body, err := ioutil.ReadAll(r.Body)
if err != nil {
writePayloadError(w, method, err)
return
}
var config string
config = string(body)
lj := licenseJSON{}
x := licenseXML{Key: "", Signature: ""}
err = xml.Unmarshal([]byte(config), &x)
if err == nil {
lj.Key = x.Key
lj.Signature = x.Signature
} else {
fmt.Println(err)
}
j, err := json.Marshal(lj)
js := "{}"
if err == nil {
js = string(j)
}
request.ConfigSet("EDITION-LICENSE", js)
util.WriteSuccessEmptyJSON(w)
}
type licenseXML struct {
XMLName xml.Name `xml:"DocumizeLicense"`
Key string
Signature string
}
type licenseJSON struct {
Key string `json:"key"`
Signature string `json:"signature"`
}
/*
<DocumizeLicense>
<Key>some key</Key>
<Signature>some signature</Signature>
</DocumizeLicense>
*/

View file

@ -229,8 +229,10 @@ func init() {
log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/links", []string{"GET", "OPTIONS"}, nil, GetDocumentLinks)) log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/links", []string{"GET", "OPTIONS"}, nil, GetDocumentLinks))
// Global installation-wide config // Global installation-wide config
log.IfErr(Add(RoutePrefixPrivate, "global", []string{"GET", "OPTIONS"}, nil, GetGlobalConfig)) log.IfErr(Add(RoutePrefixPrivate, "global/smtp", []string{"GET", "OPTIONS"}, nil, GetSMTPConfig))
log.IfErr(Add(RoutePrefixPrivate, "global", []string{"PUT", "OPTIONS"}, nil, SaveGlobalConfig)) log.IfErr(Add(RoutePrefixPrivate, "global/smtp", []string{"PUT", "OPTIONS"}, nil, SaveSMTPConfig))
log.IfErr(Add(RoutePrefixPrivate, "global/license", []string{"GET", "OPTIONS"}, nil, GetLicense))
log.IfErr(Add(RoutePrefixPrivate, "global/license", []string{"PUT", "OPTIONS"}, nil, SaveLicense))
// Pinned items // Pinned items
log.IfErr(Add(RoutePrefixPrivate, "pin/{userID}", []string{"POST", "OPTIONS"}, nil, AddPin)) log.IfErr(Add(RoutePrefixPrivate, "pin/{userID}", []string{"POST", "OPTIONS"}, nil, AddPin))

View file

@ -38,6 +38,9 @@ func init() {
environment.GetString(&keyFile, "key", false, "the key.pem file used for https", nil) environment.GetString(&keyFile, "key", false, "the key.pem file used for https", nil)
environment.GetString(&port, "port", false, "http/https port number", nil) environment.GetString(&port, "port", false, "http/https port number", nil)
environment.GetString(&forcePort2SSL, "forcesslport", false, "redirect given http port number to TLS", nil) environment.GetString(&forcePort2SSL, "forcesslport", false, "redirect given http port number to TLS", nil)
// license state
log.Info(Product.License.Status())
} }
var testHost string // used during automated testing var testHost string // used during automated testing

View file

@ -12,6 +12,7 @@
package core package core
import "fmt" import "fmt"
import "time"
// ProdInfo describes a product // ProdInfo describes a product
type ProdInfo struct { type ProdInfo struct {
@ -21,6 +22,7 @@ type ProdInfo struct {
Major string Major string
Minor string Minor string
Patch string Patch string
License License
} }
// Product returns product edition details // Product returns product edition details
@ -31,6 +33,54 @@ func Product() (p ProdInfo) {
p.Version = fmt.Sprintf("%s.%s.%s", p.Major, p.Minor, p.Patch) p.Version = fmt.Sprintf("%s.%s.%s", p.Major, p.Minor, p.Patch)
p.Edition = "Community" p.Edition = "Community"
p.Title = fmt.Sprintf("%s Edition", p.Edition) p.Title = fmt.Sprintf("%s Edition", p.Edition)
p.License = License{}
return p return
}
// License holds details of product license.
type License struct {
Name string `json:"name"`
Email string `json:"email"`
Edition string `json:"edition"`
Start time.Time `json:"start"`
End time.Time `json:"end"`
Seats int `json:"seats"`
Trial bool `json:"trial"`
}
// IsEmpty determines if we have a license.
func (l *License) IsEmpty() bool {
return l.Seats == 0 && len(l.Name) == 0 && len(l.Email) == 0 && l.Start.Year() == 1 && l.End.Year() == 1
}
// IsValid determines if we have populated and valid license.
// An empty license is valid.
func (l *License) IsValid() bool {
if l.IsEmpty() {
return true
}
now := time.Now().UTC()
return l.End.Day() <= now.Day() && l.End.Month() <= now.Month() && l.End.Year() <= now.Year()
}
// Status returns formatted message stating if license is empty/populated and invalid/valid.
func (l *License) Status() string {
lp := "populated"
if l.IsEmpty() {
lp = "empty"
}
lv := "invalid"
if l.IsValid() {
lv = "valid"
}
return fmt.Sprintf("License is %s and %s", lp, lv)
}
// LicenseData holds encrypted data and is unpacked into License.
type LicenseData struct {
Key string `json:"key"`
Signature string `json:"signature"`
} }