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/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/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/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/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 2a37875a..64bdb24c 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..26a42073 100644
--- a/app/app/templates/components/global-settings.hbs
+++ b/app/app/templates/components/global-settings.hbs
@@ -1,32 +1,48 @@
+
+
+
+
+
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/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/global_endpoint.go b/core/api/endpoint/global_endpoint.go
index 2f397ba6..79561fc2 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,98 @@ 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.Marshal(x)
+ if err != nil {
+ fmt.Printf("error: %v\n", err)
+ }
+
+ w.WriteHeader(http.StatusOK)
+ w.Write(output)
+}
+
+// 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/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 6cec5a05..61b34572 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,13 @@ 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
+ 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/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/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 7684cb1b..0387940a 100644
--- a/core/api/endpoint/server.go
+++ b/core/api/endpoint/server.go
@@ -33,11 +33,21 @@ var port, certFile, keyFile, forcePort2SSL string
var Product core.ProdInfo
func init() {
- Product = core.Product()
+ Product.Major = "0"
+ Product.Minor = "43"
+ 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)
+
+ log.Info("Server.Init complete")
}
var testHost string // used during automated testing
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)
+}
diff --git a/core/product.go b/core/product.go
index 287e6247..dcc653e9 100644
--- a/core/product.go
+++ b/core/product.go
@@ -11,7 +11,10 @@
package core
-import "fmt"
+import (
+ "fmt"
+ "time"
+)
// ProdInfo describes a product
type ProdInfo struct {
@@ -21,16 +24,42 @@ type ProdInfo struct {
Major string
Minor string
Patch string
+ 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)
-
- return p
+// 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"`
+ Valid bool
+}
+
+// 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
+}
+
+// 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.Valid {
+ 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"`
}