From 3f87401d490e0a94dcb0e8bee49a4fa57d93af66 Mon Sep 17 00:00:00 2001 From: Harvey Kandola Date: Wed, 22 Feb 2017 20:03:40 -0800 Subject: [PATCH 1/3] support for license keys --- app/app/components/global-settings.js | 19 ++- app/app/pods/customize/global/controller.js | 12 +- app/app/pods/customize/global/route.js | 3 +- app/app/pods/customize/global/template.hbs | 2 +- app/app/services/global.js | 35 ++++- .../templates/components/global-settings.hbs | 32 +++-- core/api/endpoint/global_endpoint.go | 123 +++++++++++++++++- core/api/endpoint/router.go | 6 +- core/api/endpoint/server.go | 3 + core/product.go | 52 +++++++- 10 files changed, 252 insertions(+), 35 deletions(-) diff --git a/app/app/components/global-settings.js b/app/app/components/global-settings.js index 405d4ced..cadea72f 100644 --- a/app/app/components/global-settings.js +++ b/app/app/components/global-settings.js @@ -16,14 +16,14 @@ const { } = Ember; export default Ember.Component.extend({ - SMTPHostEmptyError: computed.empty('model.global.host'), - SMTPPortEmptyError: computed.empty('model.global.port'), - SMTPSenderEmptyError: computed.empty('model.global.sender'), - SMTPUserIdEmptyError: computed.empty('model.global.userid'), - SMTPPasswordEmptyError: computed.empty('model.global.password'), + SMTPHostEmptyError: computed.empty('model.smtp.host'), + SMTPPortEmptyError: computed.empty('model.smtp.port'), + SMTPSenderEmptyError: computed.empty('model.smtp.sender'), + SMTPUserIdEmptyError: computed.empty('model.smtp.userid'), + SMTPPasswordEmptyError: computed.empty('model.smtp.password'), actions: { - save() { + saveSMTP() { if (this.get('SMTPHostEmptyError')) { $("#smtp-host").focus(); return; @@ -45,7 +45,12 @@ export default Ember.Component.extend({ return; } - this.get('save')().then(() => { + this.get('saveSMTP')().then(() => { + }); + }, + + saveLicense() { + this.get('saveLicense')().then(() => { }); } } diff --git a/app/app/pods/customize/global/controller.js b/app/app/pods/customize/global/controller.js index 499377a2..e94bfb61 100644 --- a/app/app/pods/customize/global/controller.js +++ b/app/app/pods/customize/global/controller.js @@ -16,9 +16,17 @@ export default Ember.Controller.extend(NotifierMixin, { global: Ember.inject.service(), actions: { - save() { + saveSMTP() { 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'); }); } diff --git a/app/app/pods/customize/global/route.js b/app/app/pods/customize/global/route.js index 57701fc0..396dce26 100644 --- a/app/app/pods/customize/global/route.js +++ b/app/app/pods/customize/global/route.js @@ -26,7 +26,8 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, { model() { return RSVP.hash({ - global: this.get('global').getConfig() + smtp: this.get('global').getSMTPConfig(), + license: this.get('global').getLicense() }); }, diff --git a/app/app/pods/customize/global/template.hbs b/app/app/pods/customize/global/template.hbs index bdf3d052..0ea61f38 100644 --- a/app/app/pods/customize/global/template.hbs +++ b/app/app/pods/customize/global/template.hbs @@ -1 +1 @@ -{{global-settings model=model save=(action 'save')}} +{{global-settings model=model saveSMTP=(action 'saveSMTP') saveLicense=(action 'saveLicense')}} diff --git a/app/app/services/global.js b/app/app/services/global.js index 2a37875a..830690cc 100644 --- a/app/app/services/global.js +++ b/app/app/services/global.js @@ -21,10 +21,10 @@ export default Ember.Service.extend({ appMeta: service(), store: service(), - // Returns global configuration. - getConfig() { + // Returns SMTP configuration. + getSMTPConfig() { if(this.get('sessionService.isGlobalAdmin')) { - return this.get('ajax').request(`global`, { + return this.get('ajax').request(`global/smtp`, { method: 'GET' }).then((response) => { return response; @@ -32,13 +32,36 @@ export default Ember.Service.extend({ } }, - // Saves global configuration. - saveConfig(config) { + // Saves SMTP configuration. + saveSMTPConfig(config) { if(this.get('sessionService.isGlobalAdmin')) { - return this.get('ajax').request(`global`, { + return this.get('ajax').request(`global/smtp`, { method: 'PUT', 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 + }); + } } }); diff --git a/app/app/templates/components/global-settings.hbs b/app/app/templates/components/global-settings.hbs index 06375426..28146c08 100644 --- a/app/app/templates/components/global-settings.hbs +++ b/app/app/templates/components/global-settings.hbs @@ -1,32 +1,48 @@
-
Global Settings
-
Settings applicable for all tenants
+
Mail Server Settings
+
Used for sending email notifications
e.g. my.host.com
- {{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')}}
e.g. 587
- {{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')}}
e.g. noreply@documize.com
- {{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')}}
Your credentials
- {{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')}}
Your credentials
- {{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')}}
-
save
+
save
+
+ +
+
+ +
+
+
Edition License
+
Product license
+
+
+ +
Please provide valid XML
+ {{textarea value=model.license rows="5"}} +
+
save
diff --git a/core/api/endpoint/global_endpoint.go b/core/api/endpoint/global_endpoint.go index 2f397ba6..94bcae17 100644 --- a/core/api/endpoint/global_endpoint.go +++ b/core/api/endpoint/global_endpoint.go @@ -16,13 +16,15 @@ import ( "io/ioutil" "net/http" + "encoding/xml" + "fmt" "github.com/documize/community/core/api/request" "github.com/documize/community/core/api/util" ) -// GetGlobalConfig returns installation-wide settings -func GetGlobalConfig(w http.ResponseWriter, r *http.Request) { - method := "GetGlobalConfig" +// GetSMTPConfig returns installation-wide SMTP settings +func GetSMTPConfig(w http.ResponseWriter, r *http.Request) { + method := "GetSMTPConfig" p := request.GetPersister(r) if !p.Context.Global { @@ -39,16 +41,16 @@ func GetGlobalConfig(w http.ResponseWriter, r *http.Request) { json, err := json.Marshal(y) if err != nil { - writeJSONMarshalError(w, method, "GetGlobalConfig", err) + writeJSONMarshalError(w, method, "SMTP", err) return } util.WriteSuccessBytes(w, json) } -// SaveGlobalConfig persists global configuration. -func SaveGlobalConfig(w http.ResponseWriter, r *http.Request) { - method := "SaveGlobalConfig" +// SaveSMTPConfig persists global SMTP configuration. +func SaveSMTPConfig(w http.ResponseWriter, r *http.Request) { + method := "SaveSMTPConfig" p := request.GetPersister(r) if !p.Context.Global { @@ -79,3 +81,110 @@ func SaveGlobalConfig(w http.ResponseWriter, r *http.Request) { 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"` +} + +/* + + some key + some signature + +*/ diff --git a/core/api/endpoint/router.go b/core/api/endpoint/router.go index cb756b34..ed178d12 100644 --- a/core/api/endpoint/router.go +++ b/core/api/endpoint/router.go @@ -229,8 +229,10 @@ func init() { log.IfErr(Add(RoutePrefixPrivate, "documents/{documentID}/links", []string{"GET", "OPTIONS"}, nil, GetDocumentLinks)) // Global installation-wide config - log.IfErr(Add(RoutePrefixPrivate, "global", []string{"GET", "OPTIONS"}, nil, GetGlobalConfig)) - log.IfErr(Add(RoutePrefixPrivate, "global", []string{"PUT", "OPTIONS"}, nil, SaveGlobalConfig)) + log.IfErr(Add(RoutePrefixPrivate, "global/smtp", []string{"GET", "OPTIONS"}, nil, GetSMTPConfig)) + 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 log.IfErr(Add(RoutePrefixPrivate, "pin/{userID}", []string{"POST", "OPTIONS"}, nil, AddPin)) diff --git a/core/api/endpoint/server.go b/core/api/endpoint/server.go index 7684cb1b..ec5ceedb 100644 --- a/core/api/endpoint/server.go +++ b/core/api/endpoint/server.go @@ -38,6 +38,9 @@ func init() { 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(&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 diff --git a/core/product.go b/core/product.go index 287e6247..cee134aa 100644 --- a/core/product.go +++ b/core/product.go @@ -12,6 +12,7 @@ package core import "fmt" +import "time" // ProdInfo describes a product type ProdInfo struct { @@ -21,6 +22,7 @@ type ProdInfo struct { Major string Minor string Patch string + License License } // 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.Edition = "Community" 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"` } From edccb39019d1b323bd236b1af0b6288de8f9e16f Mon Sep 17 00:00:00 2001 From: Harvey Kandola Date: Thu, 23 Feb 2017 10:29:51 -0800 Subject: [PATCH 2/3] license code refactoring --- .../templates/components/global-settings.hbs | 8 ++--- cmd/documize-community/documize.go | 3 +- core/api/endpoint/meta_endpoint.go | 5 +-- core/api/endpoint/server.go | 13 ++++++-- core/product.go | 33 ++++--------------- 5 files changed, 22 insertions(+), 40 deletions(-) diff --git a/app/app/templates/components/global-settings.hbs b/app/app/templates/components/global-settings.hbs index 28146c08..5f80caea 100644 --- a/app/app/templates/components/global-settings.hbs +++ b/app/app/templates/components/global-settings.hbs @@ -36,12 +36,12 @@
-
Edition License
-
Product license
+
Optional Edition License
+
Only applies to Enterprise Edition
- -
Please provide valid XML
+ +
XML format accepted
{{textarea value=model.license rows="5"}}
save
diff --git a/cmd/documize-community/documize.go b/cmd/documize-community/documize.go index 79390d9b..0379f1bc 100644 --- a/cmd/documize-community/documize.go +++ b/cmd/documize-community/documize.go @@ -18,8 +18,7 @@ import ( "github.com/documize/community/core/section" _ "github.com/documize/community/embed" // the compressed front-end code and static data - - _ "github.com/go-sql-driver/mysql" // the mysql driver is required behind the scenes + _ "github.com/go-sql-driver/mysql" // the mysql driver is required behind the scenes ) func main() { diff --git a/core/api/endpoint/meta_endpoint.go b/core/api/endpoint/meta_endpoint.go index 6cec5a05..b22d421d 100644 --- a/core/api/endpoint/meta_endpoint.go +++ b/core/api/endpoint/meta_endpoint.go @@ -18,7 +18,6 @@ import ( "net/http" "text/template" - "github.com/documize/community/core" "github.com/documize/community/core/api/entity" "github.com/documize/community/core/api/request" "github.com/documize/community/core/log" @@ -41,13 +40,11 @@ func GetMeta(w http.ResponseWriter, r *http.Request) { return } - product := core.Product() - data.OrgID = org.RefID data.Title = org.Title data.Message = org.Message data.AllowAnonymousAccess = org.AllowAnonymousAccess - data.Version = product.Version + data.Version = Product.Version json, err := json.Marshal(data) diff --git a/core/api/endpoint/server.go b/core/api/endpoint/server.go index ec5ceedb..04b528fb 100644 --- a/core/api/endpoint/server.go +++ b/core/api/endpoint/server.go @@ -33,14 +33,21 @@ var port, certFile, keyFile, forcePort2SSL string var Product core.ProdInfo func init() { - Product = core.Product() + Product.Major = "0" + Product.Minor = "42" + Product.Patch = "0" + Product.Version = fmt.Sprintf("%s.%s.%s", Product.Major, Product.Minor, Product.Patch) + Product.Edition = "Community" + Product.Title = fmt.Sprintf("%s Edition", Product.Edition) + Product.License = core.License{} + Product.License.Valid = true + environment.GetString(&certFile, "cert", false, "the cert.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(&forcePort2SSL, "forcesslport", false, "redirect given http port number to TLS", nil) - // license state - log.Info(Product.License.Status()) + log.Info("Server.Init complete") } var testHost string // used during automated testing diff --git a/core/product.go b/core/product.go index cee134aa..dcc653e9 100644 --- a/core/product.go +++ b/core/product.go @@ -11,8 +11,10 @@ package core -import "fmt" -import "time" +import ( + "fmt" + "time" +) // ProdInfo describes a product type ProdInfo struct { @@ -25,19 +27,6 @@ type ProdInfo struct { License License } -// Product returns product edition details -func Product() (p ProdInfo) { - p.Major = "0" - p.Minor = "42" - p.Patch = "0" - p.Version = fmt.Sprintf("%s.%s.%s", p.Major, p.Minor, p.Patch) - p.Edition = "Community" - p.Title = fmt.Sprintf("%s Edition", p.Edition) - p.License = License{} - - return -} - // License holds details of product license. type License struct { Name string `json:"name"` @@ -47,6 +36,7 @@ type License struct { End time.Time `json:"end"` Seats int `json:"seats"` Trial bool `json:"trial"` + Valid bool } // IsEmpty determines if we have a license. @@ -54,17 +44,6 @@ 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" @@ -72,7 +51,7 @@ func (l *License) Status() string { lp = "empty" } lv := "invalid" - if l.IsValid() { + if l.Valid { lv = "valid" } From a4e3264e0cb8b45663ce52393e45f0dfc7c5116d Mon Sep 17 00:00:00 2001 From: Harvey Kandola Date: Thu, 23 Feb 2017 16:39:23 -0800 Subject: [PATCH 3/3] implemented edition license checks --- README.md | 2 +- app/app/components/layout/zone-content.js | 14 +++++- app/app/services/app-meta.js | 6 +++ app/app/services/global.js | 2 +- .../templates/components/global-settings.hbs | 2 +- app/app/utils/net.js | 13 ++++++ app/package.json | 2 +- core/api/endpoint/global_endpoint.go | 14 +----- core/api/endpoint/init.go | 5 +++ core/api/endpoint/label_endpoint.go | 10 +++++ core/api/endpoint/meta_endpoint.go | 2 + core/api/endpoint/page_endpoint.go | 45 +++++++++++++++++++ core/api/endpoint/pin_endpoint.go | 15 +++++++ core/api/endpoint/sections_endpoint.go | 5 +++ core/api/endpoint/server.go | 2 +- core/api/endpoint/templates_endpoint.go | 5 +++ core/api/endpoint/user_endpoint.go | 5 +++ core/api/entity/objects.go | 2 + core/api/util/writeHTTP.go | 14 ++++++ 19 files changed, 146 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 61876f67..4a083b4b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ The mission is to bring software dev inspired features (refactoring, testing, li ## Latest version -v0.42.0 +v0.43.0 ## OS Support diff --git a/app/app/components/layout/zone-content.js b/app/app/components/layout/zone-content.js index cb25c125..f8f457d6 100644 --- a/app/app/components/layout/zone-content.js +++ b/app/app/components/layout/zone-content.js @@ -10,6 +10,18 @@ // https://documize.com import Ember from 'ember'; +import NotifierMixin from '../../mixins/notifier'; -export default Ember.Component.extend({ +const { + inject: { service } +} = Ember; + +export default Ember.Component.extend(NotifierMixin, { + appMeta :service(), + + didRender() { + if (this.get('appMeta').invalidLicense()) { + this.showNotification(`!! Expired or invalid license !!`); + } + } }); diff --git a/app/app/services/app-meta.js b/app/app/services/app-meta.js index 1c8dae9a..1ebf3705 100644 --- a/app/app/services/app-meta.js +++ b/app/app/services/app-meta.js @@ -27,9 +27,15 @@ export default Ember.Service.extend({ title: '', version: '', message: '', + edition: 'Community', + valid: true, allowAnonymousAccess: false, setupMode: false, + invalidLicense() { + return this.valid === false; + }, + getBaseUrl(endpoint) { return [this.get('endpoint'), endpoint].join('/'); }, diff --git a/app/app/services/global.js b/app/app/services/global.js index 830690cc..64bdb24c 100644 --- a/app/app/services/global.js +++ b/app/app/services/global.js @@ -54,7 +54,7 @@ export default Ember.Service.extend({ } }, - // Saves product license + // Saves product license. saveLicense(license) { if(this.get('sessionService.isGlobalAdmin')) { return this.get('ajax').request(`global/license`, { diff --git a/app/app/templates/components/global-settings.hbs b/app/app/templates/components/global-settings.hbs index 5f80caea..26a42073 100644 --- a/app/app/templates/components/global-settings.hbs +++ b/app/app/templates/components/global-settings.hbs @@ -42,7 +42,7 @@
XML format accepted
- {{textarea value=model.license rows="5"}} + {{textarea value=model.license rows="15"}}
save
diff --git a/app/app/utils/net.js b/app/app/utils/net.js index afceec75..8bac8ccf 100644 --- a/app/app/utils/net.js +++ b/app/app/utils/net.js @@ -63,9 +63,22 @@ function isAjaxNotFoundError(reason) { return false; } +function isInvalidLicenseError(reason) { + if (typeof reason === "undefined" || typeof reason.errors === "undefined") { + return false; + } + + if (reason.errors.length > 0 && reason.errors[0].status === "402") { + return true; + } + + return false; +} + export default { getSubdomain, getAppUrl, isAjaxAccessError, isAjaxNotFoundError, + isInvalidLicenseError, }; diff --git a/app/package.json b/app/package.json index 2e0fba82..937279f5 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "documize", - "version": "0.42.0", + "version": "0.43.0", "description": "The Document IDE", "private": true, "repository": "", diff --git a/core/api/endpoint/global_endpoint.go b/core/api/endpoint/global_endpoint.go index 94bcae17..79561fc2 100644 --- a/core/api/endpoint/global_endpoint.go +++ b/core/api/endpoint/global_endpoint.go @@ -109,25 +109,13 @@ func GetLicense(w http.ResponseWriter, r *http.Request) { fmt.Println(err) } - output, err := xml.MarshalIndent(x, " ", " ") + output, err := xml.Marshal(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 diff --git a/core/api/endpoint/init.go b/core/api/endpoint/init.go index 9c564ad3..98cf53a0 100644 --- a/core/api/endpoint/init.go +++ b/core/api/endpoint/init.go @@ -41,6 +41,11 @@ func writeTransactionError(w http.ResponseWriter, method string, err error) { log.Error(fmt.Sprintf("Unable to get database transaction for method %s", method), err) } +// IsInvalidLicense returns true if license is invalid +func IsInvalidLicense() bool { + return Product.License.Valid == false +} + /* func WriteAddRecordError(w http.ResponseWriter, method string, err error) { w.Header().Set("Content-Type", "application/json; charset=utf-8") diff --git a/core/api/endpoint/label_endpoint.go b/core/api/endpoint/label_endpoint.go index 4d80962d..18a7cf69 100644 --- a/core/api/endpoint/label_endpoint.go +++ b/core/api/endpoint/label_endpoint.go @@ -32,6 +32,11 @@ import ( // AddFolder creates a new folder. func AddFolder(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "AddFolder" p := request.GetPersister(r) @@ -263,6 +268,11 @@ func UpdateFolder(w http.ResponseWriter, r *http.Request) { // RemoveFolder moves documents to another folder before deleting it func RemoveFolder(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "RemoveFolder" p := request.GetPersister(r) diff --git a/core/api/endpoint/meta_endpoint.go b/core/api/endpoint/meta_endpoint.go index b22d421d..61b34572 100644 --- a/core/api/endpoint/meta_endpoint.go +++ b/core/api/endpoint/meta_endpoint.go @@ -45,6 +45,8 @@ func GetMeta(w http.ResponseWriter, r *http.Request) { data.Message = org.Message data.AllowAnonymousAccess = org.AllowAnonymousAccess data.Version = Product.Version + data.Edition = Product.License.Edition + data.Valid = Product.License.Valid json, err := json.Marshal(data) diff --git a/core/api/endpoint/page_endpoint.go b/core/api/endpoint/page_endpoint.go index c606c966..27d89bdc 100644 --- a/core/api/endpoint/page_endpoint.go +++ b/core/api/endpoint/page_endpoint.go @@ -33,6 +33,11 @@ import ( // AddDocumentPage inserts new section into document. func AddDocumentPage(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "AddDocumentPage" p := request.GetPersister(r) @@ -286,6 +291,11 @@ func GetDocumentPagesBatch(w http.ResponseWriter, r *http.Request) { // DeleteDocumentPage deletes a page. func DeleteDocumentPage(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "DeleteDocumentPage" p := request.GetPersister(r) @@ -354,6 +364,11 @@ func DeleteDocumentPage(w http.ResponseWriter, r *http.Request) { // DeleteDocumentPages batch deletes pages. func DeleteDocumentPages(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "DeleteDocumentPages" p := request.GetPersister(r) @@ -433,6 +448,11 @@ func DeleteDocumentPages(w http.ResponseWriter, r *http.Request) { // that this is a new revision. If the page is the first in a document // then the corresponding document title will also be changed. func UpdateDocumentPage(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "UpdateDocumentPage" p := request.GetPersister(r) params := mux.Vars(r) @@ -540,6 +560,11 @@ func UpdateDocumentPage(w http.ResponseWriter, r *http.Request) { // ChangeDocumentPageSequence will swap page sequence for a given number of pages. func ChangeDocumentPageSequence(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "ChangeDocumentPageSequence" p := request.GetPersister(r) @@ -598,6 +623,11 @@ func ChangeDocumentPageSequence(w http.ResponseWriter, r *http.Request) { // ChangeDocumentPageLevel handles page indent/outdent changes. func ChangeDocumentPageLevel(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "ChangeDocumentPageLevel" p := request.GetPersister(r) @@ -740,6 +770,11 @@ func GetPageMoveCopyTargets(w http.ResponseWriter, r *http.Request) { // GetDocumentRevisions returns all changes for a document. func GetDocumentRevisions(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "GetDocumentPageRevisions" p := request.GetPersister(r) @@ -770,6 +805,11 @@ func GetDocumentRevisions(w http.ResponseWriter, r *http.Request) { // GetDocumentPageRevisions returns all changes for a given page. func GetDocumentPageRevisions(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "GetDocumentPageRevisions" p := request.GetPersister(r) @@ -807,6 +847,11 @@ func GetDocumentPageRevisions(w http.ResponseWriter, r *http.Request) { // GetDocumentPageDiff returns HTML diff between two revisions of a given page. func GetDocumentPageDiff(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "GetDocumentPageDiff" p := request.GetPersister(r) diff --git a/core/api/endpoint/pin_endpoint.go b/core/api/endpoint/pin_endpoint.go index 04f1d1c7..be682241 100644 --- a/core/api/endpoint/pin_endpoint.go +++ b/core/api/endpoint/pin_endpoint.go @@ -28,6 +28,11 @@ import ( // AddPin saves pinned item. func AddPin(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "AddPin" p := request.GetPersister(r) params := mux.Vars(r) @@ -131,6 +136,11 @@ func GetUserPins(w http.ResponseWriter, r *http.Request) { // DeleteUserPin removes saved user pin. func DeleteUserPin(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "DeleteUserPin" p := request.GetPersister(r) params := mux.Vars(r) @@ -175,6 +185,11 @@ func DeleteUserPin(w http.ResponseWriter, r *http.Request) { // UpdatePinSequence records order of pinned items. func UpdatePinSequence(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "UpdatePinSequence" p := request.GetPersister(r) params := mux.Vars(r) diff --git a/core/api/endpoint/sections_endpoint.go b/core/api/endpoint/sections_endpoint.go index f297d815..eaaf8045 100644 --- a/core/api/endpoint/sections_endpoint.go +++ b/core/api/endpoint/sections_endpoint.go @@ -185,6 +185,11 @@ func RefreshSections(w http.ResponseWriter, r *http.Request) { // AddBlock inserts new reusable content block into database. func AddBlock(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "AddBlock" p := request.GetPersister(r) diff --git a/core/api/endpoint/server.go b/core/api/endpoint/server.go index 04b528fb..0387940a 100644 --- a/core/api/endpoint/server.go +++ b/core/api/endpoint/server.go @@ -34,7 +34,7 @@ var Product core.ProdInfo func init() { Product.Major = "0" - Product.Minor = "42" + Product.Minor = "43" Product.Patch = "0" Product.Version = fmt.Sprintf("%s.%s.%s", Product.Major, Product.Minor, Product.Patch) Product.Edition = "Community" diff --git a/core/api/endpoint/templates_endpoint.go b/core/api/endpoint/templates_endpoint.go index 972fbdab..3f12455d 100644 --- a/core/api/endpoint/templates_endpoint.go +++ b/core/api/endpoint/templates_endpoint.go @@ -36,6 +36,11 @@ import ( // SaveAsTemplate saves existing document as a template. func SaveAsTemplate(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "SaveAsTemplate" p := request.GetPersister(r) diff --git a/core/api/endpoint/user_endpoint.go b/core/api/endpoint/user_endpoint.go index 5ababd20..120456d6 100644 --- a/core/api/endpoint/user_endpoint.go +++ b/core/api/endpoint/user_endpoint.go @@ -33,6 +33,11 @@ import ( // AddUser is the endpoint that enables an administrator to add a new user for their orgaisation. func AddUser(w http.ResponseWriter, r *http.Request) { + if IsInvalidLicense() { + util.WriteBadLicense(w) + return + } + method := "AddUser" p := request.GetPersister(r) diff --git a/core/api/entity/objects.go b/core/api/entity/objects.go index e5ffda5c..2e4b4014 100644 --- a/core/api/entity/objects.go +++ b/core/api/entity/objects.go @@ -341,6 +341,8 @@ type SiteMeta struct { URL string `json:"url"` AllowAnonymousAccess bool `json:"allowAnonymousAccess"` Version string `json:"version"` + Edition string `json:"edition"` + Valid bool `json:"valid"` } // Template is used to create a new document. diff --git a/core/api/util/writeHTTP.go b/core/api/util/writeHTTP.go index 68c50ed3..d0a21869 100644 --- a/core/api/util/writeHTTP.go +++ b/core/api/util/writeHTTP.go @@ -164,3 +164,17 @@ func WriteJSON(w http.ResponseWriter, v interface{}) { _, err = w.Write(j) log.IfErr(err) } + +// WriteBadLicense writes 402 when license is invalid +func WriteBadLicense(w http.ResponseWriter) { + w.Header().Set("Content-Type", "application/json; charset=utf-8") + w.WriteHeader(http.StatusPaymentRequired) + var e struct { + Reason string + } + e.Reason = "invalid or expired Documize license" + + j, _ := json.Marshal(e) + _, err := w.Write(j) + log.IfErr(err) +}