mirror of
https://github.com/documize/community.git
synced 2025-07-19 05:09:42 +02:00
self-host enhancements for Word/PDF handling
This commit is contained in:
parent
99b9427b8e
commit
bbcba8eb18
23 changed files with 728 additions and 705 deletions
3
.jshintrc
Normal file
3
.jshintrc
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"esversion":6
|
||||
}
|
|
@ -8,7 +8,7 @@ The mission is to bring software dev inspired features (refactoring, testing, li
|
|||
|
||||
## Latest version
|
||||
|
||||
v1.47.2
|
||||
v1.48.0
|
||||
|
||||
## OS Support
|
||||
|
||||
|
|
|
@ -20,8 +20,10 @@ const {
|
|||
export default Ember.Component.extend({
|
||||
titleEmpty: computed.empty('model.general.title'),
|
||||
messageEmpty: computed.empty('model.general.message'),
|
||||
conversionEndpointEmpty: computed.empty('model.general.conversionEndpoint'),
|
||||
hasTitleInputError: computed.and('titleEmpty', 'titleError'),
|
||||
hasMessageInputError: computed.and('messageEmpty', 'messageError'),
|
||||
hasConversionEndpointInputError: computed.and('conversionEndpointEmpty', 'conversionEndpointError'),
|
||||
|
||||
actions: {
|
||||
save() {
|
||||
|
@ -35,10 +37,22 @@ export default Ember.Component.extend({
|
|||
return $("#siteMessage").focus();
|
||||
}
|
||||
|
||||
if (isEmpty(this.get('model.general.conversionEndpoint'))) {
|
||||
set(this, 'conversionEndpointError', true);
|
||||
return $("#conversionEndpoint").focus();
|
||||
}
|
||||
|
||||
let e = this.get('model.general.conversionEndpoint');
|
||||
if (is.endWith(e, '/')) {
|
||||
this.set('model.general.conversionEndpoint', e.substring(0, e.length-1));
|
||||
}
|
||||
|
||||
this.model.general.set('allowAnonymousAccess', Ember.$("#allowAnonymousAccess").prop('checked'));
|
||||
|
||||
this.get('save')().then(() => {
|
||||
set(this, 'titleError', false);
|
||||
set(this, 'messageError', false);
|
||||
set(this, 'conversionEndpointError', false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ export default Model.extend({
|
|||
title: attr('string'),
|
||||
message: attr('string'),
|
||||
email: attr('string'),
|
||||
conversionEndpoint: attr('string'),
|
||||
allowAnonymousAccess: attr('boolean', { defaultValue: false }),
|
||||
created: attr(),
|
||||
revised: attr()
|
||||
|
|
|
@ -25,6 +25,7 @@ export default Ember.Service.extend({
|
|||
kcAuth: service(),
|
||||
apiHost: `${config.apiHost}`,
|
||||
endpoint: `${config.apiHost}/${config.apiNamespace}`,
|
||||
conversionEndpoint: '',
|
||||
orgId: '',
|
||||
title: '',
|
||||
version: '',
|
||||
|
@ -57,7 +58,7 @@ export default Ember.Service.extend({
|
|||
allowAnonymousAccess: true,
|
||||
setupMode: true
|
||||
});
|
||||
|
||||
|
||||
this.get('localStorage').clearAll();
|
||||
|
||||
return resolve(this);
|
||||
|
@ -78,7 +79,7 @@ export default Ember.Service.extend({
|
|||
return this.get('ajax').request('public/meta').then((response) => {
|
||||
this.setProperties(response);
|
||||
|
||||
if (is.not.include(requestedUrl, '/auth/')) {
|
||||
if (is.not.include(requestedUrl, '/auth/')) {
|
||||
this.get('localStorage').storeSessionItem('entryUrl', requestedUrl);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,8 @@ export default Ember.Service.extend({
|
|||
|
||||
this.get('appMeta').setProperties({
|
||||
message: org.get('message'),
|
||||
title: org.get('title')
|
||||
title: org.get('title'),
|
||||
conversionEndpoint: org.get('conversionEndpoint')
|
||||
});
|
||||
|
||||
return this.get('ajax').request(`organizations/${id}`, {
|
||||
|
|
|
@ -17,9 +17,14 @@
|
|||
<label>Anonymous Access</label>
|
||||
<div class="tip">Content within "Everyone" will be made available to anonymous users</div>
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" id="allowAnonymousAccess" checked= {{model.general.allowAnonymousAccess}} />
|
||||
<input type="checkbox" id="allowAnonymousAccess" checked={{model.general.allowAnonymousAccess}} />
|
||||
<label for="allowAnonymousAccess">Allow anyone to access this Documize instance</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-control">
|
||||
<label>Conversion Service URL</label>
|
||||
<div class="tip">Endpoint for handling import/export (e.g. https://api.documize.com, <a href="https://docs.documize.com/s/WNEpptWJ9AABRnha/administration-guides/d/WO0pt_MXigAB6sJ7/general-options">view documentation</a>)</div>
|
||||
{{focus-input id="conversionEndpoint" type="text" value=model.general.conversionEndpoint class=(if hasConversionEndpointInputError 'error')}}
|
||||
</div>
|
||||
<div class="regular-button button-blue" {{ action 'save' }}>save</div>
|
||||
</form>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "documize",
|
||||
"version": "1.47.2",
|
||||
"version": "1.48.0",
|
||||
"description": "The Document IDE",
|
||||
"private": true,
|
||||
"repository": "",
|
||||
|
|
|
@ -1,48 +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 apidocumizecom
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/documize/community/core/api/request"
|
||||
)
|
||||
|
||||
func endPoint() string {
|
||||
r := request.ConfigString("LICENSE", "endpoint")
|
||||
if r != "" {
|
||||
return r
|
||||
}
|
||||
return "https://api.documize.com"
|
||||
}
|
||||
|
||||
func token() (string, error) {
|
||||
r := request.ConfigString("LICENSE", "token")
|
||||
if r == "" {
|
||||
return "", errors.New("Documize token is empty")
|
||||
}
|
||||
// TODO more validation here
|
||||
return r, nil
|
||||
}
|
||||
|
||||
var transport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true, // TODO should be glick.InsecureSkipVerifyTLS (from -insecure flag) but get error: x509: certificate signed by unknown authority
|
||||
}}
|
||||
|
||||
// CheckToken returns an error if the Documize LICENSE token is invalid.
|
||||
func CheckToken() error {
|
||||
_, err := token()
|
||||
return err
|
||||
}
|
|
@ -13,13 +13,13 @@ package apidocumizecom
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
|
||||
api "github.com/documize/community/core/convapi"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
|
@ -35,14 +35,14 @@ func (file *Msword) Convert(r api.DocumentConversionRequest, reply *api.Document
|
|||
base := filepath.Base(r.Filename)
|
||||
fmt.Println("Starting conversion of document: ", base)
|
||||
|
||||
var transport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true, // TODO should be glick.InsecureSkipVerifyTLS (from -insecure flag) but get error: x509: certificate signed by unknown authority
|
||||
}}
|
||||
|
||||
client := &http.Client{Transport: transport}
|
||||
|
||||
tok, err := token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp, err := client.Post(endPoint()+"/api/word?token="+tok, "application/json", bytes.NewReader(byts))
|
||||
resp, err := client.Post(r.ServiceEndpoint+"/api/word", "application/json", bytes.NewReader(byts))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import (
|
|||
|
||||
// Convert provides the entry-point into the document conversion process.
|
||||
func Convert(ctx context.Context, xtn string, fileRequest *api.DocumentConversionRequest) (*api.DocumentConversionResponse, error) {
|
||||
fileRequest.Token = plugins.Lib.Token("Convert", xtn)
|
||||
fileResultI, err := plugins.Lib.Run(ctx, "Convert", xtn, fileRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -13,6 +13,7 @@ package endpoint
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -27,10 +28,8 @@ import (
|
|||
"github.com/documize/community/core/api/util"
|
||||
api "github.com/documize/community/core/convapi"
|
||||
"github.com/documize/community/core/log"
|
||||
|
||||
uuid "github.com/nu7hatch/gouuid"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
uuid "github.com/nu7hatch/gouuid"
|
||||
)
|
||||
|
||||
// UploadConvertDocument is an endpoint to both upload and convert a document
|
||||
|
@ -96,10 +95,24 @@ func convertDocument(w http.ResponseWriter, r *http.Request, job, folderID strin
|
|||
method := "convertDocument"
|
||||
p := request.GetPersister(r)
|
||||
|
||||
licenseKey := request.ConfigString("EDITION-LICENSE", "key")
|
||||
licenseSignature := request.ConfigString("EDITION-LICENSE", "signature")
|
||||
k, _ := hex.DecodeString(licenseKey)
|
||||
s, _ := hex.DecodeString(licenseSignature)
|
||||
|
||||
conversion.LicenseKey = k
|
||||
conversion.LicenseSignature = s
|
||||
|
||||
org, err := p.GetOrganization(p.Context.OrgID)
|
||||
if err != nil {
|
||||
writePayloadError(w, method, err)
|
||||
return
|
||||
}
|
||||
|
||||
conversion.ServiceEndpoint = org.ConversionEndpoint
|
||||
|
||||
var fileResult *api.DocumentConversionResponse
|
||||
var filename string
|
||||
var err error
|
||||
|
||||
filename, fileResult, err = storageProvider.Convert(conversion)
|
||||
if err != nil {
|
||||
writePayloadError(w, method, err)
|
||||
|
|
|
@ -48,6 +48,7 @@ func GetMeta(w http.ResponseWriter, r *http.Request) {
|
|||
data.Version = Product.Version
|
||||
data.Edition = Product.License.Edition
|
||||
data.Valid = Product.License.Valid
|
||||
data.ConversionEndpoint = org.ConversionEndpoint
|
||||
|
||||
// Strip secrets
|
||||
data.AuthConfig = StripAuthSecrets(org.AuthProvider, org.AuthConfig)
|
||||
|
|
|
@ -34,13 +34,16 @@ var Product core.ProdInfo
|
|||
|
||||
func init() {
|
||||
Product.Major = "1"
|
||||
Product.Minor = "47"
|
||||
Product.Patch = "2"
|
||||
Product.Minor = "48"
|
||||
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.Seats = 1
|
||||
Product.License.Valid = true
|
||||
Product.License.Trial = false
|
||||
Product.License.Edition = "Community"
|
||||
|
||||
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)
|
||||
|
|
|
@ -87,6 +87,7 @@ type Organization struct {
|
|||
AllowAnonymousAccess bool `json:"allowAnonymousAccess"`
|
||||
AuthProvider string `json:"authProvider"`
|
||||
AuthConfig string `json:"authConfig"`
|
||||
ConversionEndpoint string `json:"conversionEndpoint"`
|
||||
Serial string `json:"-"`
|
||||
Active bool `json:"-"`
|
||||
}
|
||||
|
@ -352,6 +353,7 @@ type SiteMeta struct {
|
|||
Version string `json:"version"`
|
||||
Edition string `json:"edition"`
|
||||
Valid bool `json:"valid"`
|
||||
ConversionEndpoint string `json:"conversionEndpoint"`
|
||||
}
|
||||
|
||||
// Template is used to create a new document.
|
||||
|
|
|
@ -14,7 +14,6 @@ package plugins
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
|
@ -89,15 +88,11 @@ func LibSetup() error {
|
|||
}
|
||||
}
|
||||
|
||||
if err = apidocumizecom.CheckToken(); err == nil {
|
||||
for _, xtn := range []string{"doc", "docx"} {
|
||||
err = Lib.RegPlugin("Convert", xtn, apidocumizecom.MSwordConvert, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, xtn := range []string{"doc", "docx"} {
|
||||
err = Lib.RegPlugin("Convert", xtn, apidocumizecom.MSwordConvert, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Info(fmt.Sprintf("Documize API token is not valid: %v", err))
|
||||
}
|
||||
|
||||
err = Lib.RegPlugin("Convert", "documizeapi", documizeapi.Convert, nil)
|
||||
|
|
|
@ -59,7 +59,7 @@ func (p *Persister) AddOrganization(org entity.Organization) error {
|
|||
|
||||
// GetOrganization returns the Organization reocrod from the organization database table with the given id.
|
||||
func (p *Persister) GetOrganization(id string) (org entity.Organization, err error) {
|
||||
stmt, err := Db.Preparex("SELECT id, refid, company, title, message, url, domain, email, serial, active, allowanonymousaccess, authprovider, coalesce(authconfig,JSON_UNQUOTE('{}')) as authconfig, created, revised FROM organization WHERE refid=?")
|
||||
stmt, err := Db.Preparex("SELECT id, refid, company, title, message, url, domain, service as conversionendpoint, email, serial, active, allowanonymousaccess, authprovider, coalesce(authconfig,JSON_UNQUOTE('{}')) as authconfig, created, revised FROM organization WHERE refid=?")
|
||||
defer utility.Close(stmt)
|
||||
|
||||
if err != nil {
|
||||
|
@ -86,7 +86,7 @@ func (p *Persister) GetOrganizationByDomain(subdomain string) (org entity.Organi
|
|||
|
||||
var stmt *sqlx.Stmt
|
||||
|
||||
stmt, err = Db.Preparex("SELECT id, refid, company, title, message, url, domain, email, serial, active, allowanonymousaccess, authprovider, coalesce(authconfig,JSON_UNQUOTE('{}')) as authconfig, created, revised FROM organization WHERE domain=? AND active=1")
|
||||
stmt, err = Db.Preparex("SELECT id, refid, company, title, message, url, domain, service as conversionendpoint, email, serial, active, allowanonymousaccess, authprovider, coalesce(authconfig,JSON_UNQUOTE('{}')) as authconfig, created, revised FROM organization WHERE domain=? AND active=1")
|
||||
defer utility.Close(stmt)
|
||||
|
||||
if err != nil {
|
||||
|
@ -110,7 +110,7 @@ func (p *Persister) GetOrganizationByDomain(subdomain string) (org entity.Organi
|
|||
func (p *Persister) UpdateOrganization(org entity.Organization) (err error) {
|
||||
org.Revised = time.Now().UTC()
|
||||
|
||||
stmt, err := p.Context.Transaction.PrepareNamed("UPDATE organization SET title=:title, message=:message, email=:email, allowanonymousaccess=:allowanonymousaccess, revised=:revised WHERE refid=:refid")
|
||||
stmt, err := p.Context.Transaction.PrepareNamed("UPDATE organization SET title=:title, message=:message, service=:conversionendpoint, email=:email, allowanonymousaccess=:allowanonymousaccess, revised=:revised WHERE refid=:refid")
|
||||
defer utility.Close(stmt)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -105,6 +105,9 @@ func (store *LocalStorageProvider) Convert(params api.ConversionJobRequest) (fil
|
|||
fileRequest.Filename = filename
|
||||
fileRequest.Filedata = fileData
|
||||
fileRequest.PageBreakLevel = params.IndexDepth
|
||||
fileRequest.LicenseKey = params.LicenseKey
|
||||
fileRequest.LicenseSignature = params.LicenseSignature
|
||||
fileRequest.ServiceEndpoint = params.ServiceEndpoint
|
||||
//fileRequest.Job = params.OrgID + string(os.PathSeparator) + params.Job
|
||||
//fileRequest.OrgID = params.OrgID
|
||||
|
||||
|
|
|
@ -9,15 +9,17 @@
|
|||
//
|
||||
// https://documize.com
|
||||
|
||||
// Package convapi provides the defininitions of types used for file conversion communication between different components of the Documize system.
|
||||
// Package convapi provides the definitions of types used for file conversion communication between different components of the Documize system.
|
||||
package convapi
|
||||
|
||||
// DocumentConversionRequest is what is passed to a Convert plugin.
|
||||
type DocumentConversionRequest struct {
|
||||
Filename string
|
||||
Filedata []byte
|
||||
PageBreakLevel uint
|
||||
Token string // authorisation token
|
||||
Filename string
|
||||
Filedata []byte
|
||||
PageBreakLevel uint
|
||||
LicenseKey []byte
|
||||
LicenseSignature []byte
|
||||
ServiceEndpoint string
|
||||
}
|
||||
|
||||
// Page holds the contents of a Documize page,
|
||||
|
|
|
@ -13,9 +13,12 @@ package convapi
|
|||
|
||||
// ConversionJobRequest is the information used to set-up a conversion job.
|
||||
type ConversionJobRequest struct {
|
||||
Job string
|
||||
IndexDepth uint
|
||||
OrgID string
|
||||
Job string
|
||||
IndexDepth uint
|
||||
OrgID string
|
||||
LicenseKey []byte
|
||||
LicenseSignature []byte
|
||||
ServiceEndpoint string
|
||||
}
|
||||
|
||||
// DocumentExport is the type used by a document export plugin.
|
||||
|
|
|
@ -263,7 +263,6 @@ DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
|
|||
INSERT INTO `config` VALUES ('SMTP','{\"userid\": \"\",\"password\": \"\",\"host\": \"\",\"port\": \"\",\"sender\": \"\"}');
|
||||
INSERT INTO `config` VALUES ('FILEPLUGINS',
|
||||
'[{\"Comment\": \"Disable (or not) built-in html import (NOTE: no Plugin name)\",\"Disabled\": false,\"API\": \"Convert\",\"Actions\": [\"htm\",\"html\"]},{\"Comment\": \"Disable (or not) built-in Documize API import used from SDK (NOTE: no Plugin name)\",\"Disabled\": false,\"API\": \"Convert\",\"Actions\": [\"documizeapi\"]}]');
|
||||
INSERT INTO `config` VALUES ('LICENSE','{\"token\": \"\",\"endpoint\": \"https://api.documize.com\"}');
|
||||
INSERT INTO `config` VALUES ('META','{\"database\": \"db_00000.sql\"}');
|
||||
INSERT INTO `config` VALUES ('SECTION-GITHUB', '{\"clientID\": \"\", \"clientSecret\": \"\", \"authorizationCallbackURL\": \"https://localhost:5001/api/public/validate?section=github\"}');
|
||||
INSERT INTO `config` VALUES ('SECTION-TRELLO','{\"appKey\": \"\"}');
|
||||
|
|
3
core/database/scripts/autobuild/db_00014.sql
Normal file
3
core/database/scripts/autobuild/db_00014.sql
Normal file
|
@ -0,0 +1,3 @@
|
|||
/* community edition */
|
||||
ALTER TABLE organization ADD COLUMN `service` VARCHAR(100) NOT NULL DEFAULT 'https://api.documize.com' AFTER `domain`;
|
||||
|
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue