mirror of
https://github.com/documize/community.git
synced 2025-08-02 20:15:26 +02:00
PRovide basic in-app purchase/renewal flow
This commit is contained in:
parent
e116d3b000
commit
d1b803b246
39 changed files with 1211 additions and 1154 deletions
|
@ -32,15 +32,6 @@ func InstallUpgrade(runtime *env.Runtime, existingDB bool) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// Filter out database specific scripts.
|
||||
dbTypeScripts := SpecificScripts(runtime, scripts)
|
||||
if len(dbTypeScripts) == 0 {
|
||||
runtime.Log.Info(fmt.Sprintf("Database: unable to load scripts for database type %s", runtime.StoreProvider.Type()))
|
||||
return
|
||||
}
|
||||
|
||||
runtime.Log.Info(fmt.Sprintf("Database: loaded %d SQL scripts for provider %s", len(dbTypeScripts), runtime.StoreProvider.Type()))
|
||||
|
||||
// Get current database version.
|
||||
currentVersion := 0
|
||||
if existingDB {
|
||||
|
@ -53,6 +44,15 @@ func InstallUpgrade(runtime *env.Runtime, existingDB bool) (err error) {
|
|||
runtime.Log.Info(fmt.Sprintf("Database: current version number is %d", currentVersion))
|
||||
}
|
||||
|
||||
// Filter out database specific scripts.
|
||||
dbTypeScripts := SpecificScripts(runtime, scripts)
|
||||
if len(dbTypeScripts) == 0 {
|
||||
runtime.Log.Info(fmt.Sprintf("Database: unable to load scripts for database type %s", runtime.StoreProvider.Type()))
|
||||
return
|
||||
}
|
||||
|
||||
runtime.Log.Info(fmt.Sprintf("Database: loaded %d SQL scripts for provider %s", len(dbTypeScripts), runtime.StoreProvider.Type()))
|
||||
|
||||
// Make a list of scripts to execute based upon current database state.
|
||||
toProcess := []Script{}
|
||||
for _, s := range dbTypeScripts {
|
||||
|
@ -90,52 +90,6 @@ func InstallUpgrade(runtime *env.Runtime, existingDB bool) (err error) {
|
|||
tx.Commit()
|
||||
|
||||
return nil
|
||||
|
||||
// New style schema
|
||||
// if existingDB {
|
||||
// amLeader, err = Lock(runtime, len(toProcess))
|
||||
// if err != nil {
|
||||
// runtime.Log.Error("Database: failed to lock existing database for processing", err)
|
||||
// }
|
||||
// } else {
|
||||
// // New installation hopes that you are only spinning up one instance of Documize.
|
||||
// // Assumption: nobody will perform the intial setup in a clustered environment.
|
||||
// amLeader = true
|
||||
// }
|
||||
|
||||
// tx, err := runtime.Db.Beginx()
|
||||
// if err != nil {
|
||||
// return Unlock(runtime, tx, err, amLeader)
|
||||
// }
|
||||
|
||||
// // If currently running process is database leader then we perform upgrade.
|
||||
// if amLeader {
|
||||
// runtime.Log.Info(fmt.Sprintf("Database: %d SQL scripts to process", len(toProcess)))
|
||||
|
||||
// err = runScripts(runtime, tx, toProcess)
|
||||
// if err != nil {
|
||||
// runtime.Log.Error("Database: error processing SQL script", err)
|
||||
// }
|
||||
|
||||
// return Unlock(runtime, tx, err, amLeader)
|
||||
// }
|
||||
|
||||
// // If currently running process is a slave instance then we wait for migration to complete.
|
||||
// targetVersion := toProcess[len(toProcess)-1].Version
|
||||
|
||||
// for targetVersion != currentVersion {
|
||||
// time.Sleep(time.Second)
|
||||
// runtime.Log.Info("Database: slave instance polling for upgrade process completion")
|
||||
// tx.Rollback()
|
||||
|
||||
// // Get database version and check again.
|
||||
// currentVersion, err = CurrentVersion(runtime)
|
||||
// if err != nil {
|
||||
// return Unlock(runtime, tx, err, amLeader)
|
||||
// }
|
||||
// }
|
||||
|
||||
// return Unlock(runtime, tx, nil, amLeader)
|
||||
}
|
||||
|
||||
// Run SQL scripts to instal or upgrade this database.
|
||||
|
|
6
core/database/scripts/mysql/db_00026.sql
Normal file
6
core/database/scripts/mysql/db_00026.sql
Normal file
|
@ -0,0 +1,6 @@
|
|||
/* community edition */
|
||||
|
||||
-- add subscription
|
||||
ALTER TABLE dmz_org ADD COLUMN `c_sub` JSON NULL AFTER `c_authconfig`;
|
||||
|
||||
-- deprecations
|
6
core/database/scripts/postgresql/db_00002.sql
Normal file
6
core/database/scripts/postgresql/db_00002.sql
Normal file
|
@ -0,0 +1,6 @@
|
|||
/* community edition */
|
||||
|
||||
-- add subscription
|
||||
ALTER TABLE dmz_org ADD COLUMN c_sub JSON NULL;
|
||||
|
||||
-- deprecations
|
27
core/env/flags.go
vendored
27
core/env/flags.go
vendored
|
@ -25,12 +25,13 @@ import (
|
|||
type Flags struct {
|
||||
DBConn string // database connection string
|
||||
Salt string // the salt string used to encode JWT tokens
|
||||
DBType string // (optional) database type
|
||||
DBType string // database type
|
||||
SSLCertFile string // (optional) name of SSL certificate PEM file
|
||||
SSLKeyFile string // (optional) name of SSL key PEM file
|
||||
HTTPPort string // (optional) HTTP or HTTPS port
|
||||
ForceHTTPPort2SSL string // (optional) HTTP that should be redirected to HTTPS
|
||||
SiteMode string // (optional) if 1 then serve offline web page
|
||||
Location string // reserved
|
||||
}
|
||||
|
||||
// SSLEnabled returns true if both cert and key were provided at runtime.
|
||||
|
@ -71,8 +72,9 @@ var flagList progFlags
|
|||
var loadMutex sync.Mutex
|
||||
|
||||
// ParseFlags loads command line and OS environment variables required by the program to function.
|
||||
func ParseFlags() (f Flags) {
|
||||
var dbConn, dbType, jwtKey, siteMode, port, certFile, keyFile, forcePort2SSL string
|
||||
func ParseFlags() (f Flags, ok bool) {
|
||||
ok = true
|
||||
var dbConn, dbType, jwtKey, siteMode, port, certFile, keyFile, forcePort2SSL, location string
|
||||
|
||||
register(&jwtKey, "salt", false, "the salt string used to encode JWT tokens, if not set a random value will be generated")
|
||||
register(&certFile, "cert", false, "the cert.pem file used for https")
|
||||
|
@ -82,8 +84,11 @@ func ParseFlags() (f Flags) {
|
|||
register(&siteMode, "offline", false, "set to '1' for OFFLINE mode")
|
||||
register(&dbType, "dbtype", true, "specify the database provider: mysql|percona|mariadb|postgresql")
|
||||
register(&dbConn, "db", true, `'database specific connection string for example "user:password@tcp(localhost:3306)/dbname"`)
|
||||
register(&location, "location", false, `reserved`)
|
||||
|
||||
parse("db")
|
||||
if !parse("db") {
|
||||
ok = false
|
||||
}
|
||||
|
||||
f.DBConn = dbConn
|
||||
f.ForceHTTPPort2SSL = forcePort2SSL
|
||||
|
@ -94,7 +99,13 @@ func ParseFlags() (f Flags) {
|
|||
f.SSLKeyFile = keyFile
|
||||
f.DBType = strings.ToLower(dbType)
|
||||
|
||||
return f
|
||||
// reserved
|
||||
if len(location) == 0 {
|
||||
location = "selfhost"
|
||||
}
|
||||
f.Location = strings.ToLower(location)
|
||||
|
||||
return f, ok
|
||||
}
|
||||
|
||||
// register prepares flag for subsequent parsing
|
||||
|
@ -116,7 +127,7 @@ func register(target *string, name string, required bool, usage string) {
|
|||
}
|
||||
|
||||
// parse loads flags from OS environment and command line switches
|
||||
func parse(doFirst string) {
|
||||
func parse(doFirst string) (ok bool) {
|
||||
loadMutex.Lock()
|
||||
defer loadMutex.Unlock()
|
||||
|
||||
|
@ -141,10 +152,12 @@ func parse(doFirst string) {
|
|||
}
|
||||
fmt.Fprintln(os.Stderr)
|
||||
flag.Usage()
|
||||
return
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
165
core/env/product.go
vendored
165
core/env/product.go
vendored
|
@ -1,165 +0,0 @@
|
|||
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
|
||||
//
|
||||
// This software (Documize Community Edition) is licensed under
|
||||
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
//
|
||||
// You can operate outside the AGPL restrictions by purchasing
|
||||
// Documize Enterprise Edition and obtaining a commercial license
|
||||
// by contacting <sales@documize.com>.
|
||||
//
|
||||
// https://documize.com
|
||||
|
||||
package env
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Edition is either Community or Enterprise.
|
||||
type 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
|
||||
Version string
|
||||
Major string
|
||||
Minor string
|
||||
Patch string
|
||||
Revision int
|
||||
License License
|
||||
}
|
||||
|
||||
// License provides details of product license.
|
||||
type License struct {
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
Edition Edition `json:"edition"`
|
||||
Package Package `json:"package"`
|
||||
Plan Plan `json:"plan"`
|
||||
Start time.Time `json:"start"`
|
||||
End time.Time `json:"end"`
|
||||
Seats Seats `json:"seats"`
|
||||
Trial bool `json:"trial"`
|
||||
|
||||
// UserCount is number of users within Documize instance by tenant.
|
||||
// Provided at runtime.
|
||||
UserCount map[string]int
|
||||
}
|
||||
|
||||
// IsEmpty determines if we have a license.
|
||||
func (l *License) IsEmpty() bool {
|
||||
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.
|
||||
func (l *License) Status(orgID string) string {
|
||||
lp := "populated"
|
||||
if l.IsEmpty() {
|
||||
lp = "empty"
|
||||
}
|
||||
lv := "invalid"
|
||||
if l.IsValid(orgID) {
|
||||
lv = "valid"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("License is %s and %s", lp, lv)
|
||||
}
|
||||
|
||||
// IsValid returns if license is valid for specified tenant.
|
||||
func (l *License) IsValid(orgID string) bool {
|
||||
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.
|
||||
type LicenseData struct {
|
||||
Key string `json:"key"`
|
||||
Signature string `json:"signature"`
|
||||
}
|
||||
|
||||
// LicenseUserAcount states number of active users by tenant.
|
||||
type LicenseUserAcount struct {
|
||||
OrgID string `json:"orgId"`
|
||||
Users int `json:"users"`
|
||||
}
|
3
core/env/runtime.go
vendored
3
core/env/runtime.go
vendored
|
@ -13,6 +13,7 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"github.com/documize/community/domain"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
|
@ -23,7 +24,7 @@ type Runtime struct {
|
|||
Db *sqlx.DB
|
||||
StoreProvider StoreProvider
|
||||
Log Logger
|
||||
Product Product
|
||||
Product domain.Product
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
|
@ -14,7 +14,6 @@ package uniqueid
|
|||
|
||||
import (
|
||||
"github.com/documize/community/core/uniqueid/xid"
|
||||
"github.com/documize/community/core/uniqueid/xid16"
|
||||
)
|
||||
|
||||
// Generate creates a randomly generated string suitable for use as part of an URI.
|
||||
|
@ -22,16 +21,3 @@ import (
|
|||
func Generate() string {
|
||||
return xid.New().String()
|
||||
}
|
||||
|
||||
// Generate16 creates a randomly generated 16 character length string suitable for use as part of an URI.
|
||||
// It returns a string that is always 16 characters long.
|
||||
func Generate16() string {
|
||||
return xid16.New().String()
|
||||
}
|
||||
|
||||
// beqassjmvbajrivsc0eg
|
||||
// beqat1bmvbajrivsc0f0
|
||||
|
||||
// beqat1bmvbajrivsc1ag
|
||||
// beqat1bmvbajrivsc1g0
|
||||
// beqat1bmvbajrivsc1ug
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue