1
0
Fork 0
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:
Harvey Kandola 2017-07-24 16:24:21 +01:00
parent 25b576f861
commit 792c3e2ce8
46 changed files with 3403 additions and 171 deletions

View file

@ -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
}

View file

@ -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 {

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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
View file

@ -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
View file

@ -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"
)

View file

@ -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)

View file

@ -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
View 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
}