mirror of
https://github.com/documize/community.git
synced 2025-07-19 21:29:42 +02:00
Subscription checks
This commit is contained in:
parent
6e4c5194e2
commit
e116d3b000
20 changed files with 211 additions and 76 deletions
122
core/env/product.go
vendored
122
core/env/product.go
vendored
|
@ -16,9 +16,71 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProdInfo describes a product
|
// Edition is either Community or Enterprise.
|
||||||
type ProdInfo struct {
|
type Edition string
|
||||||
Edition string
|
|
||||||
|
// Package controls feature-set within edition.
|
||||||
|
type Package string
|
||||||
|
|
||||||
|
// Plan tells us if instance if self-hosted or Documize SaaS/Cloud.
|
||||||
|
type Plan string
|
||||||
|
|
||||||
|
// Seats represents number of users.
|
||||||
|
type Seats int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// CommunityEdition is AGPL licensed open core of product.
|
||||||
|
CommunityEdition Edition = "Community"
|
||||||
|
|
||||||
|
// EnterpriseEdition is proprietary closed-source product.
|
||||||
|
EnterpriseEdition Edition = "Enterprise"
|
||||||
|
|
||||||
|
// PackageEssentials provides core capabilities.
|
||||||
|
PackageEssentials Package = "Essentials"
|
||||||
|
|
||||||
|
// PackageAdvanced provides analytics, reporting,
|
||||||
|
// content lifecycle, content verisoning, and audit logs.
|
||||||
|
PackageAdvanced Package = "Advanced"
|
||||||
|
|
||||||
|
// PackagePremium provides actions, feedback capture,
|
||||||
|
// approvals workflow, secure external sharing.
|
||||||
|
PackagePremium Package = "Premium"
|
||||||
|
|
||||||
|
// PackageDataCenter provides multi-tenanting
|
||||||
|
// and a bunch of professional services.
|
||||||
|
PackageDataCenter Package = "Data Center"
|
||||||
|
|
||||||
|
// PlanCloud represents *.documize.com hosting.
|
||||||
|
PlanCloud Plan = "Cloud"
|
||||||
|
|
||||||
|
// PlanSelfHost represents privately hosted Documize instance.
|
||||||
|
PlanSelfHost Plan = "Self-host"
|
||||||
|
|
||||||
|
// Seats0 is 0 users.
|
||||||
|
Seats0 Seats = 0
|
||||||
|
|
||||||
|
// Seats1 is 10 users.
|
||||||
|
Seats1 Seats = 10
|
||||||
|
|
||||||
|
// Seats2 is 25 users.
|
||||||
|
Seats2 Seats = 25
|
||||||
|
|
||||||
|
//Seats3 is 50 users.
|
||||||
|
Seats3 Seats = 50
|
||||||
|
|
||||||
|
// Seats4 is 100 users.
|
||||||
|
Seats4 Seats = 100
|
||||||
|
|
||||||
|
//Seats5 is 250 users.
|
||||||
|
Seats5 Seats = 250
|
||||||
|
|
||||||
|
// Seats6 is unlimited.
|
||||||
|
Seats6 Seats = 9999
|
||||||
|
)
|
||||||
|
|
||||||
|
// Product provides meta information about product and licensing.
|
||||||
|
type Product struct {
|
||||||
|
Edition Edition
|
||||||
Title string
|
Title string
|
||||||
Version string
|
Version string
|
||||||
Major string
|
Major string
|
||||||
|
@ -28,42 +90,66 @@ type ProdInfo struct {
|
||||||
License License
|
License License
|
||||||
}
|
}
|
||||||
|
|
||||||
// License holds details of product license.
|
// License provides details of product license.
|
||||||
type License struct {
|
type License struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Edition string `json:"edition"`
|
Edition Edition `json:"edition"`
|
||||||
Package string `json:"package"`
|
Package Package `json:"package"`
|
||||||
Plan string `json:"plan"`
|
Plan Plan `json:"plan"`
|
||||||
Start time.Time `json:"start"`
|
Start time.Time `json:"start"`
|
||||||
End time.Time `json:"end"`
|
End time.Time `json:"end"`
|
||||||
Seats int `json:"seats"`
|
Seats Seats `json:"seats"`
|
||||||
Trial bool `json:"trial"`
|
Trial bool `json:"trial"`
|
||||||
Valid bool `json:"valid"`
|
|
||||||
|
// UserCount is number of users within Documize instance by tenant.
|
||||||
|
// Provided at runtime.
|
||||||
|
UserCount map[string]int
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmpty determines if we have a license.
|
// IsEmpty determines if we have a license.
|
||||||
func (l *License) IsEmpty() bool {
|
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
|
return l.Seats == Seats0 &&
|
||||||
|
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.
|
// Status returns formatted message stating if license is empty/populated and invalid/valid.
|
||||||
func (l *License) Status() string {
|
func (l *License) Status(orgID string) string {
|
||||||
lp := "populated"
|
lp := "populated"
|
||||||
if l.IsEmpty() {
|
if l.IsEmpty() {
|
||||||
lp = "empty"
|
lp = "empty"
|
||||||
}
|
}
|
||||||
lv := "invalid"
|
lv := "invalid"
|
||||||
if l.Valid {
|
if l.IsValid(orgID) {
|
||||||
lv = "valid"
|
lv = "valid"
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("License is %s and %s", lp, lv)
|
return fmt.Sprintf("License is %s and %s", lp, lv)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValid returns if license is valid
|
// IsValid returns if license is valid for specified tenant.
|
||||||
func (l *License) IsValid() bool {
|
func (l *License) IsValid(orgID string) bool {
|
||||||
return l.Valid == true
|
valid := false
|
||||||
|
|
||||||
|
// Community edition is always valid.
|
||||||
|
if l.Edition == CommunityEdition {
|
||||||
|
valid = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enterprise edition is valid if subcription date is
|
||||||
|
// greater than now and we have enough users/seats.
|
||||||
|
if l.Edition == EnterpriseEdition {
|
||||||
|
if time.Now().UTC().Before(l.End) && l.UserCount[orgID] <= int(l.Seats) {
|
||||||
|
valid = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty means we cannot be valid
|
||||||
|
if l.IsEmpty() || len(l.UserCount) == 0 {
|
||||||
|
valid = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid
|
||||||
}
|
}
|
||||||
|
|
||||||
// LicenseData holds encrypted data and is unpacked into License.
|
// LicenseData holds encrypted data and is unpacked into License.
|
||||||
|
@ -71,3 +157,9 @@ type LicenseData struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Signature string `json:"signature"`
|
Signature string `json:"signature"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LicenseUserAcount states number of active users by tenant.
|
||||||
|
type LicenseUserAcount struct {
|
||||||
|
OrgID string `json:"orgId"`
|
||||||
|
Users int `json:"users"`
|
||||||
|
}
|
||||||
|
|
10
core/env/runtime.go
vendored
10
core/env/runtime.go
vendored
|
@ -23,7 +23,7 @@ type Runtime struct {
|
||||||
Db *sqlx.DB
|
Db *sqlx.DB
|
||||||
StoreProvider StoreProvider
|
StoreProvider StoreProvider
|
||||||
Log Logger
|
Log Logger
|
||||||
Product ProdInfo
|
Product Product
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -39,11 +39,3 @@ const (
|
||||||
// SiteModeBadDB redirects to db-error.html page
|
// SiteModeBadDB redirects to db-error.html page
|
||||||
SiteModeBadDB = "3"
|
SiteModeBadDB = "3"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
// CommunityEdition is AGPL product variant
|
|
||||||
CommunityEdition = "Community"
|
|
||||||
|
|
||||||
// EnterpriseEdition is commercial licensed product variant
|
|
||||||
EnterpriseEdition = "Enterprise"
|
|
||||||
)
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ func StripAuthSecrets(r *env.Runtime, provider, config string) string {
|
||||||
switch provider {
|
switch provider {
|
||||||
case auth.AuthProviderDocumize:
|
case auth.AuthProviderDocumize:
|
||||||
return config
|
return config
|
||||||
|
|
||||||
case auth.AuthProviderKeycloak:
|
case auth.AuthProviderKeycloak:
|
||||||
c := auth.KeycloakConfig{}
|
c := auth.KeycloakConfig{}
|
||||||
err := json.Unmarshal([]byte(config), &c)
|
err := json.Unmarshal([]byte(config), &c)
|
||||||
|
@ -41,6 +42,7 @@ func StripAuthSecrets(r *env.Runtime, provider, config string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(j)
|
return string(j)
|
||||||
|
|
||||||
case auth.AuthProviderLDAP:
|
case auth.AuthProviderLDAP:
|
||||||
c := auth.LDAPConfig{}
|
c := auth.LDAPConfig{}
|
||||||
err := json.Unmarshal([]byte(config), &c)
|
err := json.Unmarshal([]byte(config), &c)
|
||||||
|
|
|
@ -206,7 +206,7 @@ func (b backerHandler) produce(id string) (files []backupItem, err error) {
|
||||||
func (b backerHandler) manifest(id string) (string, error) {
|
func (b backerHandler) manifest(id string) (string, error) {
|
||||||
m := m.Manifest{
|
m := m.Manifest{
|
||||||
ID: id,
|
ID: id,
|
||||||
Edition: b.Runtime.Product.Edition,
|
Edition: b.Runtime.Product.License.Edition,
|
||||||
Version: b.Runtime.Product.Version,
|
Version: b.Runtime.Product.Version,
|
||||||
Major: b.Runtime.Product.Major,
|
Major: b.Runtime.Product.Major,
|
||||||
Minor: b.Runtime.Product.Minor,
|
Minor: b.Runtime.Product.Minor,
|
||||||
|
|
|
@ -39,7 +39,7 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "block.add"
|
method := "block.add"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ func (h *Handler) Meta(w http.ResponseWriter, r *http.Request) {
|
||||||
data.Version = h.Runtime.Product.Version
|
data.Version = h.Runtime.Product.Version
|
||||||
data.Revision = h.Runtime.Product.Revision
|
data.Revision = h.Runtime.Product.Revision
|
||||||
data.Edition = h.Runtime.Product.Edition
|
data.Edition = h.Runtime.Product.Edition
|
||||||
data.Valid = h.Runtime.Product.License.Valid
|
data.Valid = h.Runtime.Product.License.IsValid(org.RefID)
|
||||||
data.ConversionEndpoint = org.ConversionEndpoint
|
data.ConversionEndpoint = org.ConversionEndpoint
|
||||||
data.License = h.Runtime.Product.License
|
data.License = h.Runtime.Product.License
|
||||||
data.Storage = h.Runtime.StoreProvider.Type()
|
data.Storage = h.Runtime.StoreProvider.Type()
|
||||||
|
|
|
@ -52,7 +52,7 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "page.add"
|
method := "page.add"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -322,7 +322,7 @@ func (h *Handler) Update(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "page.update"
|
method := "page.update"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -510,7 +510,7 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "page.delete"
|
method := "page.delete"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -608,7 +608,7 @@ func (h *Handler) DeletePages(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "page.delete.pages"
|
method := "page.delete.pages"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -721,7 +721,7 @@ func (h *Handler) ChangePageSequence(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "page.sequence"
|
method := "page.sequence"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -791,7 +791,7 @@ func (h *Handler) ChangePageLevel(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "page.level"
|
method := "page.level"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -987,7 +987,7 @@ func (h *Handler) GetDocumentRevisions(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "page.document.revisions"
|
method := "page.document.revisions"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1018,7 +1018,7 @@ func (h *Handler) GetRevisions(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "page.revisions"
|
method := "page.revisions"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1053,7 +1053,7 @@ func (h *Handler) GetDiff(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "page.diff"
|
method := "page.diff"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ func (h *Handler) DeleteUserPin(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ func (h *Handler) UpdatePinSequence(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "space.add"
|
method := "space.add"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -582,7 +582,7 @@ func (h *Handler) Remove(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "space.remove"
|
method := "space.remove"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -675,7 +675,7 @@ func (h *Handler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "space.delete"
|
method := "space.delete"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
package store
|
package store
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/documize/community/core/env"
|
||||||
"github.com/documize/community/domain"
|
"github.com/documize/community/domain"
|
||||||
"github.com/documize/community/model/account"
|
"github.com/documize/community/model/account"
|
||||||
"github.com/documize/community/model/activity"
|
"github.com/documize/community/model/activity"
|
||||||
|
@ -122,7 +123,7 @@ type UserStorer interface {
|
||||||
UpdateUserPassword(ctx domain.RequestContext, userID, salt, password string) (err error)
|
UpdateUserPassword(ctx domain.RequestContext, userID, salt, password string) (err error)
|
||||||
DeactiveUser(ctx domain.RequestContext, userID string) (err error)
|
DeactiveUser(ctx domain.RequestContext, userID string) (err error)
|
||||||
ForgotUserPassword(ctx domain.RequestContext, email, token string) (err error)
|
ForgotUserPassword(ctx domain.RequestContext, email, token string) (err error)
|
||||||
CountActiveUsers() (c int)
|
CountActiveUsers() (c []env.LicenseUserAcount)
|
||||||
MatchUsers(ctx domain.RequestContext, text string, maxMatches int) (u []user.User, err error)
|
MatchUsers(ctx domain.RequestContext, text string, maxMatches int) (u []user.User, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ func (h *Handler) SaveAs(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "template.saved"
|
method := "template.saved"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/documize/community/domain/store"
|
||||||
|
|
||||||
"github.com/documize/community/core/env"
|
"github.com/documize/community/core/env"
|
||||||
"github.com/documize/community/domain"
|
"github.com/documize/community/domain"
|
||||||
|
@ -13,20 +14,21 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetupTest prepares test environment
|
// SetupTest prepares test environment
|
||||||
func SetupTest() (rt *env.Runtime, s *domain.Store, ctx domain.RequestContext) {
|
func SetupTest() (rt *env.Runtime, s *store
|
||||||
|
.Store, ctx domain.RequestContext) {
|
||||||
rt, s = startRuntime()
|
rt, s = startRuntime()
|
||||||
ctx = setupContext()
|
ctx = setupContext()
|
||||||
return rt, s, ctx
|
return rt, s, ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
func startRuntime() (rt *env.Runtime, s *domain.Store) {
|
func startRuntime() (rt *env.Runtime, s *store.Store) {
|
||||||
rt = new(env.Runtime)
|
rt = new(env.Runtime)
|
||||||
s = new(domain.Store)
|
s = new(store.Store)
|
||||||
|
|
||||||
rt.Log = logging.NewLogger(false)
|
rt.Log = logging.NewLogger(false)
|
||||||
web.Embed = embed.NewEmbedder()
|
web.Embed = embed.NewEmbedder()
|
||||||
|
|
||||||
rt.Product = env.ProdInfo{}
|
rt.Product = env.Product{}
|
||||||
rt.Product.Major = "0"
|
rt.Product.Major = "0"
|
||||||
rt.Product.Minor = "0"
|
rt.Product.Minor = "0"
|
||||||
rt.Product.Patch = "0"
|
rt.Product.Patch = "0"
|
||||||
|
@ -35,9 +37,8 @@ func startRuntime() (rt *env.Runtime, s *domain.Store) {
|
||||||
rt.Product.Title = fmt.Sprintf("%s Edition", rt.Product.Edition)
|
rt.Product.Title = fmt.Sprintf("%s Edition", rt.Product.Edition)
|
||||||
rt.Product.License = env.License{}
|
rt.Product.License = env.License{}
|
||||||
rt.Product.License.Seats = 1
|
rt.Product.License.Seats = 1
|
||||||
rt.Product.License.Valid = true
|
|
||||||
rt.Product.License.Trial = false
|
rt.Product.License.Trial = false
|
||||||
rt.Product.License.Edition = "Community"
|
rt.Product.License.Edition = env.CommunityEdition
|
||||||
|
|
||||||
// parse settings from command line and environment
|
// parse settings from command line and environment
|
||||||
rt.Flags = env.ParseFlags()
|
rt.Flags = env.ParseFlags()
|
||||||
|
@ -56,7 +57,7 @@ func setupContext() domain.RequestContext {
|
||||||
ctx.Administrator = true
|
ctx.Administrator = true
|
||||||
ctx.Guest = false
|
ctx.Guest = false
|
||||||
ctx.Editor = true
|
ctx.Editor = true
|
||||||
ctx.Global = true
|
ctx.GlobalAdmin = true
|
||||||
ctx.UserID = "test"
|
ctx.UserID = "test"
|
||||||
ctx.OrgID = "test"
|
ctx.OrgID = "test"
|
||||||
return ctx
|
return ctx
|
||||||
|
|
|
@ -51,7 +51,7 @@ func (h *Handler) Add(w http.ResponseWriter, r *http.Request) {
|
||||||
method := "user.Add"
|
method := "user.Add"
|
||||||
ctx := domain.GetRequestContext(r)
|
ctx := domain.GetRequestContext(r)
|
||||||
|
|
||||||
if !h.Runtime.Product.License.IsValid() {
|
if !h.Runtime.Product.License.IsValid(ctx.OrgID) {
|
||||||
response.WriteBadLicense(w)
|
response.WriteBadLicense(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ package user
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/documize/community/core/env"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -312,17 +313,11 @@ func (s Store) ForgotUserPassword(ctx domain.RequestContext, email, token string
|
||||||
}
|
}
|
||||||
|
|
||||||
// CountActiveUsers returns the number of active users in the system.
|
// CountActiveUsers returns the number of active users in the system.
|
||||||
func (s Store) CountActiveUsers() (c int) {
|
func (s Store) CountActiveUsers() (c []env.LicenseUserAcount) {
|
||||||
row := s.Runtime.Db.QueryRow("SELECT count(*) FROM dmz_user WHERE c_refid IN (SELECT c_userid FROM dmz_user_account WHERE c_active=true)")
|
err := s.Runtime.Db.Select(&c, "SELECT c_orgid AS orgid, COUNT(*) AS users FROM dmz_user_account WHERE c_active=true GROUP BY c_orgid ORDER BY c_orgid")
|
||||||
|
|
||||||
err := row.Scan(&c)
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil && err != sql.ErrNoRows {
|
if err != nil && err != sql.ErrNoRows {
|
||||||
s.Runtime.Log.Error("CountActiveUsers", err)
|
s.Runtime.Log.Error("CountActiveUsers", err)
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
@ -14,6 +14,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/documize/community/core/env"
|
"github.com/documize/community/core/env"
|
||||||
"github.com/documize/community/domain/section"
|
"github.com/documize/community/domain/section"
|
||||||
|
@ -36,21 +37,20 @@ func main() {
|
||||||
web.Embed = embed.NewEmbedder()
|
web.Embed = embed.NewEmbedder()
|
||||||
|
|
||||||
// product details
|
// product details
|
||||||
rt.Product = env.ProdInfo{}
|
rt.Product = env.Product{}
|
||||||
rt.Product.Major = "1"
|
rt.Product.Major = "1"
|
||||||
rt.Product.Minor = "72"
|
rt.Product.Minor = "72"
|
||||||
rt.Product.Patch = "1"
|
rt.Product.Patch = "1"
|
||||||
rt.Product.Revision = 181022154519
|
rt.Product.Revision = 181022154519
|
||||||
rt.Product.Version = fmt.Sprintf("%s.%s.%s", rt.Product.Major, rt.Product.Minor, rt.Product.Patch)
|
rt.Product.Version = fmt.Sprintf("%s.%s.%s", rt.Product.Major, rt.Product.Minor, rt.Product.Patch)
|
||||||
rt.Product.Edition = "Community"
|
rt.Product.Edition = env.CommunityEdition
|
||||||
rt.Product.Title = fmt.Sprintf("%s Edition", rt.Product.Edition)
|
rt.Product.Title = fmt.Sprintf("%s Edition", rt.Product.Edition)
|
||||||
rt.Product.License = env.License{}
|
|
||||||
rt.Product.License.Seats = 1
|
|
||||||
rt.Product.License.Valid = true
|
|
||||||
rt.Product.License.Trial = false
|
|
||||||
rt.Product.License.Edition = "Community"
|
|
||||||
|
|
||||||
// setup store
|
// Community edition is good to go with no user limits.
|
||||||
|
rt.Product.License = env.License{Edition: env.CommunityEdition, Seats: env.Seats6, Trial: false,
|
||||||
|
Start: time.Now().UTC(), End: time.Now().UTC().Add(time.Hour * 24 * 7 * time.Duration(52))}
|
||||||
|
|
||||||
|
// Setup data store.
|
||||||
s := store.Store{}
|
s := store.Store{}
|
||||||
|
|
||||||
// parse settings from command line and environment
|
// parse settings from command line and environment
|
||||||
|
|
|
@ -141,6 +141,58 @@ let constants = EmberObject.extend({
|
||||||
MySQL: 'MySQL',
|
MySQL: 'MySQL',
|
||||||
PostgreSQL: 'PostgreSQL',
|
PostgreSQL: 'PostgreSQL',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Product is where we try to balance the fine line between useful open core
|
||||||
|
// and the revenue-generating proprietary edition.
|
||||||
|
Product: { // eslint-disable-line ember/avoid-leaking-state-in-ember-objects
|
||||||
|
// CommunityEdition is AGPL licensed open core of product.
|
||||||
|
CommunityEdition: 'Community',
|
||||||
|
|
||||||
|
// EnterpriseEdition is proprietary closed-source product.
|
||||||
|
EnterpriseEdition: 'Enterprise',
|
||||||
|
|
||||||
|
// PackageEssentials provides core capabilities.
|
||||||
|
PackageEssentials: "Essentials",
|
||||||
|
|
||||||
|
// PackageAdvanced provides analytics, reporting,
|
||||||
|
// content lifecycle, content verisoning, and audit logs.
|
||||||
|
PackageAdvanced: "Advanced",
|
||||||
|
|
||||||
|
// PackagePremium provides actions, feedback capture,
|
||||||
|
// approvals workflow, secure external sharing.
|
||||||
|
PackagePremium: "Premium",
|
||||||
|
|
||||||
|
// PackageDataCenter provides multi-tenanting
|
||||||
|
// and a bunch of professional services.
|
||||||
|
PackageDataCenter: "Data Center",
|
||||||
|
|
||||||
|
// PlanCloud represents *.documize.com hosting.
|
||||||
|
PlanCloud: "Cloud",
|
||||||
|
|
||||||
|
// PlanSelfHost represents privately hosted Documize instance.
|
||||||
|
PlanSelfHost: "Self-host",
|
||||||
|
|
||||||
|
// Seats0 is 0 users.
|
||||||
|
Seats0: 0,
|
||||||
|
|
||||||
|
// Seats1 is 10 users.
|
||||||
|
Seats1: 10,
|
||||||
|
|
||||||
|
// Seats2 is 25 users.
|
||||||
|
Seats2: 25,
|
||||||
|
|
||||||
|
//Seats3 is 50 users.
|
||||||
|
Seats3: 50,
|
||||||
|
|
||||||
|
// Seats4 is 100 users.
|
||||||
|
Seats4: 100,
|
||||||
|
|
||||||
|
//Seats5 is 250 users.
|
||||||
|
Seats5: 250,
|
||||||
|
|
||||||
|
// Seats6 is unlimited.
|
||||||
|
Seats6: 9999
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default { constants }
|
export default { constants }
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<label for="product-license-xml">Optional Enterprise Edition License Key</label>
|
<label for="product-license-xml">Optional Enterprise Edition License Key</label>
|
||||||
{{textarea id="product-license-xml" value=license rows="18" class=(if LicenseError 'form-control is-invalid' 'form-control')}}
|
{{textarea id="product-license-xml" value=license rows="18" class=(if LicenseError 'form-control is-invalid' 'form-control')}}
|
||||||
{{#if appMeta.valid}}
|
{{#if appMeta.valid}}
|
||||||
{{#if (eq appMeta.edition "Enterprise")}}
|
{{#if (eq appMeta.edition constants.Product.EnterpriseEdition)}}
|
||||||
<p class="mt-2 color-green">Registered to {{appMeta.license.email}} @ {{appMeta.license.name}}</p>
|
<p class="mt-2 color-green">Registered to {{appMeta.license.email}} @ {{appMeta.license.name}}</p>
|
||||||
<p class="mt-2 color-green">{{appMeta.license.package}} package up to {{appMeta.license.seats}} users</p>
|
<p class="mt-2 color-green">{{appMeta.license.package}} package up to {{appMeta.license.seats}} users</p>
|
||||||
{{#if appMeta.license.trial}}
|
{{#if appMeta.license.trial}}
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
<li class="item cursor-auto">
|
<li class="item cursor-auto">
|
||||||
<img class="logo" src="/assets/img/icon-white-64x64.png" />
|
<img class="logo" src="/assets/img/icon-white-64x64.png" />
|
||||||
</li>
|
</li>
|
||||||
{{#if (eq appMeta.edition 'Community')}}
|
{{#if (eq appMeta.edition constants.Product.CommunityEdition)}}
|
||||||
<li class="item">
|
<li class="item">
|
||||||
{{#link-to "folders" class=(if (eq selectItem 'spaces') 'link selected' 'link')}}SPACES{{/link-to}}
|
{{#link-to "folders" class=(if (eq selectItem 'spaces') 'link selected' 'link')}}SPACES{{/link-to}}
|
||||||
</li>
|
</li>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq appMeta.edition 'Enterprise')}}
|
{{#if (eq appMeta.edition constants.Product.EnterpriseEdition)}}
|
||||||
{{#if session.viewDashboard}}
|
{{#if session.viewDashboard}}
|
||||||
<li class="item">
|
<li class="item">
|
||||||
{{#link-to "dashboard" class=(if (eq selectItem 'dashboard') 'link selected' 'link')}}ACTIONS{{/link-to}}
|
{{#link-to "dashboard" class=(if (eq selectItem 'dashboard') 'link selected' 'link')}}ACTIONS{{/link-to}}
|
||||||
|
@ -36,10 +36,10 @@
|
||||||
<i class="material-icons">menu</i>
|
<i class="material-icons">menu</i>
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown-menu" aria-labelledby="top-nav-hamburger">
|
<div class="dropdown-menu" aria-labelledby="top-nav-hamburger">
|
||||||
{{#if (eq appMeta.edition 'Community')}}
|
{{#if (eq appMeta.edition constants.Product.CommunityEdition)}}
|
||||||
{{#link-to "folders" class="dropdown-item"}}Spaces{{/link-to}}
|
{{#link-to "folders" class="dropdown-item"}}Spaces{{/link-to}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq appMeta.edition 'Enterprise')}}
|
{{#if (eq appMeta.edition constants.Product.EnterpriseEdition)}}
|
||||||
{{#link-to "folders" class="dropdown-item"}}Spaces{{/link-to}}
|
{{#link-to "folders" class="dropdown-item"}}Spaces{{/link-to}}
|
||||||
{{#if session.viewDashboard}}
|
{{#if session.viewDashboard}}
|
||||||
{{#link-to "dashboard" class="dropdown-item"}}Actions{{/link-to}}
|
{{#link-to "dashboard" class="dropdown-item"}}Actions{{/link-to}}
|
||||||
|
@ -178,7 +178,7 @@
|
||||||
<div class="dotcom">
|
<div class="dotcom">
|
||||||
<a href="https://documize.com">https://documize.com</a>
|
<a href="https://documize.com">https://documize.com</a>
|
||||||
</div>
|
</div>
|
||||||
{{#if (eq appMeta.edition 'Community')}}
|
{{#if (eq appMeta.edition constants.Product.CommunityEdition)}}
|
||||||
<div class="copyright">
|
<div class="copyright">
|
||||||
© Documize Inc. All rights reserved.
|
© Documize Inc. All rights reserved.
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -30,7 +30,7 @@ type Manifest struct {
|
||||||
OrgID string `json:"org"`
|
OrgID string `json:"org"`
|
||||||
|
|
||||||
// Product edition at the time of the backup.
|
// Product edition at the time of the backup.
|
||||||
Edition string `json:"edition"`
|
Edition env.Edition `json:"edition"`
|
||||||
|
|
||||||
// When the backup took place.
|
// When the backup took place.
|
||||||
Created time.Time `json:"created"`
|
Created time.Time `json:"created"`
|
||||||
|
|
|
@ -38,7 +38,7 @@ type SiteMeta struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
Revision int `json:"revision"`
|
Revision int `json:"revision"`
|
||||||
MaxTags int `json:"maxTags"`
|
MaxTags int `json:"maxTags"`
|
||||||
Edition string `json:"edition"`
|
Edition env.Edition `json:"edition"`
|
||||||
Valid bool `json:"valid"`
|
Valid bool `json:"valid"`
|
||||||
ConversionEndpoint string `json:"conversionEndpoint"`
|
ConversionEndpoint string `json:"conversionEndpoint"`
|
||||||
License env.License `json:"license"`
|
License env.License `json:"license"`
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue