mirror of
https://github.com/documize/community.git
synced 2025-07-24 15:49:44 +02:00
major code repair from old to new API -- WIP
This commit is contained in:
parent
25b576f861
commit
792c3e2ce8
46 changed files with 3403 additions and 171 deletions
|
@ -24,10 +24,10 @@ import (
|
|||
"github.com/documize/community/core/api/entity"
|
||||
"github.com/documize/community/core/api/request"
|
||||
"github.com/documize/community/core/api/util"
|
||||
"github.com/documize/community/core/env"
|
||||
"github.com/documize/community/core/log"
|
||||
"github.com/documize/community/core/secrets"
|
||||
"github.com/documize/community/domain/section/provider"
|
||||
"github.com/documize/community/server/web"
|
||||
)
|
||||
|
||||
// Authenticate user based up HTTP Authorization header.
|
||||
|
@ -98,7 +98,7 @@ func Authenticate(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// Attach user accounts and work out permissions
|
||||
attachUserAccounts(p, org.RefID, &user)
|
||||
AttachUserAccounts(p, org.RefID, &user)
|
||||
|
||||
// active check
|
||||
|
||||
|
@ -201,7 +201,7 @@ func Authorize(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
|||
|
||||
// Fetch user permissions for this org
|
||||
if context.Authenticated {
|
||||
user, err := getSecuredUser(p, org.RefID, context.UserID)
|
||||
user, err := GetSecuredUser(p, org.RefID, context.UserID)
|
||||
|
||||
if err != nil {
|
||||
writeServerError(w, method, err)
|
||||
|
@ -242,8 +242,6 @@ func Authorize(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
|||
|
||||
// ValidateAuthToken finds and validates authentication token.
|
||||
func ValidateAuthToken(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
log.Info("cb gh")
|
||||
// TODO should this go after token validation?
|
||||
if s := r.URL.Query().Get("section"); s != "" {
|
||||
if err := provider.Callback(s, w, r); err != nil {
|
||||
|
@ -325,7 +323,7 @@ func ValidateAuthToken(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
user, err := getSecuredUser(p, org.RefID, context.UserID)
|
||||
user, err := GetSecuredUser(p, org.RefID, context.UserID)
|
||||
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
|
@ -349,7 +347,7 @@ func preAuthorizeStaticAssets(r *http.Request) bool {
|
|||
strings.ToLower(r.URL.Path) == "/robots.txt" ||
|
||||
strings.ToLower(r.URL.Path) == "/version" ||
|
||||
strings.HasPrefix(strings.ToLower(r.URL.Path), "/api/public/") ||
|
||||
((api.Runtime.Flags.SiteMode == web.SiteModeSetup) && (strings.ToLower(r.URL.Path) == "/api/setup")) {
|
||||
((api.Runtime.Flags.SiteMode == env.SiteModeSetup) && (strings.ToLower(r.URL.Path) == "/api/setup")) {
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ func AuthenticateKeycloak(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// Attach user accounts and work out permissions.
|
||||
attachUserAccounts(p, org.RefID, &user)
|
||||
AttachUserAccounts(p, org.RefID, &user)
|
||||
|
||||
// No accounts signals data integrity problem
|
||||
// so we reject login request.
|
||||
|
@ -301,7 +301,7 @@ func addUser(p request.Persister, u *entity.User, addSpace bool) (err error) {
|
|||
return err
|
||||
}
|
||||
} else {
|
||||
attachUserAccounts(p, p.Context.OrgID, &userDupe)
|
||||
AttachUserAccounts(p, p.Context.OrgID, &userDupe)
|
||||
|
||||
for _, a := range userDupe.Accounts {
|
||||
if a.OrgID == p.Context.OrgID {
|
||||
|
|
|
@ -136,7 +136,7 @@ func AddUser(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
log.Info("Adding user")
|
||||
} else {
|
||||
attachUserAccounts(p, p.Context.OrgID, &userDupe)
|
||||
AttachUserAccounts(p, p.Context.OrgID, &userDupe)
|
||||
|
||||
for _, a := range userDupe.Accounts {
|
||||
if a.OrgID == p.Context.OrgID {
|
||||
|
@ -206,7 +206,7 @@ func AddUser(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// Send back new user record
|
||||
userModel, err = getSecuredUser(p, p.Context.OrgID, userID)
|
||||
userModel, err = GetSecuredUser(p, p.Context.OrgID, userID)
|
||||
|
||||
json, err := json.Marshal(userModel)
|
||||
if err != nil {
|
||||
|
@ -254,7 +254,7 @@ func GetOrganizationUsers(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
for i := range users {
|
||||
attachUserAccounts(p, p.Context.OrgID, &users[i])
|
||||
AttachUserAccounts(p, p.Context.OrgID, &users[i])
|
||||
}
|
||||
|
||||
json, err := json.Marshal(users)
|
||||
|
@ -333,7 +333,7 @@ func GetUser(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
user, err := getSecuredUser(p, p.Context.OrgID, userID)
|
||||
user, err := GetSecuredUser(p, p.Context.OrgID, userID)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
writeNotFoundError(w, method, userID)
|
||||
|
@ -719,13 +719,14 @@ func ResetUserPassword(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// Get user object contain associated accounts but credentials are wiped.
|
||||
func getSecuredUser(p request.Persister, orgID, user string) (u entity.User, err error) {
|
||||
func GetSecuredUser(p request.Persister, orgID, user string) (u entity.User, err error) {
|
||||
u, err = p.GetUser(user)
|
||||
attachUserAccounts(p, orgID, &u)
|
||||
AttachUserAccounts(p, orgID, &u)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func attachUserAccounts(p request.Persister, orgID string, user *entity.User) {
|
||||
func AttachUserAccounts(p request.Persister, orgID string, user *entity.User) {
|
||||
user.ProtectSecrets()
|
||||
a, err := p.GetUserAccounts(user.RefID)
|
||||
|
||||
|
|
|
@ -19,9 +19,9 @@ import (
|
|||
|
||||
"github.com/documize/community/core/api"
|
||||
"github.com/documize/community/core/api/entity"
|
||||
"github.com/documize/community/core/env"
|
||||
"github.com/documize/community/core/log"
|
||||
"github.com/documize/community/core/streamutil"
|
||||
"github.com/documize/community/server/web"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
|
@ -83,7 +83,7 @@ func (p *Persister) GetOrganizationByDomain(subdomain string) (org entity.Organi
|
|||
err = nil
|
||||
subdomain = strings.ToLower(subdomain)
|
||||
|
||||
if api.Runtime.Flags.SiteMode == web.SiteModeNormal { // only return an organization when running normally
|
||||
if api.Runtime.Flags.SiteMode == env.SiteModeNormal { // only return an organization when running normally
|
||||
|
||||
var stmt *sqlx.Stmt
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ func Check(runtime *env.Runtime) bool {
|
|||
if err != nil {
|
||||
runtime.Log.Error("Can't get MySQL configuration", err)
|
||||
web.SiteInfo.Issue = "Can't get MySQL configuration: " + err.Error()
|
||||
runtime.Flags.SiteMode = web.SiteModeBadDB
|
||||
runtime.Flags.SiteMode = env.SiteModeBadDB
|
||||
return false
|
||||
}
|
||||
defer streamutil.Close(rows)
|
||||
|
@ -65,7 +65,7 @@ func Check(runtime *env.Runtime) bool {
|
|||
if err != nil {
|
||||
runtime.Log.Error("no MySQL configuration returned", err)
|
||||
web.SiteInfo.Issue = "no MySQL configuration return issue: " + err.Error()
|
||||
runtime.Flags.SiteMode = web.SiteModeBadDB
|
||||
runtime.Flags.SiteMode = env.SiteModeBadDB
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ func Check(runtime *env.Runtime) bool {
|
|||
want := fmt.Sprintf("%d.%d.%d", verInts[0], verInts[1], verInts[2])
|
||||
runtime.Log.Error("MySQL version element "+strconv.Itoa(k+1)+" of '"+version+"' not high enough, need at least version "+want, errors.New("bad MySQL version"))
|
||||
web.SiteInfo.Issue = "MySQL version element " + strconv.Itoa(k+1) + " of '" + version + "' not high enough, need at least version " + want
|
||||
runtime.Flags.SiteMode = web.SiteModeBadDB
|
||||
runtime.Flags.SiteMode = env.SiteModeBadDB
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -101,13 +101,13 @@ func Check(runtime *env.Runtime) bool {
|
|||
if charset != "utf8" {
|
||||
runtime.Log.Error("MySQL character set not utf8:", errors.New(charset))
|
||||
web.SiteInfo.Issue = "MySQL character set not utf8: " + charset
|
||||
runtime.Flags.SiteMode = web.SiteModeBadDB
|
||||
runtime.Flags.SiteMode = env.SiteModeBadDB
|
||||
return false
|
||||
}
|
||||
if !strings.HasPrefix(collation, "utf8") {
|
||||
runtime.Log.Error("MySQL collation sequence not utf8...:", errors.New(collation))
|
||||
web.SiteInfo.Issue = "MySQL collation sequence not utf8...: " + collation
|
||||
runtime.Flags.SiteMode = web.SiteModeBadDB
|
||||
runtime.Flags.SiteMode = env.SiteModeBadDB
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -119,12 +119,12 @@ func Check(runtime *env.Runtime) bool {
|
|||
`' and TABLE_TYPE='BASE TABLE'`); err != nil {
|
||||
runtime.Log.Error("Can't get MySQL number of tables", err)
|
||||
web.SiteInfo.Issue = "Can't get MySQL number of tables: " + err.Error()
|
||||
runtime.Flags.SiteMode = web.SiteModeBadDB
|
||||
runtime.Flags.SiteMode = env.SiteModeBadDB
|
||||
return false
|
||||
}
|
||||
if strings.TrimSpace(flds[0]) == "0" {
|
||||
runtime.Log.Info("Entering database set-up mode because the database is empty.....")
|
||||
runtime.Flags.SiteMode = web.SiteModeSetup
|
||||
runtime.Flags.SiteMode = env.SiteModeSetup
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -140,13 +140,13 @@ func Check(runtime *env.Runtime) bool {
|
|||
if err := runtime.Db.Select(&dummy, "SELECT 1 FROM "+table+" LIMIT 1;"); err != nil {
|
||||
runtime.Log.Error("Entering bad database mode because: SELECT 1 FROM "+table+" LIMIT 1;", err)
|
||||
web.SiteInfo.Issue = "MySQL database is not empty, but does not contain table: " + table
|
||||
runtime.Flags.SiteMode = web.SiteModeBadDB
|
||||
runtime.Flags.SiteMode = env.SiteModeBadDB
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runtime.Flags.SiteMode = web.SiteModeNormal // actually no need to do this (as already ""), this for documentation
|
||||
runtime.Flags.SiteMode = env.SiteModeNormal // actually no need to do this (as already ""), this for documentation
|
||||
web.SiteInfo.DBname = "" // do not give this info when not in set-up mode
|
||||
dbCheckOK = true
|
||||
return true
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/documize/community/core/api"
|
||||
"github.com/documize/community/core/env"
|
||||
"github.com/documize/community/core/log"
|
||||
"github.com/documize/community/core/secrets"
|
||||
"github.com/documize/community/core/stringutil"
|
||||
|
@ -65,7 +66,7 @@ func Create(w http.ResponseWriter, r *http.Request) {
|
|||
target := "/setup"
|
||||
status := http.StatusBadRequest
|
||||
|
||||
if api.Runtime.Flags.SiteMode == web.SiteModeNormal {
|
||||
if api.Runtime.Flags.SiteMode == env.SiteModeNormal {
|
||||
target = "/"
|
||||
status = http.StatusOK
|
||||
}
|
||||
|
@ -133,7 +134,7 @@ func Create(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
api.Runtime.Flags.SiteMode = web.SiteModeNormal
|
||||
api.Runtime.Flags.SiteMode = env.SiteModeNormal
|
||||
}
|
||||
|
||||
// The result of completing the onboarding process.
|
||||
|
|
5
core/env/product.go
vendored
5
core/env/product.go
vendored
|
@ -58,6 +58,11 @@ func (l *License) Status() string {
|
|||
return fmt.Sprintf("License is %s and %s", lp, lv)
|
||||
}
|
||||
|
||||
// IsValid returns if license is valid
|
||||
func (l *License) IsValid() bool {
|
||||
return l.Valid == true
|
||||
}
|
||||
|
||||
// LicenseData holds encrypted data and is unpacked into License.
|
||||
type LicenseData struct {
|
||||
Key string `json:"key"`
|
||||
|
|
11
core/env/runtime.go
vendored
11
core/env/runtime.go
vendored
|
@ -22,3 +22,14 @@ type Runtime struct {
|
|||
Log Logger
|
||||
Product ProdInfo
|
||||
}
|
||||
|
||||
const (
|
||||
// SiteModeNormal serves app
|
||||
SiteModeNormal = ""
|
||||
// SiteModeOffline serves offline.html
|
||||
SiteModeOffline = "1"
|
||||
// SiteModeSetup tells Ember to serve setup route
|
||||
SiteModeSetup = "2"
|
||||
// SiteModeBadDB redirects to db-error.html page
|
||||
SiteModeBadDB = "3"
|
||||
)
|
||||
|
|
|
@ -18,6 +18,12 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// Param returns the requested paramater from route request.
|
||||
func Param(r *http.Request, p string) string {
|
||||
params := mux.Vars(r)
|
||||
return params[p]
|
||||
}
|
||||
|
||||
// Params returns the paramaters from route request.
|
||||
func Params(r *http.Request) map[string]string {
|
||||
return mux.Vars(r)
|
||||
|
|
|
@ -14,10 +14,7 @@ package response
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/documize/community/core/log"
|
||||
)
|
||||
|
||||
// Helper for writing consistent headers back to HTTP client
|
||||
|
@ -29,55 +26,43 @@ func writeStatus(w http.ResponseWriter, status int) {
|
|||
// WriteMissingDataError notifies HTTP client of missing data in request.
|
||||
func WriteMissingDataError(w http.ResponseWriter, method, parameter string) {
|
||||
writeStatus(w, http.StatusBadRequest)
|
||||
_, err := w.Write([]byte("{Error: 'Missing data'}"))
|
||||
log.IfErr(err)
|
||||
log.Info(fmt.Sprintf("Missing data %s for method %s", parameter, method))
|
||||
w.Write([]byte("{Error: 'Missing data'}"))
|
||||
}
|
||||
|
||||
// WriteNotFoundError notifies HTTP client of 'record not found' error.
|
||||
func WriteNotFoundError(w http.ResponseWriter, method string, id string) {
|
||||
writeStatus(w, http.StatusNotFound)
|
||||
_, err := w.Write([]byte("{Error: 'Not found'}"))
|
||||
log.IfErr(err)
|
||||
log.Info(fmt.Sprintf("Not found ID %s for method %s", id, method))
|
||||
w.Write([]byte("{Error: 'Not found'}"))
|
||||
}
|
||||
|
||||
// WriteServerError notifies HTTP client of general application error.
|
||||
func WriteServerError(w http.ResponseWriter, method string, err error) {
|
||||
writeStatus(w, http.StatusBadRequest)
|
||||
_, err2 := w.Write([]byte("{Error: 'Internal server error'}"))
|
||||
log.IfErr(err2)
|
||||
log.Error(fmt.Sprintf("Internal server error for method %s", method), err)
|
||||
w.Write([]byte("{Error: 'Internal server error'}"))
|
||||
}
|
||||
|
||||
// WriteDuplicateError notifies HTTP client of duplicate data that has been rejected.
|
||||
func WriteDuplicateError(w http.ResponseWriter, method, entity string) {
|
||||
writeStatus(w, http.StatusConflict)
|
||||
_, err := w.Write([]byte("{Error: 'Duplicate record'}"))
|
||||
log.IfErr(err)
|
||||
log.Info(fmt.Sprintf("Duplicate %s record detected for method %s", entity, method))
|
||||
w.Write([]byte("{Error: 'Duplicate record'}"))
|
||||
}
|
||||
|
||||
// WriteUnauthorizedError notifies HTTP client of rejected unauthorized request.
|
||||
func WriteUnauthorizedError(w http.ResponseWriter) {
|
||||
writeStatus(w, http.StatusUnauthorized)
|
||||
_, err := w.Write([]byte("{Error: 'Unauthorized'}"))
|
||||
log.IfErr(err)
|
||||
w.Write([]byte("{Error: 'Unauthorized'}"))
|
||||
}
|
||||
|
||||
// WriteForbiddenError notifies HTTP client of request that is not allowed.
|
||||
func WriteForbiddenError(w http.ResponseWriter) {
|
||||
writeStatus(w, http.StatusForbidden)
|
||||
_, err := w.Write([]byte("{Error: 'Forbidden'}"))
|
||||
log.IfErr(err)
|
||||
w.Write([]byte("{Error: 'Forbidden'}"))
|
||||
}
|
||||
|
||||
// WriteBadRequestError notifies HTTP client of rejected request due to bad data within request.
|
||||
func WriteBadRequestError(w http.ResponseWriter, method, message string) {
|
||||
writeStatus(w, http.StatusBadRequest)
|
||||
_, err := w.Write([]byte("{Error: 'Bad Request'}"))
|
||||
log.IfErr(err)
|
||||
log.Info(fmt.Sprintf("Bad Request %s for method %s", message, method))
|
||||
w.Write([]byte("{Error: 'Bad Request'}"))
|
||||
}
|
||||
|
||||
// WriteBadLicense notifies HTTP client of invalid license (402)
|
||||
|
@ -87,44 +72,34 @@ func WriteBadLicense(w http.ResponseWriter) {
|
|||
var e struct {
|
||||
Reason string
|
||||
}
|
||||
|
||||
e.Reason = "invalid or expired Documize license"
|
||||
|
||||
j, _ := json.Marshal(e)
|
||||
_, err := w.Write(j)
|
||||
log.IfErr(err)
|
||||
w.Write(j)
|
||||
}
|
||||
|
||||
// WriteBytes dumps bytes to HTTP response
|
||||
func WriteBytes(w http.ResponseWriter, data []byte) {
|
||||
writeStatus(w, http.StatusOK)
|
||||
_, err := w.Write(data)
|
||||
log.IfErr(err)
|
||||
w.Write(data)
|
||||
}
|
||||
|
||||
// WriteString writes string to HTTP response
|
||||
func WriteString(w http.ResponseWriter, data string) {
|
||||
writeStatus(w, http.StatusOK)
|
||||
_, err := w.Write([]byte(data))
|
||||
log.IfErr(err)
|
||||
w.Write([]byte(data))
|
||||
}
|
||||
|
||||
// WriteEmpty writes empty JSON HTTP response
|
||||
func WriteEmpty(w http.ResponseWriter) {
|
||||
writeStatus(w, http.StatusOK)
|
||||
_, err := w.Write([]byte("{}"))
|
||||
log.IfErr(err)
|
||||
w.Write([]byte("{}"))
|
||||
}
|
||||
|
||||
// WriteJSON serializes data as JSON to HTTP response.
|
||||
func WriteJSON(w http.ResponseWriter, v interface{}) {
|
||||
writeStatus(w, http.StatusOK)
|
||||
|
||||
j, err := json.Marshal(v)
|
||||
|
||||
if err != nil {
|
||||
log.IfErr(err)
|
||||
}
|
||||
|
||||
_, err = w.Write(j)
|
||||
log.IfErr(err)
|
||||
j, _ := json.Marshal(v)
|
||||
w.Write(j)
|
||||
}
|
||||
|
|
42
core/timeutil/nulltime.go
Normal file
42
core/timeutil/nulltime.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
// Source: https://github.com/lib/pq/blob/b269bd035a727d6c1081f76e7a239a1b00674c40/encode.go#L521
|
||||
//
|
||||
// Copyright (c) 2011-2013, 'pq' Contributors Portions Copyright (C) 2011 Blake Mizerany
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// Package timeutil provides date and time related types and helpers.
|
||||
package timeutil
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NullTime represents a time.Time that may be null. NullTime implements the
|
||||
// sql.Scanner interface so it can be used as a scan destination, similar to
|
||||
// sql.NullString.
|
||||
type NullTime struct {
|
||||
Time time.Time
|
||||
Valid bool // Valid is true if Time is not NULL
|
||||
}
|
||||
|
||||
// Scan implements the Scanner interface.
|
||||
func (nt *NullTime) Scan(value interface{}) error {
|
||||
nt.Time, nt.Valid = value.(time.Time)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver Valuer interface.
|
||||
func (nt NullTime) Value() (driver.Value, error) {
|
||||
if !nt.Valid {
|
||||
return nil, nil
|
||||
}
|
||||
return nt.Time, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue