Fixed multiple bugs, cleaned up logging calls

This commit is contained in:
Gabriel Herbert
2025-05-20 12:16:10 +02:00
parent 80cf30bef6
commit 8b3587f536
61 changed files with 589 additions and 527 deletions

View File

@@ -33,14 +33,14 @@ func Run() error {
config.GetUint64("backupWeekly") == 0 && config.GetUint64("backupWeekly") == 0 &&
config.GetUint64("backupMonthly") == 0 { config.GetUint64("backupMonthly") == 0 {
log.Info("backup", "no backup jobs active, do nothing") log.Info(log.ContextBackup, "no backup jobs active, do nothing")
return nil return nil
} }
// initialize state // initialize state
if config.GetString("backupDir") == "" { if config.GetString("backupDir") == "" {
err := errors.New("backup directory not defined") err := errors.New("backup directory not defined")
log.Error("backup", "could not start", err) log.Error(log.ContextBackup, "could not start", err)
return err return err
} }
@@ -55,7 +55,7 @@ func Run() error {
jobRan := false // limit to one job per run jobRan := false // limit to one job per run
var runOne = func(jobName string, keepVersions uint64, interval int64) error { var runOne = func(jobName string, keepVersions uint64, interval int64) error {
log.Info("backup", fmt.Sprintf("is considering job '%s' for execution", jobName)) log.Info(log.ContextBackup, fmt.Sprintf("is considering job '%s' for execution", jobName))
var timestampLatest int64 var timestampLatest int64
for _, backup := range tocFile.Backups { for _, backup := range tocFile.Backups {
@@ -65,16 +65,16 @@ func Run() error {
} }
if timestampLatest > (now - interval) { if timestampLatest > (now - interval) {
log.Info("backup", fmt.Sprintf("does not need to execute '%s', latest backup is still valid", jobName)) log.Info(log.ContextBackup, fmt.Sprintf("does not need to execute '%s', latest backup is still valid", jobName))
return nil return nil
} }
if err := jobCleanup(&tocFile, jobName, keepVersions); err != nil { if err := jobCleanup(&tocFile, jobName, keepVersions); err != nil {
log.Error("backup", fmt.Sprintf("could not delete old versions of job '%s'", jobName), err) log.Error(log.ContextBackup, fmt.Sprintf("could not delete old versions of job '%s'", jobName), err)
return err return err
} }
if err := jobBackup(&tocFile, jobName); err != nil { if err := jobBackup(&tocFile, jobName); err != nil {
log.Error("backup", fmt.Sprintf("could not execute job '%s'", jobName), err) log.Error(log.ContextBackup, fmt.Sprintf("could not execute job '%s'", jobName), err)
return err return err
} }
jobRan = true jobRan = true
@@ -101,10 +101,10 @@ func Run() error {
func jobCleanup(tocFile *types.BackupTocFile, jobName string, countKeep uint64) error { func jobCleanup(tocFile *types.BackupTocFile, jobName string, countKeep uint64) error {
log.Info("backup", fmt.Sprintf("starting cleanup for job '%s', keep %d versions", log.Info(log.ContextBackup, fmt.Sprintf("starting cleanup for job '%s', keep %d versions",
jobName, countKeep)) jobName, countKeep))
defer log.Info("backup", fmt.Sprintf("finished cleanup for job '%s'", jobName)) defer log.Info(log.ContextBackup, fmt.Sprintf("finished cleanup for job '%s'", jobName))
// get current count // get current count
var countCurrent int var countCurrent int
@@ -114,7 +114,7 @@ func jobCleanup(tocFile *types.BackupTocFile, jobName string, countKeep uint64)
} }
} }
log.Info("backup", fmt.Sprintf("found %d versions for job '%s'", countCurrent, jobName)) log.Info(log.ContextBackup, fmt.Sprintf("found %d versions for job '%s'", countCurrent, jobName))
// delete not-kept versions // delete not-kept versions
// if 3 are to be kept, delete all but 2 (to make room for next backup) // if 3 are to be kept, delete all but 2 (to make room for next backup)
@@ -131,7 +131,7 @@ func jobCleanup(tocFile *types.BackupTocFile, jobName string, countKeep uint64)
} }
pathToDelete := getBackupJobDir(timestampToDelete, jobName) pathToDelete := getBackupJobDir(timestampToDelete, jobName)
log.Info("backup", fmt.Sprintf("is attempting to delete '%s'", pathToDelete)) log.Info(log.ContextBackup, fmt.Sprintf("is attempting to delete '%s'", pathToDelete))
exists, err := tools.Exists(pathToDelete) exists, err := tools.Exists(pathToDelete)
if err != nil { if err != nil {
@@ -151,12 +151,12 @@ func jobCleanup(tocFile *types.BackupTocFile, jobName string, countKeep uint64)
if err := tocFileWrite(*tocFile); err != nil { if err := tocFileWrite(*tocFile); err != nil {
return err return err
} }
log.Info("backup", fmt.Sprintf("has successfully deleted '%s'", pathToDelete)) log.Info(log.ContextBackup, fmt.Sprintf("has successfully deleted '%s'", pathToDelete))
} }
return nil return nil
} }
func jobBackup(tocFile *types.BackupTocFile, jobName string) error { func jobBackup(tocFile *types.BackupTocFile, jobName string) error {
log.Info("backup", fmt.Sprintf("started for job '%s'", jobName)) log.Info(log.ContextBackup, fmt.Sprintf("started for job '%s'", jobName))
newTimestamp := tools.GetTimeUnix() newTimestamp := tools.GetTimeUnix()
jobDir := getBackupJobDir(newTimestamp, jobName) jobDir := getBackupJobDir(newTimestamp, jobName)
@@ -203,7 +203,7 @@ func jobBackup(tocFile *types.BackupTocFile, jobName string) error {
if err := tocFileWrite(*tocFile); err != nil { if err := tocFileWrite(*tocFile); err != nil {
return err return err
} }
log.Info("backup", fmt.Sprintf("successfully completed job '%s'", jobName)) log.Info(log.ContextBackup, fmt.Sprintf("successfully completed job '%s'", jobName))
return nil return nil
} }
@@ -230,7 +230,7 @@ func TocFileReadCreate() (types.BackupTocFile, error) {
exists, err := tools.Exists(path) exists, err := tools.Exists(path)
if err != nil { if err != nil {
log.Error("backup", "could not check existence of TOC file", err) log.Error(log.ContextBackup, "could not check existence of TOC file", err)
return tocFile, err return tocFile, err
} }
if !exists { if !exists {

2
cache/cache_cert.go vendored
View File

@@ -58,7 +58,7 @@ func CheckRenewCert() error {
} }
if file.ModTime().Unix() != certUnixMod { if file.ModTime().Unix() != certUnixMod {
log.Info("server", fmt.Sprintf("loading HTTP server certificate from '%s'", certPath)) log.Info(log.ContextServer, fmt.Sprintf("loading HTTP server certificate from '%s'", certPath))
cert, err = tls.LoadX509KeyPair(certPath, certPathKey) cert, err = tls.LoadX509KeyPair(certPath, certPathKey)
if err != nil { if err != nil {

View File

@@ -3,6 +3,7 @@ package cache
import ( import (
"context" "context"
"fmt" "fmt"
"r3/login/login_external"
"r3/login/login_metaMap" "r3/login/login_metaMap"
"r3/login/login_roleAssign" "r3/login/login_roleAssign"
"r3/types" "r3/types"
@@ -88,11 +89,11 @@ func LoadOauthClientMap_tx(ctx context.Context, tx pgx.Tx) error {
// retrieve login meta mapping // retrieve login meta mapping
for k, c := range oauthClientIdMap { for k, c := range oauthClientIdMap {
if c.Flow == oauthFlowAuthCodePkce { if c.Flow == oauthFlowAuthCodePkce {
c.LoginMetaMap, err = login_metaMap.Get_tx(ctx, tx, "oauth_client", c.Id) c.LoginMetaMap, err = login_metaMap.Get_tx(ctx, tx, login_external.EntityOauthClient, c.Id)
if err != nil { if err != nil {
return err return err
} }
c.LoginRolesAssign, err = login_roleAssign.Get_tx(ctx, tx, "oauth_client", c.Id) c.LoginRolesAssign, err = login_roleAssign.Get_tx(ctx, tx, login_external.EntityOauthClient, c.Id)
if err != nil { if err != nil {
return err return err
} }

32
cache/cache_schema.go vendored
View File

@@ -152,14 +152,14 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
Schema_mx.Lock() Schema_mx.Lock()
defer Schema_mx.Unlock() defer Schema_mx.Unlock()
log.Info("cache", fmt.Sprintf("starting schema processing for %d module(s)", len(moduleIds))) log.Info(log.ContextCache, fmt.Sprintf("starting schema processing for %d module(s)", len(moduleIds)))
mods, err := module.Get_tx(ctx, tx, moduleIds) mods, err := module.Get_tx(ctx, tx, moduleIds)
if err != nil { if err != nil {
return err return err
} }
for _, mod := range mods { for _, mod := range mods {
log.Info("cache", fmt.Sprintf("parsing module '%s'", mod.Name)) log.Info(log.ContextCache, fmt.Sprintf("parsing module '%s'", mod.Name))
mod.Relations = make([]types.Relation, 0) mod.Relations = make([]types.Relation, 0)
mod.Forms = make([]types.Form, 0) mod.Forms = make([]types.Form, 0)
mod.MenuTabs = make([]types.MenuTab, 0) mod.MenuTabs = make([]types.MenuTab, 0)
@@ -177,7 +177,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
ModuleApiNameMapId[mod.Name] = make(map[string]uuid.UUID) ModuleApiNameMapId[mod.Name] = make(map[string]uuid.UUID)
// get articles // get articles
log.Info("cache", "load articles") log.Info(log.ContextCache, "load articles")
mod.Articles, err = article.Get_tx(ctx, tx, mod.Id) mod.Articles, err = article.Get_tx(ctx, tx, mod.Id)
if err != nil { if err != nil {
@@ -185,7 +185,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// get relations // get relations
log.Info("cache", "load relations") log.Info(log.ContextCache, "load relations")
rels, err := relation.Get_tx(ctx, tx, mod.Id) rels, err := relation.Get_tx(ctx, tx, mod.Id)
if err != nil { if err != nil {
@@ -224,7 +224,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// get forms // get forms
log.Info("cache", "load forms") log.Info(log.ContextCache, "load forms")
mod.Forms, err = form.Get_tx(ctx, tx, mod.Id, []uuid.UUID{}) mod.Forms, err = form.Get_tx(ctx, tx, mod.Id, []uuid.UUID{})
if err != nil { if err != nil {
@@ -232,7 +232,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// get menu tabs // get menu tabs
log.Info("cache", "load menu tabs") log.Info(log.ContextCache, "load menu tabs")
mod.MenuTabs, err = menuTab.Get_tx(ctx, tx, mod.Id) mod.MenuTabs, err = menuTab.Get_tx(ctx, tx, mod.Id)
if err != nil { if err != nil {
@@ -240,7 +240,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// get icons // get icons
log.Info("cache", "load icons") log.Info(log.ContextCache, "load icons")
mod.Icons, err = icon.Get_tx(ctx, tx, mod.Id) mod.Icons, err = icon.Get_tx(ctx, tx, mod.Id)
if err != nil { if err != nil {
@@ -248,7 +248,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// get roles // get roles
log.Info("cache", "load roles") log.Info(log.ContextCache, "load roles")
mod.Roles, err = role.Get_tx(ctx, tx, mod.Id) mod.Roles, err = role.Get_tx(ctx, tx, mod.Id)
if err != nil { if err != nil {
@@ -261,7 +261,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// get login forms // get login forms
log.Info("cache", "load login forms") log.Info(log.ContextCache, "load login forms")
mod.LoginForms, err = loginForm.Get_tx(ctx, tx, mod.Id) mod.LoginForms, err = loginForm.Get_tx(ctx, tx, mod.Id)
if err != nil { if err != nil {
@@ -275,7 +275,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// store & backfill PG functions // store & backfill PG functions
log.Info("cache", "load PG functions") log.Info(log.ContextCache, "load PG functions")
mod.PgFunctions, err = pgFunction.Get_tx(ctx, tx, mod.Id) mod.PgFunctions, err = pgFunction.Get_tx(ctx, tx, mod.Id)
if err != nil { if err != nil {
@@ -286,7 +286,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// get JS functions // get JS functions
log.Info("cache", "load JS functions") log.Info(log.ContextCache, "load JS functions")
mod.JsFunctions, err = jsFunction.Get_tx(ctx, tx, mod.Id) mod.JsFunctions, err = jsFunction.Get_tx(ctx, tx, mod.Id)
if err != nil { if err != nil {
@@ -294,7 +294,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// get collections // get collections
log.Info("cache", "load collections") log.Info(log.ContextCache, "load collections")
mod.Collections, err = collection.Get_tx(ctx, tx, mod.Id) mod.Collections, err = collection.Get_tx(ctx, tx, mod.Id)
if err != nil { if err != nil {
@@ -302,7 +302,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// get APIs // get APIs
log.Info("cache", "load APIs") log.Info(log.ContextCache, "load APIs")
mod.Apis, err = api.Get_tx(ctx, tx, mod.Id, uuid.Nil) mod.Apis, err = api.Get_tx(ctx, tx, mod.Id, uuid.Nil)
if err != nil { if err != nil {
@@ -314,7 +314,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// get client events // get client events
log.Info("cache", "load client events") log.Info(log.ContextCache, "load client events")
mod.ClientEvents, err = clientEvent.Get_tx(ctx, tx, mod.Id) mod.ClientEvents, err = clientEvent.Get_tx(ctx, tx, mod.Id)
if err != nil { if err != nil {
@@ -325,7 +325,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// get variables // get variables
log.Info("cache", "load variables") log.Info(log.ContextCache, "load variables")
mod.Variables, err = variable.Get_tx(ctx, tx, mod.Id) mod.Variables, err = variable.Get_tx(ctx, tx, mod.Id)
if err != nil { if err != nil {
@@ -333,7 +333,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
} }
// get widgets // get widgets
log.Info("cache", "load widgets") log.Info(log.ContextCache, "load widgets")
mod.Widgets, err = widget.Get_tx(ctx, tx, mod.Id) mod.Widgets, err = widget.Get_tx(ctx, tx, mod.Id)
if err != nil { if err != nil {

View File

@@ -41,7 +41,7 @@ func CheckInNode() error {
} }
if tools.GetTimeUnix() > masterLastCheckIn+(int64(config.GetUint64("clusterNodeMissingAfter"))) { if tools.GetTimeUnix() > masterLastCheckIn+(int64(config.GetUint64("clusterNodeMissingAfter"))) {
log.Info("cluster", "node has recognized an absent master, requesting role for itself") log.Info(log.ContextCluster, "node has recognized an absent master, requesting role for itself")
// cluster master missing, request cluster master role for this node // cluster master missing, request cluster master role for this node
if _, err := db.Pool.Exec(context.Background(), ` if _, err := db.Pool.Exec(context.Background(), `
@@ -270,7 +270,7 @@ func LoginReauthorizedAll_tx(ctx context.Context, tx pgx.Tx, updateNodes bool) e
return nil return nil
} }
func MasterAssigned(state bool) error { func MasterAssigned(state bool) error {
log.Info("cluster", fmt.Sprintf("node has changed its master state to '%v'", state)) log.Info(log.ContextCluster, fmt.Sprintf("node has changed its master state to '%v'", state))
cache.SetIsClusterMaster(state) cache.SetIsClusterMaster(state)
// reload scheduler as most events should only be executed by the cluster master // reload scheduler as most events should only be executed by the cluster master

View File

@@ -155,19 +155,19 @@ func SetLicense(l types.License) {
license = l license = l
} }
func SetLogLevels() { func SetLogLevels() {
log.SetLogLevel("api", int(GetUint64("logApi"))) log.SetLogLevel(log.ContextApi, int(GetUint64("logApi")))
log.SetLogLevel("backup", int(GetUint64("logBackup"))) log.SetLogLevel(log.ContextBackup, int(GetUint64("logBackup")))
log.SetLogLevel("cache", int(GetUint64("logCache"))) log.SetLogLevel(log.ContextCache, int(GetUint64("logCache")))
log.SetLogLevel("cluster", int(GetUint64("logCluster"))) log.SetLogLevel(log.ContextCluster, int(GetUint64("logCluster")))
log.SetLogLevel("csv", int(GetUint64("logCsv"))) log.SetLogLevel(log.ContextCsv, int(GetUint64("logCsv")))
log.SetLogLevel("imager", int(GetUint64("logImager"))) log.SetLogLevel(log.ContextImager, int(GetUint64("logImager")))
log.SetLogLevel("ldap", int(GetUint64("logLdap"))) log.SetLogLevel(log.ContextLdap, int(GetUint64("logLdap")))
log.SetLogLevel("mail", int(GetUint64("logMail"))) log.SetLogLevel(log.ContextMail, int(GetUint64("logMail")))
log.SetLogLevel("module", int(GetUint64("logModule"))) log.SetLogLevel(log.ContextModule, int(GetUint64("logModule")))
log.SetLogLevel("scheduler", int(GetUint64("logScheduler"))) log.SetLogLevel(log.ContextScheduler, int(GetUint64("logScheduler")))
log.SetLogLevel("server", int(GetUint64("logServer"))) log.SetLogLevel(log.ContextServer, int(GetUint64("logServer")))
log.SetLogLevel("transfer", int(GetUint64("logTransfer"))) log.SetLogLevel(log.ContextTransfer, int(GetUint64("logTransfer")))
log.SetLogLevel("websocket", int(GetUint64("logWebsocket"))) log.SetLogLevel(log.ContextWebsocket, int(GetUint64("logWebsocket")))
} }
func SetInstanceIdIfEmpty_tx(ctx context.Context, tx pgx.Tx) error { func SetInstanceIdIfEmpty_tx(ctx context.Context, tx pgx.Tx) error {
if GetString("instanceId") != "" { if GetString("instanceId") != "" {

View File

@@ -67,7 +67,7 @@ vCPF8QXc4V/wgJZtn6vdSXGR5W0dByItU5TLOlk6kLX4Aj6G8T+J//7NX5InD5Q/
func ActivateLicense() { func ActivateLicense() {
if GetString("licenseFile") == "" { if GetString("licenseFile") == "" {
log.Info("server", "skipping activation check, no license installed") log.Info(log.ContextServer, "skipping activation check, no license installed")
// set empty in case license was removed // set empty in case license was removed
SetLicense(types.License{}) SetLicense(types.License{})
@@ -77,13 +77,13 @@ func ActivateLicense() {
var licFile types.LicenseFile var licFile types.LicenseFile
if err := json.Unmarshal([]byte(GetString("licenseFile")), &licFile); err != nil { if err := json.Unmarshal([]byte(GetString("licenseFile")), &licFile); err != nil {
log.Error("server", "could not unmarshal license from config", err) log.Error(log.ContextServer, "could not unmarshal license from config", err)
return return
} }
licenseJson, err := json.Marshal(licFile.License) licenseJson, err := json.Marshal(licFile.License)
if err != nil { if err != nil {
log.Error("server", "could not marshal license data", err) log.Error(log.ContextServer, "could not marshal license data", err)
return return
} }
hashed := sha256.Sum256(licenseJson) hashed := sha256.Sum256(licenseJson)
@@ -91,34 +91,34 @@ func ActivateLicense() {
// get license signature // get license signature
signature, err := base64.URLEncoding.DecodeString(licFile.Signature) signature, err := base64.URLEncoding.DecodeString(licFile.Signature)
if err != nil { if err != nil {
log.Error("server", "could not decode license signature", err) log.Error(log.ContextServer, "could not decode license signature", err)
return return
} }
// verify signature // verify signature
data, _ := pem.Decode([]byte(publicKey)) data, _ := pem.Decode([]byte(publicKey))
if data == nil { if data == nil {
log.Error("server", "could not decode public key", errors.New("")) log.Error(log.ContextServer, "could not decode public key", errors.New(""))
return return
} }
key, err := x509.ParsePKCS1PublicKey(data.Bytes) key, err := x509.ParsePKCS1PublicKey(data.Bytes)
if err != nil { if err != nil {
log.Error("server", "could not parse public key", errors.New("")) log.Error(log.ContextServer, "could not parse public key", errors.New(""))
return return
} }
if err := rsa.VerifyPKCS1v15(key, crypto.SHA256, hashed[:], signature); err != nil { if err := rsa.VerifyPKCS1v15(key, crypto.SHA256, hashed[:], signature); err != nil {
log.Error("server", "failed to verify license", err) log.Error(log.ContextServer, "failed to verify license", err)
return return
} }
// check if license has been revoked // check if license has been revoked
if slices.Contains(revocations, licFile.License.LicenseId) { if slices.Contains(revocations, licFile.License.LicenseId) {
log.Error("server", "failed to enable license", fmt.Errorf("license ID '%s' has been revoked", licFile.License.LicenseId)) log.Error(log.ContextServer, "failed to enable license", fmt.Errorf("license ID '%s' has been revoked", licFile.License.LicenseId))
return return
} }
// set license // set license
log.Info("server", "setting license") log.Info(log.ContextServer, "setting license")
SetLicense(licFile.License) SetLicense(licFile.License)
} }

View File

@@ -94,7 +94,7 @@ func GetString(name string) string {
defer access_mx.RUnlock() defer access_mx.RUnlock()
if _, exists := storeString[name]; !exists { if _, exists := storeString[name]; !exists {
log.Error("server", "configuration store get error", log.Error(log.ContextServer, "configuration store get error",
fmt.Errorf("string value '%s' does not exist", name)) fmt.Errorf("string value '%s' does not exist", name))
return "" return ""
@@ -106,7 +106,7 @@ func GetUint64(name string) uint64 {
defer access_mx.RUnlock() defer access_mx.RUnlock()
if _, exists := storeUint64[name]; !exists { if _, exists := storeUint64[name]; !exists {
log.Error("server", "configuration store get error", log.Error(log.ContextServer, "configuration store get error",
fmt.Errorf("uint64 value '%s' does not exist", name)) fmt.Errorf("uint64 value '%s' does not exist", name))
return 0 return 0
@@ -118,7 +118,7 @@ func GetUint64Slice(name string) []uint64 {
defer access_mx.RUnlock() defer access_mx.RUnlock()
if _, exists := storeUint64Slice[name]; !exists { if _, exists := storeUint64Slice[name]; !exists {
log.Error("server", "configuration store get error", log.Error(log.ContextServer, "configuration store get error",
fmt.Errorf("uint64 slice value '%s' does not exist", name)) fmt.Errorf("uint64 slice value '%s' does not exist", name))
return make([]uint64, 0) return make([]uint64, 0)

View File

@@ -30,7 +30,7 @@ var (
func PrepareProcessing(filePathOverwrite string) { func PrepareProcessing(filePathOverwrite string) {
canProcess = setCheckConvertPath(filePathOverwrite) canProcess = setCheckConvertPath(filePathOverwrite)
log.Info("imager", fmt.Sprintf("started, processing capabilities: %v", canProcess)) log.Info(log.ContextImager, fmt.Sprintf("started, processing capabilities: %v", canProcess))
} }
func GetCanProcess() bool { func GetCanProcess() bool {
@@ -86,7 +86,7 @@ func processFile(fileId uuid.UUID, ext string, src string, dst string) {
// clean extension // clean extension
ext = strings.ToLower(strings.Replace(ext, ".", "", -1)) ext = strings.ToLower(strings.Replace(ext, ".", "", -1))
log.Info("imager", fmt.Sprintf("is working on file '%s' (%s)", fileId, ext)) log.Info(log.ContextImager, fmt.Sprintf("is working on file '%s' (%s)", fileId, ext))
defer func() { defer func() {
fileIdMapQueue_mx.Lock() fileIdMapQueue_mx.Lock()
@@ -107,7 +107,7 @@ func processFile(fileId uuid.UUID, ext string, src string, dst string) {
fileIdMapFailed[fileId] = true fileIdMapFailed[fileId] = true
fileIdMapFailed_mx.Unlock() fileIdMapFailed_mx.Unlock()
log.Warning("imager", "failed to create thumbnail", returnErr) log.Warning(log.ContextImager, "failed to create thumbnail", returnErr)
} }
// free up worker // free up worker
@@ -181,7 +181,7 @@ func processFile(fileId uuid.UUID, ext string, src string, dst string) {
"-annotate", "+10+40", fmt.Sprintf("%s", textThumb), dst} "-annotate", "+10+40", fmt.Sprintf("%s", textThumb), dst}
default: default:
log.Info("imager", fmt.Sprintf("skipped unsupported file extension '%s'", ext)) log.Info(log.ContextImager, fmt.Sprintf("skipped unsupported file extension '%s'", ext))
return return
} }

View File

@@ -229,7 +229,7 @@ func FromInterfaceValues_tx(ctx context.Context, tx pgx.Tx, loginId int64,
if !atr.Nullable && setAtr.Value == nil { if !atr.Nullable && setAtr.Value == nil {
rel := cache.RelationIdMap[atr.RelationId] rel := cache.RelationIdMap[atr.RelationId]
log.Info("csv", fmt.Sprintf("skips record on relation '%s', no value set for required attribute '%s'", log.Info(log.ContextCsv, fmt.Sprintf("skips record on relation '%s', no value set for required attribute '%s'",
rel.Name, atr.Name)) rel.Name, atr.Name))
badNulls = true badNulls = true

View File

@@ -58,7 +58,7 @@ func Stop() error {
} }
if !state { if !state {
log.Info("server", "embedded database already stopped") log.Info(log.ContextServer, "embedded database already stopped")
return nil return nil
} }
@@ -126,7 +126,7 @@ func execWaitFor(call string, args []string, waitFor []string, waitTime int) (st
if err != nil { if err != nil {
if err != io.EOF { if err != io.EOF {
// log error if not end-of-file // log error if not end-of-file
log.Error("server", "failed to read from std out", err) log.Error(log.ContextServer, "failed to read from std out", err)
} }
break break
} }

View File

@@ -38,19 +38,19 @@ func RunIfRequired() error {
// loop upgrade procedure until DB version matches application version // loop upgrade procedure until DB version matches application version
func startLoop() error { func startLoop() error {
log.Info("server", "version discrepancy (platform<->database) recognized, starting automatic upgrade") log.Info(log.ContextServer, "version discrepancy (platform<->database) recognized, starting automatic upgrade")
for { for {
// abort when versions match // abort when versions match
if config.GetAppVersion().Cut == config.GetDbVersionCut() { if config.GetAppVersion().Cut == config.GetDbVersionCut() {
log.Info("server", "version discrepancy has been resolved") log.Info(log.ContextServer, "version discrepancy has been resolved")
return nil return nil
} }
if err := oneIteration(config.GetDbVersionCut()); err != nil { if err := oneIteration(config.GetDbVersionCut()); err != nil {
return err return err
} }
log.Info("server", "upgrade successful") log.Info(log.ContextServer, "upgrade successful")
} }
return nil return nil
} }
@@ -67,7 +67,7 @@ func oneIteration(dbVersionCut string) error {
// log before upgrade because changes to log table index // log before upgrade because changes to log table index
// caused infinite lock when trying to log to DB afterwards // caused infinite lock when trying to log to DB afterwards
log.Info("server", fmt.Sprintf("DB version '%s' recognized, starting upgrade", log.Info(log.ContextServer, fmt.Sprintf("DB version '%s' recognized, starting upgrade",
dbVersionCut)) dbVersionCut))
// execute known DB upgrades // execute known DB upgrades
@@ -77,7 +77,7 @@ func oneIteration(dbVersionCut string) error {
} }
dbVersionCutNew, err := upgradeFunctions[dbVersionCut](ctx, tx) dbVersionCutNew, err := upgradeFunctions[dbVersionCut](ctx, tx)
if err != nil { if err != nil {
log.Error("server", "upgrade NOT successful", err) log.Error(log.ContextServer, "upgrade NOT successful", err)
return err return err
} }
@@ -177,8 +177,8 @@ var upgradeFunctions = map[string]func(ctx context.Context, tx pgx.Tx) (string,
ALTER TABLE instance.login_meta_map ADD CONSTRAINT login_meta_map_oauth_client_id_fkey ALTER TABLE instance.login_meta_map ADD CONSTRAINT login_meta_map_oauth_client_id_fkey
FOREIGN KEY (oauth_client_id) FOREIGN KEY (oauth_client_id)
REFERENCES instance.oauth_client (id) MATCH SIMPLE REFERENCES instance.oauth_client (id) MATCH SIMPLE
ON UPDATE NO ACTION ON UPDATE CASCADE
ON DELETE NO ACTION; ON DELETE CASCADE;
CREATE INDEX IF NOT EXISTS fki_login_meta_map_oauth_client_id_fkey CREATE INDEX IF NOT EXISTS fki_login_meta_map_oauth_client_id_fkey
ON instance.login_meta_map USING btree (oauth_client_id ASC NULLS LAST); ON instance.login_meta_map USING btree (oauth_client_id ASC NULLS LAST);
@@ -3084,7 +3084,7 @@ var upgradeFunctions = map[string]func(ctx context.Context, tx pgx.Tx) (string,
filepath.Join(config.File.Paths.Files, filepath.Join(config.File.Paths.Files,
fileId.String()[:3], fmt.Sprintf("%s_0", fileId))); err != nil { fileId.String()[:3], fmt.Sprintf("%s_0", fileId))); err != nil {
log.Warning("server", fmt.Sprintf("failed to move file '%s/%s' during platform upgrade", log.Warning(log.ContextServer, fmt.Sprintf("failed to move file '%s/%s' during platform upgrade",
fa.attributeId, fileId), err) fa.attributeId, fileId), err)
} }
} }

View File

@@ -47,7 +47,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
if errToLog == nil { if errToLog == nil {
errToLog = errors.New(errMsgUser) errToLog = errors.New(errMsgUser)
} }
handler.AbortRequestWithCode(w, "api", httpCode, errToLog, errMsgUser) handler.AbortRequestWithCode(w, handler.ContextApi, httpCode, errToLog, errMsgUser)
} }
ctx, ctxCanc := context.WithTimeout(context.Background(), ctx, ctxCanc := context.WithTimeout(context.Background(),
@@ -120,7 +120,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
} }
// URL processing complete, actually use API // URL processing complete, actually use API
log.Info("api", fmt.Sprintf("'%s.%s' (v%d) is called with %s (record ID: %d)", log.Info(log.ContextApi, fmt.Sprintf("'%s.%s' (v%d) is called with %s (record ID: %d)",
modName, apiName, version, r.Method, recordId)) modName, apiName, version, r.Method, recordId))
// resolve API by module+API names // resolve API by module+API names

View File

@@ -15,8 +15,6 @@ import (
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
var logContext = "api_auth"
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
if blocked := bruteforce.Check(r); blocked { if blocked := bruteforce.Check(r); blocked {
@@ -27,7 +25,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
if r.Method != "POST" { if r.Method != "POST" {
handler.AbortRequestWithCode(w, logContext, http.StatusBadRequest, handler.AbortRequestWithCode(w, handler.ContextApiAuth, http.StatusBadRequest,
errors.New("invalid HTTP method"), "invalid HTTP method, allowed: POST") errors.New("invalid HTTP method"), "invalid HTTP method, allowed: POST")
return return
@@ -39,7 +37,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
Password string `json:"password"` Password string `json:"password"`
} }
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
handler.AbortRequestWithCode(w, logContext, http.StatusBadRequest, handler.AbortRequestWithCode(w, handler.ContextApiAuth, http.StatusBadRequest,
err, "request body malformed") err, "request body malformed")
return return
@@ -53,7 +51,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate requestor // authenticate requestor
res, err := login_auth.User(ctx, req.Username, req.Password, pgtype.Int4{}, pgtype.Text{}) res, err := login_auth.User(ctx, req.Username, req.Password, pgtype.Int4{}, pgtype.Text{})
if err != nil { if err != nil {
handler.AbortRequestWithCode(w, logContext, http.StatusUnauthorized, handler.AbortRequestWithCode(w, handler.ContextApiAuth, http.StatusUnauthorized,
err, handler.ErrAuthFailed) err, handler.ErrAuthFailed)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
@@ -61,7 +59,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
} }
if len(res.MfaTokens) != 0 { if len(res.MfaTokens) != 0 {
handler.AbortRequestWithCode(w, logContext, http.StatusBadRequest, handler.AbortRequestWithCode(w, handler.ContextApiAuth, http.StatusBadRequest,
nil, "failed to authenticate, MFA is currently not supported") nil, "failed to authenticate, MFA is currently not supported")
return return

View File

@@ -9,28 +9,24 @@ import (
"time" "time"
) )
var (
handlerContext = "cache_download"
)
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
// parse getters // parse getters
moduleId, err := handler.ReadUuidGetterFromUrl(r, "module_id") moduleId, err := handler.ReadUuidGetterFromUrl(r, "module_id")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCacheDownload, err, handler.ErrGeneral)
return return
} }
dateChange, err := handler.ReadInt64GetterFromUrl(r, "date") dateChange, err := handler.ReadInt64GetterFromUrl(r, "date")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCacheDownload, err, handler.ErrGeneral)
return return
} }
// load JSON cache for requested module // load JSON cache for requested module
json, err := cache.GetModuleCacheJson(moduleId) json, err := cache.GetModuleCacheJson(moduleId)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCacheDownload, err, handler.ErrGeneral)
return return
} }

View File

@@ -11,8 +11,6 @@ import (
"time" "time"
) )
var logContext = "client_download"
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
if blocked := bruteforce.Check(r); blocked { if blocked := bruteforce.Check(r); blocked {
@@ -23,7 +21,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// get authentication token // get authentication token
token, err := handler.ReadGetterFromUrl(r, "token") token, err := handler.ReadGetterFromUrl(r, "token")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
@@ -34,7 +32,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate via token // authenticate via token
if _, err := login_auth.Token(ctx, token); err != nil { if _, err := login_auth.Token(ctx, token); err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrAuthFailed)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
return return
} }
@@ -42,7 +40,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// parse getters // parse getters
requestedOs, err := handler.ReadGetterFromUrl(r, "os") requestedOs, err := handler.ReadGetterFromUrl(r, "os")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
@@ -62,12 +60,12 @@ func Handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Disposition", "attachment; filename=r3_client.dmg") w.Header().Set("Content-Disposition", "attachment; filename=r3_client.dmg")
_, err = w.Write(cache.Client_amd64_mac) _, err = w.Write(cache.Client_amd64_mac)
default: default:
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
} }

View File

@@ -23,7 +23,7 @@ func HandlerConfig(w http.ResponseWriter, r *http.Request) {
// get authentication token // get authentication token
token, err := handler.ReadGetterFromUrl(r, "token") token, err := handler.ReadGetterFromUrl(r, "token")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
@@ -35,7 +35,7 @@ func HandlerConfig(w http.ResponseWriter, r *http.Request) {
// check token // check token
login, err := login_auth.Token(ctx, token) login, err := login_auth.Token(ctx, token)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrAuthFailed)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
return return
} }
@@ -43,32 +43,32 @@ func HandlerConfig(w http.ResponseWriter, r *http.Request) {
// parse getters // parse getters
tokenFixed, err := handler.ReadGetterFromUrl(r, "tokenFixed") tokenFixed, err := handler.ReadGetterFromUrl(r, "tokenFixed")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
hostName, err := handler.ReadGetterFromUrl(r, "hostName") hostName, err := handler.ReadGetterFromUrl(r, "hostName")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
hostPort, err := handler.ReadInt64GetterFromUrl(r, "hostPort") hostPort, err := handler.ReadInt64GetterFromUrl(r, "hostPort")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
languageCode, err := handler.ReadGetterFromUrl(r, "languageCode") languageCode, err := handler.ReadGetterFromUrl(r, "languageCode")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
deviceName, err := handler.ReadGetterFromUrl(r, "deviceName") deviceName, err := handler.ReadGetterFromUrl(r, "deviceName")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
ssl, err := handler.ReadInt64GetterFromUrl(r, "ssl") ssl, err := handler.ReadInt64GetterFromUrl(r, "ssl")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
@@ -114,12 +114,12 @@ func HandlerConfig(w http.ResponseWriter, r *http.Request) {
fJson, err := json.MarshalIndent(f, "", "\t") fJson, err := json.MarshalIndent(f, "", "\t")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
if _, err := w.Write(fJson); err != nil { if _, err := w.Write(fJson); err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral)
return return
} }
} }

View File

@@ -26,10 +26,6 @@ import (
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
var (
handlerContext = "csv_download"
)
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
if blocked := bruteforce.Check(r); blocked { if blocked := bruteforce.Check(r); blocked {
@@ -42,77 +38,77 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// read getters from URL // read getters from URL
token, err := handler.ReadGetterFromUrl(r, "token") token, err := handler.ReadGetterFromUrl(r, "token")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
commaChar, err := handler.ReadGetterFromUrl(r, "comma_char") commaChar, err := handler.ReadGetterFromUrl(r, "comma_char")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
dateFormat, err := handler.ReadGetterFromUrl(r, "date_format") dateFormat, err := handler.ReadGetterFromUrl(r, "date_format")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
timezone, err := handler.ReadGetterFromUrl(r, "timezone") timezone, err := handler.ReadGetterFromUrl(r, "timezone")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
boolFalse, err := handler.ReadGetterFromUrl(r, "bool_false") boolFalse, err := handler.ReadGetterFromUrl(r, "bool_false")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
boolTrue, err := handler.ReadGetterFromUrl(r, "bool_true") boolTrue, err := handler.ReadGetterFromUrl(r, "bool_true")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
ignoreHeaderString, err := handler.ReadGetterFromUrl(r, "ignore_header") ignoreHeaderString, err := handler.ReadGetterFromUrl(r, "ignore_header")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
relationIdString, err := handler.ReadGetterFromUrl(r, "relation_id") relationIdString, err := handler.ReadGetterFromUrl(r, "relation_id")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
joinsString, err := handler.ReadGetterFromUrl(r, "joins") joinsString, err := handler.ReadGetterFromUrl(r, "joins")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
expressionsString, err := handler.ReadGetterFromUrl(r, "expressions") expressionsString, err := handler.ReadGetterFromUrl(r, "expressions")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
filtersString, err := handler.ReadGetterFromUrl(r, "filters") filtersString, err := handler.ReadGetterFromUrl(r, "filters")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
ordersString, err := handler.ReadGetterFromUrl(r, "orders") ordersString, err := handler.ReadGetterFromUrl(r, "orders")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
totalLimitString, err := handler.ReadGetterFromUrl(r, "total_limit") totalLimitString, err := handler.ReadGetterFromUrl(r, "total_limit")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
columnsString, err := handler.ReadGetterFromUrl(r, "columns") columnsString, err := handler.ReadGetterFromUrl(r, "columns")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
var columns []types.Column var columns []types.Column
if err := json.Unmarshal([]byte(columnsString), &columns); err != nil { if err := json.Unmarshal([]byte(columnsString), &columns); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
@@ -121,36 +117,36 @@ func Handler(w http.ResponseWriter, r *http.Request) {
get.RelationId, err = uuid.FromString(relationIdString) get.RelationId, err = uuid.FromString(relationIdString)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
if err := json.Unmarshal([]byte(joinsString), &get.Joins); err != nil { if err := json.Unmarshal([]byte(joinsString), &get.Joins); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
if err := json.Unmarshal([]byte(expressionsString), &get.Expressions); err != nil { if err := json.Unmarshal([]byte(expressionsString), &get.Expressions); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
if err := json.Unmarshal([]byte(filtersString), &get.Filters); err != nil { if err := json.Unmarshal([]byte(filtersString), &get.Filters); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
if err := json.Unmarshal([]byte(ordersString), &get.Orders); err != nil { if err := json.Unmarshal([]byte(ordersString), &get.Orders); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
totalLimit, err := strconv.Atoi(totalLimitString) totalLimit, err := strconv.Atoi(totalLimitString)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
ignoreHeader := ignoreHeaderString == "true" ignoreHeader := ignoreHeaderString == "true"
// check invalid parameters // check invalid parameters
if len(get.Expressions) != len(columns) { if len(get.Expressions) != len(columns) {
handler.AbortRequest(w, handlerContext, errors.New("expression count != column count"), handler.AbortRequest(w, handler.ContextCsvDownload, errors.New("expression count != column count"),
handler.ErrGeneral) handler.ErrGeneral)
return return
@@ -164,7 +160,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate via token // authenticate via token
login, err := login_auth.Token(ctx, token) login, err := login_auth.Token(ctx, token)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrUnauthorized) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrUnauthorized)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
return return
} }
@@ -176,15 +172,15 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// prepare CSV file // prepare CSV file
filePath, err := tools.GetUniqueFilePath(config.File.Paths.Temp, 8999999, 9999999) filePath, err := tools.GetUniqueFilePath(config.File.Paths.Temp, 8999999, 9999999)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
log.Info("csv", fmt.Sprintf("starts export to file '%s' for download", filePath)) log.Info(log.ContextCsv, fmt.Sprintf("starts export to file '%s' for download", filePath))
file, err := os.Create(filePath) file, err := os.Create(filePath)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
defer file.Close() defer file.Close()
@@ -212,7 +208,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// fallback to attribute title // fallback to attribute title
atr, exists := cache.AttributeIdMap[expr.AttributeId.Bytes] atr, exists := cache.AttributeIdMap[expr.AttributeId.Bytes]
if !exists { if !exists {
handler.AbortRequest(w, handlerContext, handler.ErrSchemaUnknownAttribute(expr.AttributeId.Bytes), handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, handler.ErrSchemaUnknownAttribute(expr.AttributeId.Bytes), handler.ErrGeneral)
return return
} }
@@ -224,13 +220,13 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// fallback to attribute + relation name // fallback to attribute + relation name
rel, exists := cache.RelationIdMap[atr.RelationId] rel, exists := cache.RelationIdMap[atr.RelationId]
if !exists { if !exists {
handler.AbortRequest(w, handlerContext, handler.ErrSchemaUnknownRelation(atr.RelationId), handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, handler.ErrSchemaUnknownRelation(atr.RelationId), handler.ErrGeneral)
return return
} }
columnNames[i] = rel.Name + "." + atr.Name columnNames[i] = rel.Name + "." + atr.Name
} }
if err := writer.Write(columnNames); err != nil { if err := writer.Write(columnNames); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
} }
@@ -245,7 +241,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// load user location based on timezone for datetime values // load user location based on timezone for datetime values
locUser, err := time.LoadLocation(timezone) locUser, err := time.LoadLocation(timezone)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
@@ -254,7 +250,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
for i, column := range columns { for i, column := range columns {
atr, exists := cache.AttributeIdMap[column.AttributeId] atr, exists := cache.AttributeIdMap[column.AttributeId]
if !exists { if !exists {
handler.AbortRequest(w, handlerContext, nil, handler.AbortRequest(w, handler.ContextCsvDownload, nil,
handler.ErrSchemaUnknownAttribute(column.AttributeId).Error()) handler.ErrSchemaUnknownAttribute(column.AttributeId).Error())
return return
@@ -267,7 +263,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
dateFormat, columnAttributeContentUse, login.Id) dateFormat, columnAttributeContentUse, login.Id)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
@@ -280,11 +276,11 @@ func Handler(w http.ResponseWriter, r *http.Request) {
writer.Flush() writer.Flush()
if err := writer.Error(); err != nil { if err := writer.Error(); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }
if err := file.Close(); err != nil { if err := file.Close(); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral)
return return
} }

View File

@@ -27,8 +27,6 @@ import (
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
) )
var handlerContext = "csv_upload"
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
if blocked := bruteforce.Check(r); blocked { if blocked := bruteforce.Check(r); blocked {
@@ -40,7 +38,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
reader, err := r.MultipartReader() reader, err := r.MultipartReader()
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral)
return return
} }
@@ -73,17 +71,17 @@ func Handler(w http.ResponseWriter, r *http.Request) {
token = handler.GetStringFromPart(part) token = handler.GetStringFromPart(part)
case "columns": case "columns":
if err := json.Unmarshal(handler.GetBytesFromPart(part), &columns); err != nil { if err := json.Unmarshal(handler.GetBytesFromPart(part), &columns); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral)
return return
} }
case "joins": case "joins":
if err := json.Unmarshal(handler.GetBytesFromPart(part), &joins); err != nil { if err := json.Unmarshal(handler.GetBytesFromPart(part), &joins); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral)
return return
} }
case "lookups": case "lookups":
if err := json.Unmarshal(handler.GetBytesFromPart(part), &lookups); err != nil { if err := json.Unmarshal(handler.GetBytesFromPart(part), &lookups); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral)
return return
} }
case "boolTrue": case "boolTrue":
@@ -110,7 +108,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate via token // authenticate via token
login, err := login_auth.Token(ctx, token) login, err := login_auth.Token(ctx, token)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrUnauthorized) handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrUnauthorized)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
return return
} }
@@ -122,20 +120,20 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// store file in temporary directory // store file in temporary directory
filePath, err := tools.GetUniqueFilePath(config.File.Paths.Temp, 8999999, 9999999) filePath, err := tools.GetUniqueFilePath(config.File.Paths.Temp, 8999999, 9999999)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral)
return return
} }
dest, err := os.Create(filePath) dest, err := os.Create(filePath)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral)
return return
} }
defer os.Remove(filePath) defer os.Remove(filePath)
defer dest.Close() defer dest.Close()
if _, err := io.Copy(dest, part); err != nil { if _, err := io.Copy(dest, part); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral)
return return
} }
@@ -148,14 +146,15 @@ func Handler(w http.ResponseWriter, r *http.Request) {
res.Error = err.Error() res.Error = err.Error()
if !expectedErr { if !expectedErr {
log.Error("server", fmt.Sprintf("aborted %s request", handlerContext), err) handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral)
return
} }
} }
} }
resJson, err := json.Marshal(res) resJson, err := json.Marshal(res)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral)
return return
} }
w.Write(resJson) w.Write(resJson)
@@ -167,7 +166,7 @@ func importFromCsv(ctx context.Context, filePath string, loginId int64, boolTrue
dateFormat string, timezone string, commaChar string, ignoreHeader bool, columns []types.Column, dateFormat string, timezone string, commaChar string, ignoreHeader bool, columns []types.Column,
joins []types.QueryJoin, lookups []types.QueryLookup) (int, error) { joins []types.QueryJoin, lookups []types.QueryLookup) (int, error) {
log.Info("csv", fmt.Sprintf("starts import from file '%s' via upload", filePath)) log.Info(log.ContextCsv, fmt.Sprintf("starts import from file '%s' via upload", filePath))
file, err := os.Open(filePath) file, err := os.Open(filePath)
if err != nil { if err != nil {
@@ -217,7 +216,7 @@ func importFromCsv(ctx context.Context, filePath string, loginId int64, boolTrue
continue continue
} }
log.Info("csv", fmt.Sprintf("is importing line %d", importedCnt+1)) log.Info(log.ContextCsv, fmt.Sprintf("is importing line %d", importedCnt+1))
if err := importLine_tx(ctx, tx, loginId, boolTrue, dateFormat, locUser, if err := importLine_tx(ctx, tx, loginId, boolTrue, dateFormat, locUser,
values, columns, joins, lookups, indexMapPgIndexAttributeIds); err != nil { values, columns, joins, lookups, indexMapPgIndexAttributeIds); err != nil {

View File

@@ -24,10 +24,7 @@ type accessRequest struct {
Request json.RawMessage `json:"request"` Request json.RawMessage `json:"request"`
} }
var ( var allowedActions = []string{"del", "get", "set"}
allowedActions = []string{"del", "get", "set"}
handlerContext = "data_access"
)
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
@@ -39,7 +36,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
if r.Method != "POST" { if r.Method != "POST" {
handler.AbortRequest(w, handlerContext, errors.New("invalid HTTP method"), handler.AbortRequest(w, handler.ContextDataAccess, errors.New("invalid HTTP method"),
"invalid HTTP method, allowed: POST") "invalid HTTP method, allowed: POST")
return return
@@ -48,12 +45,12 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// parse body // parse body
var req accessRequest var req accessRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
handler.AbortRequest(w, handlerContext, err, "request body malformed") handler.AbortRequest(w, handler.ContextDataAccess, err, "request body malformed")
return return
} }
if !slices.Contains(allowedActions, req.Action) { if !slices.Contains(allowedActions, req.Action) {
handler.AbortRequest(w, handlerContext, errors.New("invalid action"), handler.AbortRequest(w, handler.ContextDataAccess, errors.New("invalid action"),
"invalid action, allowed: del, get, set") "invalid action, allowed: del, get, set")
return return
@@ -67,7 +64,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate requestor // authenticate requestor
login, err := login_auth.Token(ctx, req.Token) login, err := login_auth.Token(ctx, req.Token)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrAuthFailed) handler.AbortRequest(w, handler.ContextDataAccess, err, handler.ErrAuthFailed)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
return return
} }
@@ -75,29 +72,29 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// execute request // execute request
tx, err := db.Pool.Begin(ctx) tx, err := db.Pool.Begin(ctx)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataAccess, err, handler.ErrGeneral)
return return
} }
defer tx.Rollback(ctx) defer tx.Rollback(ctx)
log.Info("server", fmt.Sprintf("DIRECT ACCESS, %s data, payload: %s", req.Action, req.Request)) log.Info(log.ContextServer, fmt.Sprintf("DIRECT ACCESS, %s data, payload: %s", req.Action, req.Request))
res, err := request.Exec_tx(ctx, tx, "", login.Id, login.Admin, res, err := request.Exec_tx(ctx, tx, "", login.Id, login.Admin,
types.WebsocketClientDeviceBrowser, login.NoAuth, "data", req.Action, req.Request) types.WebsocketClientDeviceBrowser, login.NoAuth, "data", req.Action, req.Request)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataAccess, err, handler.ErrGeneral)
return return
} }
if err := tx.Commit(ctx); err != nil { if err := tx.Commit(ctx); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataAccess, err, handler.ErrGeneral)
return return
} }
resJson, err := json.Marshal(res) resJson, err := json.Marshal(res)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataAccess, err, handler.ErrGeneral)
return return
} }
w.Write(resJson) w.Write(resJson)

View File

@@ -15,8 +15,6 @@ import (
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
var logContext = "data_auth"
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
if blocked := bruteforce.Check(r); blocked { if blocked := bruteforce.Check(r); blocked {
@@ -27,7 +25,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
if r.Method != "POST" { if r.Method != "POST" {
handler.AbortRequest(w, logContext, errors.New("invalid HTTP method"), handler.AbortRequest(w, handler.ContextDataAuth, errors.New("invalid HTTP method"),
"invalid HTTP method, allowed: POST") "invalid HTTP method, allowed: POST")
return return
@@ -39,7 +37,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
Password string `json:"password"` Password string `json:"password"`
} }
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
handler.AbortRequest(w, logContext, err, "request body malformed") handler.AbortRequest(w, handler.ContextDataAuth, err, "request body malformed")
return return
} }
@@ -51,7 +49,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate requestor // authenticate requestor
res, err := login_auth.User(ctx, req.Username, req.Password, pgtype.Int4{}, pgtype.Text{}) res, err := login_auth.User(ctx, req.Username, req.Password, pgtype.Int4{}, pgtype.Text{})
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) handler.AbortRequest(w, handler.ContextDataAuth, err, handler.ErrAuthFailed)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
return return
} }

View File

@@ -14,8 +14,6 @@ import (
"time" "time"
) )
var logContext = "data_download"
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
if blocked := bruteforce.Check(r); blocked { if blocked := bruteforce.Check(r); blocked {
@@ -26,7 +24,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// get authentication token // get authentication token
token, err := handler.ReadGetterFromUrl(r, "token") token, err := handler.ReadGetterFromUrl(r, "token")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataDownload, err, handler.ErrGeneral)
return return
} }
@@ -38,7 +36,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate via token // authenticate via token
login, err := login_auth.Token(ctx, token) login, err := login_auth.Token(ctx, token)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) handler.AbortRequest(w, handler.ContextDataDownload, err, handler.ErrAuthFailed)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
return return
} }
@@ -46,18 +44,18 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// parse other getters // parse other getters
attributeId, err := handler.ReadUuidGetterFromUrl(r, "attribute_id") attributeId, err := handler.ReadUuidGetterFromUrl(r, "attribute_id")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataDownload, err, handler.ErrGeneral)
return return
} }
fileId, err := handler.ReadUuidGetterFromUrl(r, "file_id") fileId, err := handler.ReadUuidGetterFromUrl(r, "file_id")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataDownload, err, handler.ErrGeneral)
return return
} }
// check file access privilege // check file access privilege
if err := data.MayAccessFile(login.Id, attributeId); err != nil { if err := data.MayAccessFile(login.Id, attributeId); err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrUnauthorized) handler.AbortRequest(w, handler.ContextDataDownload, err, handler.ErrUnauthorized)
return return
} }
@@ -70,7 +68,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
if version == -1 { if version == -1 {
version, err = data.FileGetLatestVersion(fileId) version, err = data.FileGetLatestVersion(fileId)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataDownload, err, handler.ErrGeneral)
return return
} }
} }

View File

@@ -15,8 +15,6 @@ import (
"time" "time"
) )
var logContext = "data_download_thumb"
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
if blocked := bruteforce.Check(r); blocked { if blocked := bruteforce.Check(r); blocked {
@@ -33,7 +31,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// get authentication token // get authentication token
token, err := handler.ReadGetterFromUrl(r, "token") token, err := handler.ReadGetterFromUrl(r, "token")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrGeneral)
return return
} }
@@ -45,7 +43,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate via token // authenticate via token
login, err := login_auth.Token(ctx, token) login, err := login_auth.Token(ctx, token)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrAuthFailed)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
return return
} }
@@ -53,18 +51,18 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// parse other getters // parse other getters
attributeId, err := handler.ReadUuidGetterFromUrl(r, "attribute_id") attributeId, err := handler.ReadUuidGetterFromUrl(r, "attribute_id")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrGeneral)
return return
} }
fileId, err := handler.ReadUuidGetterFromUrl(r, "file_id") fileId, err := handler.ReadUuidGetterFromUrl(r, "file_id")
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrGeneral)
return return
} }
// check file access privilege // check file access privilege
if err := data.MayAccessFile(login.Id, attributeId); err != nil { if err := data.MayAccessFile(login.Id, attributeId); err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrUnauthorized) handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrUnauthorized)
return return
} }
@@ -73,7 +71,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
_, err = os.Stat(filePath) _, err = os.Stat(filePath)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrGeneral)
return return
} }
@@ -84,7 +82,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
version, err := data.FileGetLatestVersion(fileId) version, err := data.FileGetLatestVersion(fileId)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrGeneral)
return return
} }
filePathSrc := data.GetFilePathVersion(fileId, version) filePathSrc := data.GetFilePathVersion(fileId, version)

View File

@@ -16,8 +16,6 @@ import (
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
) )
var logContext = "data_upload"
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
if blocked := bruteforce.Check(r); blocked { if blocked := bruteforce.Check(r); blocked {
@@ -29,7 +27,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
reader, err := r.MultipartReader() reader, err := r.MultipartReader()
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrGeneral)
return return
} }
@@ -74,7 +72,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate via token // authenticate via token
login, err := login_auth.Token(ctx, token) login, err := login_auth.Token(ctx, token)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrAuthFailed)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
return return
} }
@@ -82,14 +80,14 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// parse attribute ID // parse attribute ID
attributeId, err := uuid.FromString(attributeIdString) attributeId, err := uuid.FromString(attributeIdString)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrGeneral)
return return
} }
// parse file ID // parse file ID
fileId, err := uuid.FromString(fileIdString) fileId, err := uuid.FromString(fileIdString)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrGeneral)
return return
} }
@@ -98,13 +96,13 @@ func Handler(w http.ResponseWriter, r *http.Request) {
if isNewFile { if isNewFile {
fileId, err = uuid.NewV4() fileId, err = uuid.NewV4()
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrGeneral)
return return
} }
} }
if err := data.SetFile(ctx, login.Id, attributeId, fileId, part, isNewFile); err != nil { if err := data.SetFile(ctx, login.Id, attributeId, fileId, part, isNewFile); err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrGeneral)
return return
} }
response.Id = fileId response.Id = fileId
@@ -112,7 +110,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
responseJson, err := json.Marshal(response) responseJson, err := json.Marshal(response)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrGeneral)
return return
} }
w.Write(responseJson) w.Write(responseJson)

View File

@@ -12,7 +12,46 @@ import (
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
) )
type handlerContext int
const (
ContextApi handlerContext = 10
ContextApiAuth handlerContext = 20
ContextCacheDownload handlerContext = 30
ContextClientDownload handlerContext = 40
ContextCsvDownload handlerContext = 50
ContextCsvUpload handlerContext = 60
ContextDataAccess handlerContext = 70
ContextDataAuth handlerContext = 80
ContextDataDownload handlerContext = 90
ContextDataDownloadThumb handlerContext = 100
ContextDataUpload handlerContext = 110
ContextIconUpload handlerContext = 120
ContextIcsUpload handlerContext = 130
ContextLicenseUpload handlerContext = 140
ContextManifestDownload handlerContext = 150
ContextWebsocket handlerContext = 160
)
var ( var (
ContextNameMap = map[handlerContext]string{
ContextApi: "api",
ContextApiAuth: "api_auth",
ContextCacheDownload: "cache_download",
ContextClientDownload: "client_download",
ContextCsvDownload: "csv_download",
ContextCsvUpload: "csv_upload",
ContextDataAccess: "data_access",
ContextDataAuth: "data_auth",
ContextDataDownload: "data_download",
ContextDataDownloadThumb: "data_download_thumb",
ContextDataUpload: "data_upload",
ContextIconUpload: "icon_upload",
ContextIcsUpload: "ics_download",
ContextLicenseUpload: "license_upload",
ContextManifestDownload: "manifest_download",
ContextWebsocket: "websocket",
}
NoImage []byte NoImage []byte
) )
@@ -53,14 +92,12 @@ func SetNoImage(v []byte) {
NoImage = v NoImage = v
} }
func AbortRequest(w http.ResponseWriter, context string, errToLog error, errMessageUser string) { func AbortRequest(w http.ResponseWriter, context handlerContext, errToLog error, errMessageUser string) {
AbortRequestWithCode(w, context, http.StatusBadRequest, errToLog, errMessageUser) AbortRequestWithCode(w, context, http.StatusBadRequest, errToLog, errMessageUser)
} }
func AbortRequestWithCode(w http.ResponseWriter, context string, func AbortRequestWithCode(w http.ResponseWriter, context handlerContext, httpCode int, errToLog error, errMessageUser string) {
httpCode int, errToLog error, errMessageUser string) { log.Error(log.ContextServer, fmt.Sprintf("aborted %s request", ContextNameMap[context]), errToLog)
log.Error("server", fmt.Sprintf("aborted %s request", context), errToLog)
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.WriteHeader(httpCode) w.WriteHeader(httpCode)

View File

@@ -17,8 +17,6 @@ import (
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
) )
var logContext = "icon_upload"
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
if blocked := bruteforce.Check(r); blocked { if blocked := bruteforce.Check(r); blocked {
@@ -30,7 +28,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
reader, err := r.MultipartReader() reader, err := r.MultipartReader()
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral)
return return
} }
@@ -71,56 +69,56 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate via token // authenticate via token
login, err := login_auth.Token(ctx, token) login, err := login_auth.Token(ctx, token)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrAuthFailed)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
return return
} }
if !login.Admin { if !login.Admin {
handler.AbortRequest(w, logContext, err, handler.ErrUnauthorized) handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrUnauthorized)
return return
} }
// parse module ID // parse module ID
moduleId, err := uuid.FromString(moduleIdString) moduleId, err := uuid.FromString(moduleIdString)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral)
return return
} }
// parse icon ID // parse icon ID
iconId, err := uuid.FromString(iconIdString) iconId, err := uuid.FromString(iconIdString)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral)
return return
} }
// insert/update icon // insert/update icon
tx, err := db.Pool.Begin(ctx) tx, err := db.Pool.Begin(ctx)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral)
return return
} }
defer tx.Rollback(ctx) defer tx.Rollback(ctx)
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if _, err := buf.ReadFrom(part); err != nil { if _, err := buf.ReadFrom(part); err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral)
return return
} }
// check size // check size
if int(len(buf.Bytes())/1024) > 64 { if int(len(buf.Bytes())/1024) > 64 {
handler.AbortRequest(w, logContext, errors.New("icon size > 64kb"), handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIconUpload, errors.New("icon size > 64kb"), handler.ErrGeneral)
return return
} }
if err := icon.Set_tx(ctx, tx, moduleId, iconId, "", buf.Bytes(), false); err != nil { if err := icon.Set_tx(ctx, tx, moduleId, iconId, "", buf.Bytes(), false); err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral)
return return
} }
if err := tx.Commit(ctx); err != nil { if err := tx.Commit(ctx); err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral)
return return
} }
} }

View File

@@ -25,8 +25,6 @@ import (
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
var handlerContext = "ics_download"
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
if config.GetUint64("icsDownload") != 1 { if config.GetUint64("icsDownload") != 1 {
@@ -45,17 +43,17 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// parse getters // parse getters
fieldId, err := handler.ReadUuidGetterFromUrl(r, "field_id") fieldId, err := handler.ReadUuidGetterFromUrl(r, "field_id")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral)
return return
} }
loginIdRequested, err := handler.ReadInt64GetterFromUrl(r, "login_id") loginIdRequested, err := handler.ReadInt64GetterFromUrl(r, "login_id")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral)
return return
} }
tokenFixed, err := handler.ReadGetterFromUrl(r, "token_fixed") tokenFixed, err := handler.ReadGetterFromUrl(r, "token_fixed")
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral)
return return
} }
@@ -67,7 +65,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate via fixed token // authenticate via fixed token
login, err := login_auth.TokenFixed(ctx, loginIdRequested, "ics", tokenFixed) login, err := login_auth.TokenFixed(ctx, loginIdRequested, "ics", tokenFixed)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrAuthFailed) handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrAuthFailed)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
return return
} }
@@ -75,20 +73,20 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// start DB transaction // start DB transaction
tx, err := db.Pool.Begin(ctx) tx, err := db.Pool.Begin(ctx)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral)
return return
} }
defer tx.Rollback(ctx) defer tx.Rollback(ctx)
if err := db.SetSessionConfig_tx(ctx, tx, login.Id); err != nil { if err := db.SetSessionConfig_tx(ctx, tx, login.Id); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral)
return return
} }
// get calendar field details from cache // get calendar field details from cache
f, err := cache.GetCalendarField_tx(ctx, tx, fieldId) f, err := cache.GetCalendarField_tx(ctx, tx, fieldId)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral)
return return
} }
@@ -198,7 +196,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
atr, exists := cache.AttributeIdMap[column.AttributeId] atr, exists := cache.AttributeIdMap[column.AttributeId]
if !exists { if !exists {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral)
return return
} }
if schema.IsContentFiles(atr.Content) { if schema.IsContentFiles(atr.Content) {
@@ -213,11 +211,11 @@ func Handler(w http.ResponseWriter, r *http.Request) {
var query string var query string
results, _, err := data.Get_tx(ctx, tx, dataGet, login.Id, &query) results, _, err := data.Get_tx(ctx, tx, dataGet, login.Id, &query)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral)
return return
} }
if err := tx.Commit(ctx); err != nil { if err := tx.Commit(ctx); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral)
return return
} }
@@ -240,7 +238,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
WHERE id = $1 WHERE id = $1
) )
`, f.OpenForm.FormIdOpen).Scan(&modName, &modNameParent); err != nil { `, f.OpenForm.FormIdOpen).Scan(&modName, &modNameParent); err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral)
return return
} }
@@ -270,7 +268,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
recordId, exists := result.IndexRecordIds[f.IndexDate0] recordId, exists := result.IndexRecordIds[f.IndexDate0]
if !exists { if !exists {
handler.AbortRequest(w, handlerContext, errors.New("record ID not found on date relation"), handler.AbortRequest(w, handler.ContextIcsUpload, errors.New("record ID not found on date relation"),
handler.ErrGeneral) handler.ErrGeneral)
return return
@@ -290,7 +288,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
reflect.TypeOf(result.Values[0]).String() != "int64" || reflect.TypeOf(result.Values[0]).String() != "int64" ||
reflect.TypeOf(result.Values[1]).String() != "int64" { reflect.TypeOf(result.Values[1]).String() != "int64" {
handler.AbortRequest(w, handlerContext, errors.New("invalid values for date"), handler.AbortRequest(w, handler.ContextIcsUpload, errors.New("invalid values for date"),
handler.ErrGeneral) handler.ErrGeneral)
return return

View File

@@ -15,8 +15,6 @@ import (
"time" "time"
) )
var logContext = "license_upload"
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
if blocked := bruteforce.Check(r); blocked { if blocked := bruteforce.Check(r); blocked {
@@ -28,7 +26,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
reader, err := r.MultipartReader() reader, err := r.MultipartReader()
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrGeneral)
return return
} }
@@ -57,47 +55,47 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate via token // authenticate via token
login, err := login_auth.Token(ctx, token) login, err := login_auth.Token(ctx, token)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrAuthFailed)
bruteforce.BadAttempt(r) bruteforce.BadAttempt(r)
return return
} }
if !login.Admin { if !login.Admin {
handler.AbortRequest(w, logContext, err, handler.ErrUnauthorized) handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrUnauthorized)
return return
} }
// read file into buffer // read file into buffer
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
if _, err := buf.ReadFrom(part); err != nil { if _, err := buf.ReadFrom(part); err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrGeneral)
return return
} }
// check size // check size
if int(len(buf.Bytes())/1024) > 64 { if int(len(buf.Bytes())/1024) > 64 {
handler.AbortRequest(w, logContext, errors.New("license file size > 64kb"), handler.ErrGeneral) handler.AbortRequest(w, handler.ContextLicenseUpload, errors.New("license file size > 64kb"), handler.ErrGeneral)
return return
} }
// set license // set license
tx, err := db.Pool.Begin(ctx) tx, err := db.Pool.Begin(ctx)
if err != nil { if err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrGeneral)
return return
} }
defer tx.Rollback(ctx) defer tx.Rollback(ctx)
if err := config.SetString_tx(ctx, tx, "licenseFile", buf.String()); err != nil { if err := config.SetString_tx(ctx, tx, "licenseFile", buf.String()); err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrGeneral)
return return
} }
if err := cluster.ConfigChanged_tx(ctx, tx, true, false, false); err != nil { if err := cluster.ConfigChanged_tx(ctx, tx, true, false, false); err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrGeneral)
return return
} }
if err := tx.Commit(ctx); err != nil { if err := tx.Commit(ctx); err != nil {
handler.AbortRequest(w, logContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrGeneral)
return return
} }
} }

View File

@@ -38,26 +38,23 @@ type manifest struct {
StartUrl string `json:"start_url"` StartUrl string `json:"start_url"`
} }
var ( var manifestDefault = manifest{
handlerContext = "manifest_download" Id: "platform",
manifestDefault = manifest{ Name: "REI3",
Id: "platform", ShortName: "REI3",
Name: "REI3", Scope: "/",
ShortName: "REI3", StartUrl: "/",
Scope: "/", Display: "standalone",
StartUrl: "/", Orientation: "any",
Display: "standalone", BackgroundColor: "#f5f5f5",
Orientation: "any", ThemeColor: "#444444",
BackgroundColor: "#f5f5f5", Icons: []icon{
ThemeColor: "#444444", {Purpose: "any", Sizes: "192x192", Src: "/images/icon_fav192.png", Type: "image/png"},
Icons: []icon{ {Purpose: "any", Sizes: "512x512", Src: "/images/icon_fav512.png", Type: "image/png"},
{Purpose: "any", Sizes: "192x192", Src: "/images/icon_fav192.png", Type: "image/png"}, {Purpose: "maskable", Sizes: "192x192", Src: "/images/icon_mask192.png", Type: "image/png"},
{Purpose: "any", Sizes: "512x512", Src: "/images/icon_fav512.png", Type: "image/png"}, {Purpose: "maskable", Sizes: "512x512", Src: "/images/icon_mask512.png", Type: "image/png"},
{Purpose: "maskable", Sizes: "192x192", Src: "/images/icon_mask192.png", Type: "image/png"}, },
{Purpose: "maskable", Sizes: "512x512", Src: "/images/icon_mask512.png", Type: "image/png"}, }
},
}
)
func Handler(w http.ResponseWriter, r *http.Request) { func Handler(w http.ResponseWriter, r *http.Request) {
@@ -103,7 +100,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
payloadJson, err := json.Marshal(manifestApp) payloadJson, err := json.Marshal(manifestApp)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextManifestDownload, err, handler.ErrGeneral)
return return
} }
@@ -120,13 +117,13 @@ func Handler(w http.ResponseWriter, r *http.Request) {
moduleId, err := uuid.FromString(elements[2]) moduleId, err := uuid.FromString(elements[2])
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextManifestDownload, err, handler.ErrGeneral)
return return
} }
module, exists := cache.ModuleIdMap[moduleId] module, exists := cache.ModuleIdMap[moduleId]
if !exists { if !exists {
handler.AbortRequest(w, handlerContext, handler.ErrSchemaUnknownModule(moduleId), handler.ErrGeneral) handler.AbortRequest(w, handler.ContextManifestDownload, handler.ErrSchemaUnknownModule(moduleId), handler.ErrGeneral)
return return
} }
@@ -135,7 +132,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
if module.ParentId.Valid { if module.ParentId.Valid {
parent, exists := cache.ModuleIdMap[module.ParentId.Bytes] parent, exists := cache.ModuleIdMap[module.ParentId.Bytes]
if !exists { if !exists {
handler.AbortRequest(w, handlerContext, handler.ErrSchemaUnknownModule(module.ParentId.Bytes), handler.ErrGeneral) handler.AbortRequest(w, handler.ContextManifestDownload, handler.ErrSchemaUnknownModule(module.ParentId.Bytes), handler.ErrGeneral)
return return
} }
parentName = parent.Name parentName = parent.Name
@@ -162,12 +159,12 @@ func Handler(w http.ResponseWriter, r *http.Request) {
if module.IconIdPwa1.Valid && module.IconIdPwa2.Valid { if module.IconIdPwa1.Valid && module.IconIdPwa2.Valid {
iconPwa1, err := cache.GetPwaIcon(module.IconIdPwa1.Bytes) iconPwa1, err := cache.GetPwaIcon(module.IconIdPwa1.Bytes)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextManifestDownload, err, handler.ErrGeneral)
return return
} }
iconPwa2, err := cache.GetPwaIcon(module.IconIdPwa2.Bytes) iconPwa2, err := cache.GetPwaIcon(module.IconIdPwa2.Bytes)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextManifestDownload, err, handler.ErrGeneral)
return return
} }
@@ -179,7 +176,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
payloadJson, err := json.Marshal(manifestMod) payloadJson, err := json.Marshal(manifestMod)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextManifestDownload, err, handler.ErrGeneral)
return return
} }

View File

@@ -21,7 +21,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// get authentication token // get authentication token
token, err := handler.ReadGetterFromUrl(r, "token") token, err := handler.ReadGetterFromUrl(r, "token")
if err != nil { if err != nil {
log.Error("server", genErr, err) log.Error(log.ContextServer, genErr, err)
return return
} }
@@ -31,34 +31,34 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// authenticate via token // authenticate via token
login, err := login_auth.Token(ctx, token) login, err := login_auth.Token(ctx, token)
if err != nil { if err != nil {
log.Error("server", genErr, err) log.Error(log.ContextServer, genErr, err)
return return
} }
if !login.Admin { if !login.Admin {
log.Error("server", genErr, errors.New(handler.ErrUnauthorized)) log.Error(log.ContextServer, genErr, errors.New(handler.ErrUnauthorized))
return return
} }
// get module ID // get module ID
moduleId, err := handler.ReadUuidGetterFromUrl(r, "module_id") moduleId, err := handler.ReadUuidGetterFromUrl(r, "module_id")
if err != nil { if err != nil {
log.Error("server", genErr, err) log.Error(log.ContextServer, genErr, err)
return return
} }
filePath, err := tools.GetUniqueFilePath(config.File.Paths.Temp, 8999999, 9999999) filePath, err := tools.GetUniqueFilePath(config.File.Paths.Temp, 8999999, 9999999)
if err != nil { if err != nil {
log.Error("server", genErr, err) log.Error(log.ContextServer, genErr, err)
return return
} }
if err := transfer.ExportToFile(ctx, moduleId, filePath); err != nil { if err := transfer.ExportToFile(ctx, moduleId, filePath); err != nil {
log.Error("server", genErr, err) log.Error(log.ContextServer, genErr, err)
return return
} }
http.ServeFile(w, r, filePath) http.ServeFile(w, r, filePath)
if err := os.Remove(filePath); err != nil { if err := os.Remove(filePath); err != nil {
log.Warning("server", "could not delete temporary export file", err) log.Warning(log.ContextServer, "could not delete temporary export file", err)
} }
} }

View File

@@ -25,7 +25,7 @@ func Handler(res http.ResponseWriter, req *http.Request) {
if err != nil { if err != nil {
res.WriteHeader(http.StatusBadRequest) res.WriteHeader(http.StatusBadRequest)
log.Error("server", "could not finish module import", err) log.Error(log.ContextServer, "could not finish module import", err)
} }
var response struct { var response struct {
@@ -35,7 +35,7 @@ func Handler(res http.ResponseWriter, req *http.Request) {
responseJson, err := json.Marshal(response) responseJson, err := json.Marshal(response)
if err != nil { if err != nil {
log.Error("server", "could not finish module import", err) log.Error(log.ContextServer, "could not finish module import", err)
res.Write([]byte{}) res.Write([]byte{})
return return
} }

View File

@@ -55,8 +55,6 @@ var (
ReadBufferSize: 1024, ReadBufferSize: 1024,
WriteBufferSize: 1024} WriteBufferSize: 1024}
handlerContext = "websocket"
hub = hubType{ hub = hubType{
clients: make(map[*clientType]bool), clients: make(map[*clientType]bool),
clientAdd: make(chan *clientType), clientAdd: make(chan *clientType),
@@ -87,21 +85,21 @@ func Handler(w http.ResponseWriter, r *http.Request) {
// get client host address // get client host address
host, _, err := net.SplitHostPort(r.RemoteAddr) host, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextWebsocket, err, handler.ErrGeneral)
return return
} }
// create unique client ID for session tracking // create unique client ID for session tracking
clientId, err := uuid.NewV4() clientId, err := uuid.NewV4()
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextWebsocket, err, handler.ErrGeneral)
return return
} }
// upgrade to websocket // upgrade to websocket
ws, err := clientUpgrader.Upgrade(w, r, nil) ws, err := clientUpgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) handler.AbortRequest(w, handler.ContextWebsocket, err, handler.ErrGeneral)
return return
} }
@@ -147,15 +145,15 @@ func (hub *hubType) start() {
delete(hub.clients, client) delete(hub.clients, client)
if wasKicked { if wasKicked {
log.Info(handlerContext, fmt.Sprintf("kicked client (login ID %d) at %s", client.loginId, client.address)) log.Info(log.ContextWebsocket, fmt.Sprintf("kicked client (login ID %d) at %s", client.loginId, client.address))
} else { } else {
log.Info(handlerContext, fmt.Sprintf("disconnected client (login ID %d) at %s", client.loginId, client.address)) log.Info(log.ContextWebsocket, fmt.Sprintf("disconnected client (login ID %d) at %s", client.loginId, client.address))
} }
go func() { go func() {
// run DB calls in async func as they must not block hub operations during heavy DB load // run DB calls in async func as they must not block hub operations during heavy DB load
if err := login_session.LogRemove(client.id); err != nil { if err := login_session.LogRemove(client.id); err != nil {
log.Error(handlerContext, "failed to remove login session log", err) log.Error(log.ContextWebsocket, "failed to remove login session log", err)
} }
}() }()
} }
@@ -211,7 +209,7 @@ func (hub *hubType) start() {
} }
if err != nil { if err != nil {
log.Error(handlerContext, "could not prepare unrequested transaction", err) log.Error(log.ContextWebsocket, "could not prepare unrequested transaction", err)
continue continue
} }
@@ -300,11 +298,11 @@ func (client *clientType) handleTransaction(reqTransJson json.RawMessage) json.R
// umarshal user input, this can always fail (never trust user input) // umarshal user input, this can always fail (never trust user input)
if err := json.Unmarshal(reqTransJson, &reqTrans); err != nil { if err := json.Unmarshal(reqTransJson, &reqTrans); err != nil {
log.Error(handlerContext, "failed to unmarshal transaction", err) log.Error(log.ContextWebsocket, "failed to unmarshal transaction", err)
return []byte("{}") return []byte("{}")
} }
log.Info(handlerContext, fmt.Sprintf("TRANSACTION %d, started by login ID %d (%s)", log.Info(log.ContextWebsocket, fmt.Sprintf("TRANSACTION %d, started by login ID %d (%s)",
reqTrans.TransactionNr, client.loginId, client.address)) reqTrans.TransactionNr, client.loginId, client.address))
// take over transaction number for response so client can match it locally // take over transaction number for response so client can match it locally
@@ -368,7 +366,7 @@ func (client *clientType) handleTransaction(reqTransJson json.RawMessage) json.R
} }
if err != nil { if err != nil {
log.Warning(handlerContext, "failed to authenticate user", err) log.Warning(log.ContextWebsocket, "failed to authenticate user", err)
bruteforce.BadAttemptByHost(client.address) bruteforce.BadAttemptByHost(client.address)
if handler.CheckForLicenseErrCode(err) { if handler.CheckForLicenseErrCode(err) {
@@ -396,10 +394,10 @@ func (client *clientType) handleTransaction(reqTransJson json.RawMessage) json.R
// authentication can return with no error but incomplete if MFA is on but 2nd factor not provided yet // authentication can return with no error but incomplete if MFA is on but 2nd factor not provided yet
// in this case the login ID is still 0 // in this case the login ID is still 0
if resTrans.Error == "" && client.loginId != 0 { if resTrans.Error == "" && client.loginId != 0 {
log.Info(handlerContext, fmt.Sprintf("authenticated client (login ID %d, admin: %v)", client.loginId, client.admin)) log.Info(log.ContextWebsocket, fmt.Sprintf("authenticated client (login ID %d, admin: %v)", client.loginId, client.admin))
if err := login_session.Log(client.id, client.loginId, client.address, client.device); err != nil { if err := login_session.Log(client.id, client.loginId, client.address, client.device); err != nil {
log.Error(handlerContext, "failed to create login session log", err) log.Error(log.ContextWebsocket, "failed to create login session log", err)
} }
} }
} }
@@ -407,7 +405,7 @@ func (client *clientType) handleTransaction(reqTransJson json.RawMessage) json.R
// marshal response transaction // marshal response transaction
resTransJson, err := json.Marshal(resTrans) resTransJson, err := json.Marshal(resTrans)
if err != nil { if err != nil {
log.Error(handlerContext, "cannot marshal responses", err) log.Error(log.ContextWebsocket, "cannot marshal responses", err)
return []byte("{}") return []byte("{}")
} }
return resTransJson return resTransJson

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"r3/cache" "r3/cache"
"r3/login" "r3/login"
"r3/login/login_external"
"r3/login/login_metaMap" "r3/login/login_metaMap"
"r3/login/login_roleAssign" "r3/login/login_roleAssign"
"r3/types" "r3/types"
@@ -13,7 +14,7 @@ import (
func Del_tx(ctx context.Context, tx pgx.Tx, id int32) error { func Del_tx(ctx context.Context, tx pgx.Tx, id int32) error {
if err := login.DelByLdap_tx(ctx, tx, id); err != nil { if err := login.DelByExternalProvider_tx(ctx, tx, login_external.EntityLdap, id); err != nil {
return err return err
} }
@@ -84,7 +85,7 @@ func Get_tx(ctx context.Context, tx pgx.Tx) ([]types.Ldap, error) {
} }
for i, _ := range ldaps { for i, _ := range ldaps {
ldaps[i].LoginRolesAssign, err = login_roleAssign.Get_tx(ctx, tx, "ldap", ldaps[i].Id) ldaps[i].LoginRolesAssign, err = login_roleAssign.Get_tx(ctx, tx, login_external.EntityLdap, ldaps[i].Id)
if err != nil { if err != nil {
return ldaps, err return ldaps, err
} }
@@ -128,10 +129,10 @@ func Set_tx(ctx context.Context, tx pgx.Tx, l types.Ldap) error {
} }
} }
if err := login_metaMap.Set_tx(ctx, tx, "ldap", l.Id, l.LoginMetaMap); err != nil { if err := login_metaMap.Set_tx(ctx, tx, login_external.EntityLdap, l.Id, l.LoginMetaMap); err != nil {
return err return err
} }
if err := login_roleAssign.Set_tx(ctx, tx, "ldap", l.Id, l.LoginRolesAssign); err != nil { if err := login_roleAssign.Set_tx(ctx, tx, login_external.EntityLdap, l.Id, l.LoginRolesAssign); err != nil {
return err return err
} }
return nil return nil

View File

@@ -14,7 +14,7 @@ func Check(ldapId int32, username string, password string) error {
ldapConn, ldap, err := ldap_conn.ConnectAndBind(ldapId) ldapConn, ldap, err := ldap_conn.ConnectAndBind(ldapId)
if err != nil { if err != nil {
log.Error("ldap", "failed to connect or bind", err) log.Error(log.ContextLdap, "failed to connect or bind", err)
return err return err
} }
defer ldapConn.Close() defer ldapConn.Close()
@@ -30,22 +30,22 @@ func Check(ldapId int32, username string, password string) error {
)) ))
if err != nil { if err != nil {
log.Error("ldap", "failed to execute search", err) log.Error(log.ContextLdap, "failed to execute search", err)
return err return err
} }
if len(search.Entries) != 1 { if len(search.Entries) != 1 {
err := errors.New("zero or more than one user returned") err := errors.New("zero or more than one user returned")
log.Error("ldap", "failed to execute search", err) log.Error(log.ContextLdap, "failed to execute search", err)
return err return err
} }
// authenticate user by attempting bind with their credentials // authenticate user by attempting bind with their credentials
if err := ldapConn.Bind(search.Entries[0].DN, password); err != nil { if err := ldapConn.Bind(search.Entries[0].DN, password); err != nil {
log.Info("ldap", fmt.Sprintf("authentication for login '%s' failed", username)) log.Info(log.ContextLdap, fmt.Sprintf("authentication for login '%s' failed", username))
return err return err
} }
log.Info("ldap", fmt.Sprintf("authentication for login '%s' successful", username)) log.Info(log.ContextLdap, fmt.Sprintf("authentication for login '%s' successful", username))
return nil return nil
} }

View File

@@ -31,7 +31,7 @@ func ConnectAndBind(ldapId int32) (*goldap.Conn, types.Ldap, error) {
ServerName: ldap.Host, ServerName: ldap.Host,
} }
log.Info("ldap", fmt.Sprintf("connecting to '%s'", bind)) log.Info(log.ContextLdap, fmt.Sprintf("connecting to '%s'", bind))
var ldapConn *goldap.Conn var ldapConn *goldap.Conn
if ldap.Tls { if ldap.Tls {

View File

@@ -34,7 +34,7 @@ func RunAll() error {
ldapIdMap := cache.GetLdapIdMap() ldapIdMap := cache.GetLdapIdMap()
if len(ldapIdMap) != 0 && !config.GetLicenseActive() { if len(ldapIdMap) != 0 && !config.GetLicenseActive() {
log.Warning("ldap", "skipping run", errors.New("no valid license")) log.Warning(log.ContextLdap, "skipping run", errors.New("no valid license"))
return nil return nil
} }
@@ -146,7 +146,7 @@ func run(ldapId int32) error {
pagingControl := goldap.NewControlPaging(pageSize) pagingControl := goldap.NewControlPaging(pageSize)
controls := []goldap.Control{pagingControl} controls := []goldap.Control{pagingControl}
for { for {
log.Info("ldap", fmt.Sprintf("querying '%s': '%s' in '%s'", log.Info(log.ContextLdap, fmt.Sprintf("querying '%s': '%s' in '%s'",
ldap.Name, filters, ldap.SearchDn)) ldap.Name, filters, ldap.SearchDn))
response, err := ldapConn.Search(goldap.NewSearchRequest( response, err := ldapConn.Search(goldap.NewSearchRequest(
@@ -246,14 +246,14 @@ func run(ldapId int32) error {
// import logins // import logins
for key, l := range logins { for key, l := range logins {
log.Info("ldap", fmt.Sprintf("processing login '%s' (key: %s, roles: %d)", l.name, key, len(l.roleIds))) log.Info(log.ContextLdap, fmt.Sprintf("processing login '%s' (key: %s, roles: %d)", l.name, key, len(l.roleIds)))
if err := login.SetLdapLogin(ldap, key, l.name, l.active, l.meta, l.roleIds); err != nil { if err := login.SetLdapLogin(ldap, key, l.name, l.active, l.meta, l.roleIds); err != nil {
log.Warning("ldap", fmt.Sprintf("failed to import login '%s'", l.name), err) log.Warning(log.ContextLdap, fmt.Sprintf("failed to import login '%s'", l.name), err)
continue continue
} }
} }
log.Info("ldap", fmt.Sprintf("finished login import for '%s'", ldap.Name)) log.Info(log.ContextLdap, fmt.Sprintf("finished login import for '%s'", ldap.Name))
return nil return nil
} }

View File

@@ -14,28 +14,62 @@ import (
"github.com/jackc/pgx/v5/pgtype" "github.com/jackc/pgx/v5/pgtype"
) )
type logContext int
const (
// log contexts
ContextApi logContext = 10
ContextBackup logContext = 20
ContextCache logContext = 30
ContextCluster logContext = 40
ContextCsv logContext = 50
ContextImager logContext = 60
ContextLdap logContext = 70
ContextMail logContext = 80
ContextModule logContext = 90 // only used via instance logging functions
ContextScheduler logContext = 100
ContextServer logContext = 110
ContextTransfer logContext = 120
ContextWebsocket logContext = 130
)
var ( var (
access_mx = sync.RWMutex{}
nodeId = pgtype.UUID{} // ID of the current node
// simple options, accessible without lock // simple options, accessible without lock
debug atomic.Bool debug atomic.Bool
outputCli atomic.Bool // write logs also to command line outputCli atomic.Bool // write logs also to command line
// log levels logContextLevel = map[logContext]int{
access_mx = sync.RWMutex{} ContextApi: 1,
nodeId = pgtype.UUID{} // ID of the current node ContextBackup: 1,
contextLevel = map[string]int{ ContextCache: 1,
"api": 1, ContextCluster: 1,
"backup": 1, ContextCsv: 1,
"cache": 1, ContextImager: 1,
"cluster": 1, ContextLdap: 1,
"csv": 1, ContextMail: 1,
"imager": 1, ContextModule: 1,
"mail": 1, ContextScheduler: 1,
"module": 1, ContextServer: 1,
"ldap": 1, ContextTransfer: 1,
"scheduler": 1, ContextWebsocket: 1,
"server": 1, }
"transfer": 1, logContextName = map[logContext]string{
"websocket": 1, ContextApi: "api",
ContextBackup: "backup",
ContextCache: "cache",
ContextCluster: "cluster",
ContextCsv: "csv",
ContextImager: "imager",
ContextLdap: "ldap",
ContextMail: "mail",
ContextModule: "module",
ContextScheduler: "scheduler",
ContextServer: "server",
ContextTransfer: "transfer",
ContextWebsocket: "websocket",
} }
) )
@@ -126,14 +160,13 @@ func SetDebug(state bool) {
func SetOutputCli(state bool) { func SetOutputCli(state bool) {
outputCli.Store(state) outputCli.Store(state)
} }
func SetLogLevel(context string, level int) { func SetLogLevel(context logContext, level int) {
access_mx.Lock() access_mx.Lock()
defer access_mx.Unlock() defer access_mx.Unlock()
if _, exists := contextLevel[context]; !exists { if _, exists := logContextLevel[context]; exists {
return logContextLevel[context] = level
} }
contextLevel[context] = level
} }
func SetNodeId(id uuid.UUID) { func SetNodeId(id uuid.UUID) {
access_mx.Lock() access_mx.Lock()
@@ -142,20 +175,20 @@ func SetNodeId(id uuid.UUID) {
access_mx.Unlock() access_mx.Unlock()
} }
func Info(context string, message string) { func Info(context logContext, message string) {
go write(3, context, message, nil) go write(3, context, message, nil)
} }
func Warning(context string, message string, err error) { func Warning(context logContext, message string, err error) {
go write(2, context, message, err) go write(2, context, message, err)
} }
func Error(context string, message string, err error) { func Error(context logContext, message string, err error) {
go write(1, context, message, err) go write(1, context, message, err)
} }
func write(level int, logContext string, message string, err error) { func write(level int, logContext logContext, message string, err error) {
access_mx.RLock() access_mx.RLock()
nodeIdLocal := nodeId nodeIdLocal := nodeId
levelActive, exists := contextLevel[logContext] levelActive, exists := logContextLevel[logContext]
access_mx.RUnlock() access_mx.RUnlock()
if !exists { if !exists {
@@ -177,7 +210,7 @@ func write(level int, logContext string, message string, err error) {
// log to CLI if available // log to CLI if available
if outputCli.Load() { if outputCli.Load() {
fmt.Printf("%s %s %s\n", tools.GetTimeSql(), logContext, message) fmt.Printf("%s %s %s\n", tools.GetTimeSql(), logContextName[logContext], message)
} }
// log to database if available // log to database if available
@@ -195,7 +228,7 @@ func write(level int, logContext string, message string, err error) {
if _, err := db.Pool.Exec(ctx, ` if _, err := db.Pool.Exec(ctx, `
INSERT INTO instance.log (level, context, message, date_milli, node_id) INSERT INTO instance.log (level, context, message, date_milli, node_id)
VALUES ($1,$2,$3,$4,$5) VALUES ($1,$2,$3,$4,$5)
`, level, logContext, message, tools.GetTimeUnixMilli(), nodeIdLocal); err != nil { `, level, logContextName[logContext], message, tools.GetTimeUnixMilli(), nodeIdLocal); err != nil {
// if database logging fails, output error to CLI if available // if database logging fails, output error to CLI if available
if outputCli.Load() { if outputCli.Load() {

View File

@@ -9,6 +9,7 @@ import (
"r3/db" "r3/db"
"r3/handler" "r3/handler"
"r3/log" "r3/log"
"r3/login/login_external"
"r3/login/login_meta" "r3/login/login_meta"
"r3/login/login_role" "r3/login/login_role"
"r3/login/login_setting" "r3/login/login_setting"
@@ -33,15 +34,19 @@ func Del_tx(ctx context.Context, tx pgx.Tx, id int64) error {
return err return err
} }
// delete all logins for LDAP connector // delete all logins for external login provider
func DelByLdap_tx(ctx context.Context, tx pgx.Tx, ldapId int32) error { func DelByExternalProvider_tx(ctx context.Context, tx pgx.Tx, entity string, entityId int32) error {
if err := login_external.ValidateEntity(entity); err != nil {
return err
}
loginIds := make([]int64, 0) loginIds := make([]int64, 0)
rows, err := tx.Query(ctx, ` rows, err := tx.Query(ctx, fmt.Sprintf(`
SELECT id SELECT id
FROM instance.login FROM instance.login
WHERE ldap_id = $1 WHERE %s_id = $1
`, ldapId) `, entity), entityId)
if err != nil { if err != nil {
return err return err
} }
@@ -547,11 +552,10 @@ func GenerateSaltHash(pw string) (salt pgtype.Text, hash pgtype.Text) {
// call login sync function for every module that has one to inform about changed login meta data // call login sync function for every module that has one to inform about changed login meta data
func syncLogin_tx(ctx context.Context, tx pgx.Tx, action string, id int64) { func syncLogin_tx(ctx context.Context, tx pgx.Tx, action string, id int64) {
logContext := "server"
logErr := "failed to execute user sync" logErr := "failed to execute user sync"
if !slices.Contains([]string{"DELETED", "UPDATED"}, action) { if !slices.Contains([]string{"DELETED", "UPDATED"}, action) {
log.Error(logContext, logErr, fmt.Errorf("unknown action '%s'", action)) log.Error(log.ContextServer, logErr, fmt.Errorf("unknown action '%s'", action))
return return
} }
@@ -567,7 +571,7 @@ func syncLogin_tx(ctx context.Context, tx pgx.Tx, action string, id int64) {
} }
if _, err := tx.Exec(ctx, `SELECT instance.user_sync($1,$2,$3,$4)`, mod.Name, fnc.Name, id, action); err != nil { if _, err := tx.Exec(ctx, `SELECT instance.user_sync($1,$2,$3,$4)`, mod.Name, fnc.Name, id, action); err != nil {
log.Error(logContext, logErr, err) log.Error(log.ContextServer, logErr, err)
} }
} }
cache.Schema_mx.RUnlock() cache.Schema_mx.RUnlock()

View File

@@ -196,7 +196,7 @@ func OpenId(ctx context.Context, oauthClientId int32, code string, codeVerifier
return types.LoginAuthResult{}, err return types.LoginAuthResult{}, err
} }
if active && rolesChanged { if active && rolesChanged {
login_clusterEvent.Reauth_tx(ctx, tx, "ldap", l.Id, l.Name) login_clusterEvent.Reauth_tx(ctx, tx, l.Id, l.Name)
} }
if err := tx.Commit(ctx); err != nil { if err := tx.Commit(ctx); err != nil {
return types.LoginAuthResult{}, err return types.LoginAuthResult{}, err

View File

@@ -9,18 +9,18 @@ import (
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
) )
func Kick_tx(ctx context.Context, tx pgx.Tx, logContext string, loginId int64, loginName string) { func Kick_tx(ctx context.Context, tx pgx.Tx, loginId int64, loginName string) {
log.Info(logContext, fmt.Sprintf("user account '%s' is locked, kicking active sessions", loginName)) log.Info(log.ContextServer, fmt.Sprintf("user account '%s' is locked, kicking active sessions", loginName))
if err := cluster.LoginDisabled_tx(ctx, tx, true, loginId); err != nil { if err := cluster.LoginDisabled_tx(ctx, tx, true, loginId); err != nil {
log.Warning(logContext, fmt.Sprintf("could not kick active sessions for '%s'", loginName), err) log.Warning(log.ContextServer, fmt.Sprintf("could not kick active sessions for '%s'", loginName), err)
} }
} }
func Reauth_tx(ctx context.Context, tx pgx.Tx, logContext string, loginId int64, loginName string) { func Reauth_tx(ctx context.Context, tx pgx.Tx, loginId int64, loginName string) {
log.Info(logContext, fmt.Sprintf("user account '%s' received new roles, renewing access permissions", loginName)) log.Info(log.ContextServer, fmt.Sprintf("user account '%s' received new roles, renewing access permissions", loginName))
if err := cluster.LoginReauthorized_tx(ctx, tx, true, loginId); err != nil { if err := cluster.LoginReauthorized_tx(ctx, tx, true, loginId); err != nil {
log.Warning(logContext, fmt.Sprintf("could not renew access permissions for '%s'", loginName), err) log.Warning(log.ContextServer, fmt.Sprintf("could not renew access permissions for '%s'", loginName), err)
} }
} }

View File

@@ -0,0 +1,18 @@
package login_external
import (
"fmt"
"slices"
)
const (
EntityLdap = "ldap"
EntityOauthClient = "oauth_client"
)
func ValidateEntity(entity string) error {
if !slices.Contains([]string{EntityLdap, EntityOauthClient}, entity) {
return fmt.Errorf("invalid external login entity '%s'", entity)
}
return nil
}

View File

@@ -93,7 +93,7 @@ func SetLdapLogin(ldap types.Ldap, ldapKey string, name string,
roleIdsEx = roleIds roleIdsEx = roleIds
} }
log.Info("ldap", fmt.Sprintf("user account '%s' is new or has been changed, updating login", name)) log.Info(log.ContextLdap, fmt.Sprintf("user account '%s' is new or has been changed, updating login", name))
if _, err := Set_tx(ctx, tx, loginId, ldap.LoginTemplateId, ldapIdSql, ldapKeySql, pgtype.Int4{}, if _, err := Set_tx(ctx, tx, loginId, ldap.LoginTemplateId, ldapIdSql, ldapKeySql, pgtype.Int4{},
pgtype.Text{}, pgtype.Text{}, name, "", adminEx, false, active, pgtype.Int4{}, metaEx, roleIdsEx, pgtype.Text{}, pgtype.Text{}, name, "", adminEx, false, active, pgtype.Int4{}, metaEx, roleIdsEx,
@@ -103,10 +103,10 @@ func SetLdapLogin(ldap types.Ldap, ldapKey string, name string,
} }
if active && rolesChanged { if active && rolesChanged {
login_clusterEvent.Reauth_tx(ctx, tx, "ldap", loginId, name) login_clusterEvent.Reauth_tx(ctx, tx, loginId, name)
} }
if !active && activeEx { if !active && activeEx {
login_clusterEvent.Kick_tx(ctx, tx, "ldap", loginId, name) login_clusterEvent.Kick_tx(ctx, tx, loginId, name)
} }
return tx.Commit(ctx) return tx.Commit(ctx)
} }

View File

@@ -3,24 +3,17 @@ package login_metaMap
import ( import (
"context" "context"
"fmt" "fmt"
"r3/login/login_external"
"r3/types" "r3/types"
"slices"
"strings" "strings"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
) )
func validateEntity(entity string) error {
if !slices.Contains([]string{"ldap", "oauth_client"}, entity) {
return fmt.Errorf("invalid login meta map entity '%s'", entity)
}
return nil
}
func Get_tx(ctx context.Context, tx pgx.Tx, entity string, entityId int32) (types.LoginMeta, error) { func Get_tx(ctx context.Context, tx pgx.Tx, entity string, entityId int32) (types.LoginMeta, error) {
var m types.LoginMeta var m types.LoginMeta
if err := validateEntity(entity); err != nil { if err := login_external.ValidateEntity(entity); err != nil {
return m, err return m, err
} }
@@ -50,7 +43,7 @@ func Get_tx(ctx context.Context, tx pgx.Tx, entity string, entityId int32) (type
func Set_tx(ctx context.Context, tx pgx.Tx, entity string, entityId int32, m types.LoginMeta) error { func Set_tx(ctx context.Context, tx pgx.Tx, entity string, entityId int32, m types.LoginMeta) error {
if err := validateEntity(entity); err != nil { if err := login_external.ValidateEntity(entity); err != nil {
return err return err
} }

View File

@@ -3,23 +3,16 @@ package login_roleAssign
import ( import (
"context" "context"
"fmt" "fmt"
"r3/login/login_external"
"r3/types" "r3/types"
"slices"
"github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5"
) )
func validateEntity(entity string) error {
if !slices.Contains([]string{"ldap", "oauth_client"}, entity) {
return fmt.Errorf("invalid login meta map entity '%s'", entity)
}
return nil
}
func Get_tx(ctx context.Context, tx pgx.Tx, entity string, entityId int32) ([]types.LoginRoleAssign, error) { func Get_tx(ctx context.Context, tx pgx.Tx, entity string, entityId int32) ([]types.LoginRoleAssign, error) {
roles := make([]types.LoginRoleAssign, 0) roles := make([]types.LoginRoleAssign, 0)
if err := validateEntity(entity); err != nil { if err := login_external.ValidateEntity(entity); err != nil {
return roles, err return roles, err
} }
@@ -46,7 +39,7 @@ func Get_tx(ctx context.Context, tx pgx.Tx, entity string, entityId int32) ([]ty
func Set_tx(ctx context.Context, tx pgx.Tx, entity string, entityId int32, assigns []types.LoginRoleAssign) error { func Set_tx(ctx context.Context, tx pgx.Tx, entity string, entityId int32, assigns []types.LoginRoleAssign) error {
if err := validateEntity(entity); err != nil { if err := login_external.ValidateEntity(entity); err != nil {
return err return err
} }

14
r3.go
View File

@@ -395,7 +395,7 @@ func (prg *program) execute(svc service.Service) {
// prepare image processing // prepare image processing
data_image.PrepareProcessing(cli.imageMagick) data_image.PrepareProcessing(cli.imageMagick)
log.Info("server", fmt.Sprintf("is ready to start application (%s)", appVersion)) log.Info(log.ContextServer, fmt.Sprintf("is ready to start application (%s)", appVersion))
// start scheduler (must start after module cache) // start scheduler (must start after module cache)
go scheduler.Start() go scheduler.Start()
@@ -453,7 +453,7 @@ func (prg *program) execute(svc service.Service) {
IdleTimeout: 120 * time.Second, IdleTimeout: 120 * time.Second,
ReadHeaderTimeout: 5 * time.Second, ReadHeaderTimeout: 5 * time.Second,
} }
log.Info("server", fmt.Sprintf("starting web handlers for '%s'", webServerString)) log.Info(log.ContextServer, fmt.Sprintf("starting web handlers for '%s'", webServerString))
// if dynamic port (0) is used we can only now open the app in default browser (port is now known) // if dynamic port (0) is used we can only now open the app in default browser (port is now known)
if cli.open && config.File.Web.Port != 0 { if cli.open && config.File.Web.Port != 0 {
@@ -498,7 +498,7 @@ func (prg *program) execute(svc service.Service) {
case "1.3": case "1.3":
prg.webServer.TLSConfig.MinVersion = tls.VersionTLS13 prg.webServer.TLSConfig.MinVersion = tls.VersionTLS13
default: default:
log.Warning("server", "failed to apply min. TLS version", log.Warning(log.ContextServer, "failed to apply min. TLS version",
fmt.Errorf("version '%s' is not supported (valid: 1.1, 1.2 or 1.3)", config.File.Web.TlsMinVersion)) fmt.Errorf("version '%s' is not supported (valid: 1.1, 1.2 or 1.3)", config.File.Web.TlsMinVersion))
} }
if err := prg.webServer.ServeTLS(webListener, "", ""); err != nil && err != http.ErrServerClosed { if err := prg.webServer.ServeTLS(webListener, "", ""); err != nil && err != http.ErrServerClosed {
@@ -579,7 +579,7 @@ func initCachesOptional(ctx context.Context) error {
defer tx.Rollback(ctx) defer tx.Rollback(ctx)
if err := cache.LoadSearchDictionaries_tx(ctx, tx); err != nil { if err := cache.LoadSearchDictionaries_tx(ctx, tx); err != nil {
log.Error("server", "failed to read/update text search dictionaries", err) log.Error(log.ContextServer, "failed to read/update text search dictionaries", err)
return tx.Rollback(ctx) return tx.Rollback(ctx)
} }
return tx.Commit(ctx) return tx.Commit(ctx)
@@ -635,7 +635,7 @@ func (prg *program) Stop(svc service.Service) error {
if err := prg.webServer.Shutdown(ctx); err != nil { if err := prg.webServer.Shutdown(ctx); err != nil {
prg.logger.Error(err) prg.logger.Error(err)
} }
log.Info("server", "stopped web handlers") log.Info(log.ContextServer, "stopped web handlers")
} }
// close database connection and deregister cluster node if DB is open // close database connection and deregister cluster node if DB is open
@@ -644,7 +644,7 @@ func (prg *program) Stop(svc service.Service) error {
prg.logger.Error(err) prg.logger.Error(err)
} }
db.Close() db.Close()
log.Info("server", "stopped database handler") log.Info(log.ContextServer, "stopped database handler")
} }
// stop embedded database if owned // stop embedded database if owned
@@ -652,7 +652,7 @@ func (prg *program) Stop(svc service.Service) error {
if err := embedded.Stop(); err != nil { if err := embedded.Stop(); err != nil {
prg.logger.Error(err) prg.logger.Error(err)
} }
log.Info("server", "stopped embedded database") log.Info(log.ContextServer, "stopped embedded database")
} }
return nil return nil
} }

View File

@@ -25,14 +25,14 @@ func ExecTransaction(ctx context.Context, address string, loginId int64, isAdmin
tx, err := db.Pool.Begin(ctx) tx, err := db.Pool.Begin(ctx)
if err != nil { if err != nil {
log.Error("websocket", "cannot begin transaction", err) log.Error(log.ContextWebsocket, "cannot begin transaction", err)
return responses, errors.New(handler.ErrGeneral) return responses, errors.New(handler.ErrGeneral)
} }
defer tx.Rollback(ctx) defer tx.Rollback(ctx)
if clearDbCache { if clearDbCache {
if err := tx.Conn().DeallocateAll(ctx); err != nil { if err := tx.Conn().DeallocateAll(ctx); err != nil {
log.Error("websocket", "failed to deallocate DB connection", err) log.Error(log.ContextWebsocket, "failed to deallocate DB connection", err)
return responses, err return responses, err
} }
} }
@@ -40,7 +40,7 @@ func ExecTransaction(ctx context.Context, address string, loginId int64, isAdmin
// set session parameters, used by system functions such as instance.get_user_id() // set session parameters, used by system functions such as instance.get_user_id()
if err := db.SetSessionConfig_tx(ctx, tx, loginId); err != nil { if err := db.SetSessionConfig_tx(ctx, tx, loginId); err != nil {
log.Error("websocket", fmt.Sprintf("TRANSACTION %d, transaction config failure (login ID %d)", log.Error(log.ContextWebsocket, fmt.Sprintf("TRANSACTION %d, transaction config failure (login ID %d)",
reqTrans.TransactionNr, loginId), err) reqTrans.TransactionNr, loginId), err)
return responses, err return responses, err
@@ -49,14 +49,14 @@ func ExecTransaction(ctx context.Context, address string, loginId int64, isAdmin
// work through requests // work through requests
for _, req := range reqTrans.Requests { for _, req := range reqTrans.Requests {
log.Info("websocket", fmt.Sprintf("TRANSACTION %d, %s %s, payload: %s", log.Info(log.ContextWebsocket, fmt.Sprintf("TRANSACTION %d, %s %s, payload: %s",
reqTrans.TransactionNr, req.Action, req.Ressource, req.Payload)) reqTrans.TransactionNr, req.Action, req.Ressource, req.Payload))
payload, err := Exec_tx(ctx, tx, address, loginId, isAdmin, device, isNoAuth, req.Ressource, req.Action, req.Payload) payload, err := Exec_tx(ctx, tx, address, loginId, isAdmin, device, isNoAuth, req.Ressource, req.Action, req.Payload)
if err != nil { if err != nil {
returnErr, isExpected := handler.ConvertToErrCode(err, !isAdmin) returnErr, isExpected := handler.ConvertToErrCode(err, !isAdmin)
if !isExpected { if !isExpected {
log.Warning("websocket", fmt.Sprintf("TRANSACTION %d, request %s %s failure (login ID %d)", log.Warning(log.ContextWebsocket, fmt.Sprintf("TRANSACTION %d, request %s %s failure (login ID %d)",
reqTrans.TransactionNr, req.Ressource, req.Action, loginId), err) reqTrans.TransactionNr, req.Ressource, req.Action, loginId), err)
} }
return responses, returnErr return responses, returnErr
@@ -73,7 +73,7 @@ func ExecTransaction(ctx context.Context, address string, loginId int64, isAdmin
if err := tx.Commit(ctx); err != nil { if err := tx.Commit(ctx); err != nil {
returnErr, isExpected := handler.ConvertToErrCode(err, !isAdmin) returnErr, isExpected := handler.ConvertToErrCode(err, !isAdmin)
if !isExpected { if !isExpected {
log.Warning("websocket", fmt.Sprintf("TRANSACTION %d, commit failure (login ID %d)", log.Warning(log.ContextWebsocket, fmt.Sprintf("TRANSACTION %d, commit failure (login ID %d)",
reqTrans.TransactionNr, loginId), err) reqTrans.TransactionNr, loginId), err)
} }
return responses, returnErr return responses, returnErr

View File

@@ -4,6 +4,8 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"r3/cache" "r3/cache"
"r3/login"
"r3/login/login_external"
"r3/login/login_metaMap" "r3/login/login_metaMap"
"r3/login/login_roleAssign" "r3/login/login_roleAssign"
"r3/types" "r3/types"
@@ -12,17 +14,19 @@ import (
) )
func OauthClientDel_tx(ctx context.Context, tx pgx.Tx, reqJson json.RawMessage) (interface{}, error) { func OauthClientDel_tx(ctx context.Context, tx pgx.Tx, reqJson json.RawMessage) (interface{}, error) {
var req struct { var id int32
Id int64 `json:"id"` if err := json.Unmarshal(reqJson, &id); err != nil {
return nil, err
} }
if err := json.Unmarshal(reqJson, &req); err != nil {
if err := login.DelByExternalProvider_tx(ctx, tx, login_external.EntityOauthClient, id); err != nil {
return nil, err return nil, err
} }
_, err := tx.Exec(ctx, ` _, err := tx.Exec(ctx, `
DELETE FROM instance.oauth_client DELETE FROM instance.oauth_client
WHERE id = $1 WHERE id = $1
`, req.Id) `, id)
return nil, err return nil, err
} }
@@ -66,10 +70,10 @@ func OauthClientSet_tx(ctx context.Context, tx pgx.Tx, reqJson json.RawMessage)
return nil, err return nil, err
} }
} }
if err := login_metaMap.Set_tx(ctx, tx, "oauth_client", req.Id, req.LoginMetaMap); err != nil { if err := login_metaMap.Set_tx(ctx, tx, login_external.EntityOauthClient, req.Id, req.LoginMetaMap); err != nil {
return nil, err return nil, err
} }
if err := login_roleAssign.Set_tx(ctx, tx, "oauth_client", req.Id, req.LoginRolesAssign); err != nil { if err := login_roleAssign.Set_tx(ctx, tx, login_external.EntityOauthClient, req.Id, req.LoginRolesAssign); err != nil {
return nil, err return nil, err
} }
return nil, nil return nil, nil

View File

@@ -82,22 +82,22 @@ var (
func Start() { func Start() {
time.Sleep(loopIntervalStartWait) time.Sleep(loopIntervalStartWait)
log.Info("scheduler", "started") log.Info(log.ContextScheduler, "started")
for { for {
time.Sleep(loopInterval) time.Sleep(loopInterval)
if loopStopping.Load() { if loopStopping.Load() {
log.Info("scheduler", "stopped") log.Info(log.ContextScheduler, "stopped")
return return
} }
if err := runTasksBySchedule(); err != nil { if err := runTasksBySchedule(); err != nil {
log.Error("scheduler", "failed to start tasks", err) log.Error(log.ContextScheduler, "failed to start tasks", err)
} }
} }
} }
func Stop() { func Stop() {
loopStopping.Store(true) loopStopping.Store(true)
log.Info("scheduler", "stopping") log.Info(log.ContextScheduler, "stopping")
} }
func init() { func init() {
@@ -154,7 +154,7 @@ func runTasksBySchedule() error {
taskNameNext = t.nameLog taskNameNext = t.nameLog
} }
} }
log.Info("scheduler", fmt.Sprintf("will start next task at %s ('%s')", log.Info(log.ContextScheduler, fmt.Sprintf("will start next task at %s ('%s')",
time.Unix(nextExecutionUnix, 0), taskNameNext)) time.Unix(nextExecutionUnix, 0), taskNameNext))
} }
@@ -229,11 +229,11 @@ func runTaskByIndex(taskIndex int) {
// run task and store schedule meta data // run task and store schedule meta data
var err error var err error
log.Info("scheduler", fmt.Sprintf("task '%s' started (scheduled for: %s)", log.Info(log.ContextScheduler, fmt.Sprintf("task '%s' started (scheduled for: %s)",
t.nameLog, time.Unix(t.runNextUnix, 0))) t.nameLog, time.Unix(t.runNextUnix, 0)))
if err := storeTaskDate(t, "attempt"); err != nil { if err := storeTaskDate(t, "attempt"); err != nil {
log.Error("scheduler", fmt.Sprintf("task '%s' failed to update its meta data", log.Error(log.ContextScheduler, fmt.Sprintf("task '%s' failed to update its meta data",
t.nameLog), err) t.nameLog), err)
} }
@@ -245,12 +245,12 @@ func runTaskByIndex(taskIndex int) {
if err == nil { if err == nil {
if err := storeTaskDate(t, "success"); err != nil { if err := storeTaskDate(t, "success"); err != nil {
log.Error("scheduler", fmt.Sprintf("task '%s' failed to update its meta data", t.nameLog), err) log.Error(log.ContextScheduler, fmt.Sprintf("task '%s' failed to update its meta data", t.nameLog), err)
} else { } else {
log.Info("scheduler", fmt.Sprintf("task '%s' executed successfully", t.nameLog)) log.Info(log.ContextScheduler, fmt.Sprintf("task '%s' executed successfully", t.nameLog))
} }
} else { } else {
log.Error("scheduler", fmt.Sprintf("task '%s' failed to execute", t.nameLog), err) log.Error(log.ContextScheduler, fmt.Sprintf("task '%s' failed to execute", t.nameLog), err)
} }
// store last successful run time for schedule and set next run time // store last successful run time for schedule and set next run time
@@ -274,7 +274,7 @@ func runTaskByIndex(taskIndex int) {
} }
func load() error { func load() error {
log.Info("scheduler", "is updating its configuration") log.Info(log.ContextScheduler, "is updating its configuration")
tasks = nil tasks = nil
// get system tasks and their states // get system tasks and their states

View File

@@ -38,7 +38,7 @@ func adminMails() error {
var sendMail = func(subject string, body string, dateExpiration int64, reason string) error { var sendMail = func(subject string, body string, dateExpiration int64, reason string) error {
// get mail receivers // get mail receivers
if config.GetString("adminMails") == "" { if config.GetString("adminMails") == "" {
log.Warning("server", "cannot send admin notification mails", fmt.Errorf("no mail receivers defined")) log.Warning(log.ContextServer, "cannot send admin notification mails", fmt.Errorf("no mail receivers defined"))
return nil return nil
} }
@@ -48,7 +48,7 @@ func adminMails() error {
} }
if len(toList) == 0 { if len(toList) == 0 {
log.Warning("server", "cannot send admin notification mails", fmt.Errorf("no mail receivers defined")) log.Warning(log.ContextServer, "cannot send admin notification mails", fmt.Errorf("no mail receivers defined"))
return nil return nil
} }

View File

@@ -170,7 +170,7 @@ func cleanUpFiles() error {
// if deletion fails, abort and keep its reference as file might be in access // if deletion fails, abort and keep its reference as file might be in access
if err := os.Remove(filePath); err != nil { if err := os.Remove(filePath); err != nil {
log.Warning("server", "failed to remove old file version", err) log.Warning(log.ContextServer, "failed to remove old file version", err)
continue continue
} }
} }
@@ -190,7 +190,7 @@ func cleanUpFiles() error {
break break
} }
log.Info("server", fmt.Sprintf("successfully cleaned up %d file versions (no retention)", log.Info(log.ContextServer, fmt.Sprintf("successfully cleaned up %d file versions (no retention)",
removeCnt)) removeCnt))
// limit not reached this loop, we are done // limit not reached this loop, we are done
@@ -240,7 +240,7 @@ func cleanUpFiles() error {
// referenced file version exists, attempt to delete it // referenced file version exists, attempt to delete it
// if deletion fails, abort and keep its reference as file might be in access // if deletion fails, abort and keep its reference as file might be in access
if err := os.Remove(filePath); err != nil { if err := os.Remove(filePath); err != nil {
log.Warning("server", "failed to remove old file version", err) log.Warning(log.ContextServer, "failed to remove old file version", err)
continue continue
} }
@@ -259,7 +259,7 @@ func cleanUpFiles() error {
filePathThumb := data.GetFilePathThumb(fileId) filePathThumb := data.GetFilePathThumb(fileId)
if exists, _ := tools.Exists(filePathThumb); exists { if exists, _ := tools.Exists(filePathThumb); exists {
if err := os.Remove(filePathThumb); err != nil { if err := os.Remove(filePathThumb); err != nil {
log.Warning("server", "failed to remove old file thumbnail", err) log.Warning(log.ContextServer, "failed to remove old file thumbnail", err)
continue continue
} }
} }
@@ -282,7 +282,7 @@ func cleanUpFiles() error {
if tag.RowsAffected() == 0 { if tag.RowsAffected() == 0 {
break break
} }
log.Info("server", fmt.Sprintf("successfully cleaned up %d files (deleted/unassigned)", log.Info(log.ContextServer, fmt.Sprintf("successfully cleaned up %d files (deleted/unassigned)",
tag.RowsAffected())) tag.RowsAffected()))
// limit not reached this loop, we are done // limit not reached this loop, we are done

View File

@@ -80,7 +80,7 @@ func clusterProcessEvents() error {
func clusterProcessEvent(ctx context.Context, tx pgx.Tx, e types.ClusterEvent, collectionUpdates *[]types.ClusterEventCollectionUpdated) error { func clusterProcessEvent(ctx context.Context, tx pgx.Tx, e types.ClusterEvent, collectionUpdates *[]types.ClusterEventCollectionUpdated) error {
log.Info("cluster", fmt.Sprintf("node is reacting to event '%s'", e.Content)) log.Info(log.ContextCluster, fmt.Sprintf("node is reacting to event '%s'", e.Content))
var err error var err error
var jsonPayload []byte var jsonPayload []byte

View File

@@ -18,7 +18,7 @@ func updateCheck() error {
} }
url := fmt.Sprintf("%s?old=%s", config.GetString("updateCheckUrl"), config.GetAppVersion().Full) url := fmt.Sprintf("%s?old=%s", config.GetString("updateCheckUrl"), config.GetAppVersion().Full)
log.Info("server", fmt.Sprintf("starting update check at '%s'", url)) log.Info(log.ContextServer, fmt.Sprintf("starting update check at '%s'", url))
httpClient, err := config.GetHttpClient(false, 10) httpClient, err := config.GetHttpClient(false, 10)
if err != nil { if err != nil {
@@ -61,6 +61,6 @@ func updateCheck() error {
return err return err
} }
log.Info("server", fmt.Sprintf("update check returned version '%s'", check.Version)) log.Info(log.ContextServer, fmt.Sprintf("update check returned version '%s'", check.Version))
return nil return nil
} }

View File

@@ -32,7 +32,7 @@ var (
func DoAll() error { func DoAll() error {
if !cache.GetMailAccountsExist() { if !cache.GetMailAccountsExist() {
log.Info("mail", "cannot start retrieval, no accounts defined") log.Info(log.ContextMail, "cannot start retrieval, no accounts defined")
return nil return nil
} }
@@ -43,10 +43,10 @@ func DoAll() error {
continue continue
} }
log.Info("mail", fmt.Sprintf("is retrieving from '%s'", ma.Name)) log.Info(log.ContextMail, fmt.Sprintf("is retrieving from '%s'", ma.Name))
if err := do(ma); err != nil { if err := do(ma); err != nil {
log.Error("mail", fmt.Sprintf("failed to retrieve from '%s'", ma.Name), err) log.Error(log.ContextMail, fmt.Sprintf("failed to retrieve from '%s'", ma.Name), err)
continue continue
} }
} }
@@ -112,14 +112,14 @@ func do(ma types.MailAccount) error {
return err return err
} }
log.Info("mail", fmt.Sprintf("found %d messages inside %s for account '%s'", log.Info(log.ContextMail, fmt.Sprintf("found %d messages inside %s for account '%s'",
mbox.Messages, imapFolder, ma.Name)) mbox.Messages, imapFolder, ma.Name))
if mbox.Messages == 0 { if mbox.Messages == 0 {
return nil return nil
} }
log.Info("mail", fmt.Sprintf("is now fetching messages (at most %d per run)", collectPerRun)) log.Info(log.ContextMail, fmt.Sprintf("is now fetching messages (at most %d per run)", collectPerRun))
// fetch mails from mailbox // fetch mails from mailbox
seqDel := new(imap.SeqSet) // messages to delete seqDel := new(imap.SeqSet) // messages to delete
@@ -145,7 +145,7 @@ func do(ma types.MailAccount) error {
for msg := range messages { for msg := range messages {
if err := processMessage(ma.Id, msg, &section); err != nil { if err := processMessage(ma.Id, msg, &section); err != nil {
// mail processing can fail because of many reasons, warn and move on // mail processing can fail because of many reasons, warn and move on
log.Warning("mail", "failed to process message - its not being deleted from the mailbox", err) log.Warning(log.ContextMail, "failed to process message - its not being deleted from the mailbox", err)
} else { } else {
// add to deletion sequence if processed successfully // add to deletion sequence if processed successfully
@@ -158,7 +158,7 @@ func do(ma types.MailAccount) error {
return err return err
} }
log.Info("mail", fmt.Sprintf("processed %d messages successfully, marking them for deletion", log.Info(log.ContextMail, fmt.Sprintf("processed %d messages successfully, marking them for deletion",
len(seqDel.Set))) len(seqDel.Set)))
// if database update was successful, execute mail deletion // if database update was successful, execute mail deletion

View File

@@ -27,7 +27,7 @@ var (
func DoAll() error { func DoAll() error {
if !cache.GetMailAccountsExist() { if !cache.GetMailAccountsExist() {
log.Info("mail", "cannot start sending, no accounts defined") log.Info(log.ContextMail, "cannot start sending, no accounts defined")
return nil return nil
} }
@@ -59,14 +59,14 @@ func DoAll() error {
mails = append(mails, m) mails = append(mails, m)
} }
log.Info("mail", fmt.Sprintf("found %d messages to be sent", len(mails))) log.Info(log.ContextMail, fmt.Sprintf("found %d messages to be sent", len(mails)))
for _, m := range mails { for _, m := range mails {
if err := do(m); err != nil { if err := do(m); err != nil {
// unable to send, update attempt counter and date for later attempt // unable to send, update attempt counter and date for later attempt
log.Error("mail", fmt.Sprintf("is unable to send (attempt %d)", log.Error(log.ContextMail, fmt.Sprintf("is unable to send (attempt %d)",
m.AttemptCount+1), err) m.AttemptCount+1), err)
if _, err := db.Pool.Exec(context.Background(), ` if _, err := db.Pool.Exec(context.Background(), `
@@ -80,7 +80,7 @@ func DoAll() error {
} }
// everything went well, delete spool entry // everything went well, delete spool entry
log.Info("mail", "successfully sent message") log.Info(log.ContextMail, "successfully sent message")
if _, err := db.Pool.Exec(context.Background(), ` if _, err := db.Pool.Exec(context.Background(), `
DELETE FROM instance.mail_spool DELETE FROM instance.mail_spool
@@ -201,7 +201,7 @@ func do(m types.Mail) error {
fileInfo, err := os.Stat(filePath) fileInfo, err := os.Stat(filePath)
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
log.Error("mail", "could not attach file to message", log.Error(log.ContextMail, "could not attach file to message",
fmt.Errorf("'%s' does not exist, ignoring it", filePath)) fmt.Errorf("'%s' does not exist, ignoring it", filePath))
continue continue
@@ -216,7 +216,7 @@ func do(m types.Mail) error {
} }
// send mail // send mail
log.Info("mail", fmt.Sprintf("sending message (%d attachments)", log.Info(log.ContextMail, fmt.Sprintf("sending message (%d attachments)",
len(msg.GetAttachments()))) len(msg.GetAttachments())))
client, err := mail.NewClient(ma.HostName, mail.WithPort(int(ma.HostPort)), client, err := mail.NewClient(ma.HostName, mail.WithPort(int(ma.HostPort)),
@@ -253,7 +253,7 @@ func do(m types.Mail) error {
if err := client.Close(); err != nil { if err := client.Close(); err != nil {
// some mail services do not cleanly close their connections // some mail services do not cleanly close their connections
// we should not care too much if the email was successfully sent - still warn as this is not correct behavior // we should not care too much if the email was successfully sent - still warn as this is not correct behavior
log.Warning("mail", "failed to disconnect from SMTP server", err) log.Warning(log.ContextMail, "failed to disconnect from SMTP server", err)
} }
// add to mail traffic log // add to mail traffic log

View File

@@ -65,7 +65,7 @@ func DoAll() error {
for _, c := range calls { for _, c := range calls {
if err := callExecute(c); err != nil { if err := callExecute(c); err != nil {
log.Error("api", fmt.Sprintf("failed to execute REST call %s '%s'", c.method, c.url), err) log.Error(log.ContextApi, fmt.Sprintf("failed to execute REST call %s '%s'", c.method, c.url), err)
_, err := db.Pool.Exec(context.Background(), ` _, err := db.Pool.Exec(context.Background(), `
UPDATE instance.rest_spool UPDATE instance.rest_spool
@@ -74,7 +74,7 @@ func DoAll() error {
`, c.id) `, c.id)
if err != nil { if err != nil {
log.Error("api", "failed to update call attempt count", err) log.Error(log.ContextApi, "failed to update call attempt count", err)
} }
continue continue
} }
@@ -90,7 +90,7 @@ func DoAll() error {
} }
func callExecute(c restCall) error { func callExecute(c restCall) error {
log.Info("api", fmt.Sprintf("is calling %s '%s'", c.method, c.url)) log.Info(log.ContextApi, fmt.Sprintf("is calling %s '%s'", c.method, c.url))
httpReq, err := http.NewRequest(c.method, c.url, strings.NewReader(c.body.String)) httpReq, err := http.NewRequest(c.method, c.url, strings.NewReader(c.body.String))
if err != nil { if err != nil {

View File

@@ -137,7 +137,7 @@ func deleteLoginForms_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, log
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del login form %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del login form %s", id.String()))
if err := loginForm.Del_tx(ctx, tx, id); err != nil { if err := loginForm.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -154,7 +154,7 @@ func deletePgTriggers_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, pgT
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del PG trigger %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del PG trigger %s", id.String()))
if err := pgTrigger.Del_tx(ctx, tx, id); err != nil { if err := pgTrigger.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -171,7 +171,7 @@ func deleteRelations_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, rela
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del relation %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del relation %s", id.String()))
if err := relation.Del_tx(ctx, tx, id); err != nil { if err := relation.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -190,7 +190,7 @@ func deleteRelationPgIndexes_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UU
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del PG index %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del PG index %s", id.String()))
if err := pgIndex.Del_tx(ctx, tx, id); err != nil { if err := pgIndex.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -209,7 +209,7 @@ func deleteRelationAttributes_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.U
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del attribute %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del attribute %s", id.String()))
if err := attribute.Del_tx(ctx, tx, id); err != nil { if err := attribute.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -228,7 +228,7 @@ func deleteRelationPresets_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del preset %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del preset %s", id.String()))
if err := preset.Del_tx(ctx, tx, id); err != nil { if err := preset.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -245,7 +245,7 @@ func deleteCollections_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, co
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del collection %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del collection %s", id.String()))
if err := collection.Del_tx(ctx, tx, id); err != nil { if err := collection.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -262,7 +262,7 @@ func deleteRoles_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, roles []
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del role %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del role %s", id.String()))
if err := role.Del_tx(ctx, tx, id); err != nil { if err := role.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -279,7 +279,7 @@ func deleteMenuTabs_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, menuT
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del menu tab %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del menu tab %s", id.String()))
if err := menuTab.Del_tx(ctx, tx, id); err != nil { if err := menuTab.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -296,7 +296,7 @@ func deleteForms_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, forms []
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del form %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del form %s", id.String()))
if err := form.Del_tx(ctx, tx, id); err != nil { if err := form.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -427,7 +427,7 @@ func deleteFormFields_tx(ctx context.Context, tx pgx.Tx, form types.Form) error
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del field %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del field %s", id.String()))
if err := field.Del_tx(ctx, tx, id); err != nil { if err := field.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -439,7 +439,7 @@ func deleteFormFields_tx(ctx context.Context, tx pgx.Tx, form types.Form) error
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del tab %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del tab %s", id.String()))
if err := tab.Del_tx(ctx, tx, id); err != nil { if err := tab.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -451,7 +451,7 @@ func deleteFormFields_tx(ctx context.Context, tx pgx.Tx, form types.Form) error
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del column %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del column %s", id.String()))
if err := column.Del_tx(ctx, tx, id); err != nil { if err := column.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -468,7 +468,7 @@ func deleteIcons_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, icons []
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del icon %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del icon %s", id.String()))
if err := icon.Del_tx(ctx, tx, id); err != nil { if err := icon.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -485,7 +485,7 @@ func deleteArticles_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, artic
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del article %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del article %s", id.String()))
if err := article.Del_tx(ctx, tx, id); err != nil { if err := article.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -502,7 +502,7 @@ func deleteApis_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, apis []ty
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del API %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del API %s", id.String()))
if err := api.Del_tx(ctx, tx, id); err != nil { if err := api.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -519,7 +519,7 @@ func deleteClientEvents_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, c
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del client event %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del client event %s", id.String()))
if err := clientEvent.Del_tx(ctx, tx, id); err != nil { if err := clientEvent.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -536,7 +536,7 @@ func deleteVariables_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, vari
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del variable %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del variable %s", id.String()))
if err := variable.Del_tx(ctx, tx, id); err != nil { if err := variable.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -553,7 +553,7 @@ func deleteWidgets_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, widget
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del widget %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del widget %s", id.String()))
if err := widget.Del_tx(ctx, tx, id); err != nil { if err := widget.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -570,7 +570,7 @@ func deletePgFunctions_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, pg
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del PG function %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del PG function %s", id.String()))
if err := pgFunction.Del_tx(ctx, tx, id); err != nil { if err := pgFunction.Del_tx(ctx, tx, id); err != nil {
return err return err
} }
@@ -587,7 +587,7 @@ func deleteJsFunctions_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, js
return err return err
} }
for _, id := range idsDelete { for _, id := range idsDelete {
log.Info("transfer", fmt.Sprintf("del JS function %s", id.String())) log.Info(log.ContextTransfer, fmt.Sprintf("del JS function %s", id.String()))
if err := jsFunction.Del_tx(ctx, tx, id); err != nil { if err := jsFunction.Del_tx(ctx, tx, id); err != nil {
return err return err
} }

View File

@@ -32,7 +32,7 @@ import (
// dependent app version, release date) will be updated // dependent app version, release date) will be updated
func ExportToFile(ctx context.Context, moduleId uuid.UUID, zipFilePath string) error { func ExportToFile(ctx context.Context, moduleId uuid.UUID, zipFilePath string) error {
log.Info("transfer", fmt.Sprintf("start export for module %s", moduleId)) log.Info(log.ContextTransfer, fmt.Sprintf("start export for module %s", moduleId))
if exportKey == "" { if exportKey == "" {
return errors.New("no export key for module signing set") return errors.New("no export key for module signing set")
@@ -90,7 +90,7 @@ func export_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, filePaths *[]
return err return err
} }
log.Info("transfer", fmt.Sprintf("exporting module '%s' (owner: %v)", log.Info(log.ContextTransfer, fmt.Sprintf("exporting module '%s' (owner: %v)",
file.Content.Module.Name, isOwner)) file.Content.Module.Name, isOwner))
// user is not owner, export original version // user is not owner, export original version

View File

@@ -57,7 +57,7 @@ func ImportFromFiles_tx(ctx context.Context, tx pgx.Tx, filePathsImport []string
Import_mx.Lock() Import_mx.Lock()
defer Import_mx.Unlock() defer Import_mx.Unlock()
log.Info("transfer", fmt.Sprintf("start import for modules from file(s): '%s'", strings.Join(filePathsImport, "', '"))) log.Info(log.ContextTransfer, fmt.Sprintf("start import for modules from file(s): '%s'", strings.Join(filePathsImport, "', '")))
// extract module packages // extract module packages
filePathsModules := make([]string, 0) filePathsModules := make([]string, 0)
@@ -113,10 +113,10 @@ func ImportFromFiles_tx(ctx context.Context, tx pgx.Tx, filePathsImport []string
return errors.New("import loop count exceeded") return errors.New("import loop count exceeded")
} }
} }
log.Info("transfer", fmt.Sprintf("import loop %d started", loopsRan+1)) log.Info(log.ContextTransfer, fmt.Sprintf("import loop %d started", loopsRan+1))
for _, m := range modules { for _, m := range modules {
log.Info("transfer", fmt.Sprintf("import START, module '%s', %s", m.Name, m.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("import START, module '%s', %s", m.Name, m.Id))
/* execution order /* execution order
1. delete to be removed triggers (only need to run once), known issues: 1. delete to be removed triggers (only need to run once), known issues:
@@ -141,7 +141,7 @@ func ImportFromFiles_tx(ctx context.Context, tx pgx.Tx, filePathsImport []string
return err return err
} }
} }
log.Info("transfer", fmt.Sprintf("import END, module '%s', %s", m.Name, m.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("import END, module '%s', %s", m.Name, m.Id))
} }
} }
@@ -161,7 +161,7 @@ func ImportFromFiles_tx(ctx context.Context, tx pgx.Tx, filePathsImport []string
} }
} }
log.Info("transfer", "module files were moved to transfer path if imported") log.Info(log.ContextTransfer, "module files were moved to transfer path if imported")
// update schema cache // update schema cache
moduleIdsUpdated := make([]uuid.UUID, 0) moduleIdsUpdated := make([]uuid.UUID, 0)
@@ -186,7 +186,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
return err return err
} }
if run { if run {
log.Info("transfer", fmt.Sprintf("set module '%s' v%d, %s", log.Info(log.ContextTransfer, fmt.Sprintf("set module '%s' v%d, %s",
mod.Name, mod.ReleaseBuild, mod.Id)) mod.Name, mod.ReleaseBuild, mod.Id))
if err := importCheckResultAndApply(ctx, tx, module.Set_tx(ctx, tx, mod), mod.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, module.Set_tx(ctx, tx, mod), mod.Id, idMapSkipped); err != nil {
@@ -203,7 +203,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set article %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set article %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, article.Set_tx(ctx, tx, e.ModuleId, if err := importCheckResultAndApply(ctx, tx, article.Set_tx(ctx, tx, e.ModuleId,
e.Id, e.Name, e.Captions), e.Id, idMapSkipped); err != nil { e.Id, e.Name, e.Captions), e.Id, idMapSkipped); err != nil {
@@ -221,7 +221,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set icon %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set icon %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, icon.Set_tx(ctx, tx, e.ModuleId, if err := importCheckResultAndApply(ctx, tx, icon.Set_tx(ctx, tx, e.ModuleId,
e.Id, e.Name, e.File, true), e.Id, idMapSkipped); err != nil { e.Id, e.Name, e.File, true), e.Id, idMapSkipped); err != nil {
@@ -239,7 +239,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set relation %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set relation %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, relation.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, relation.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -261,7 +261,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set PK attribute %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set PK attribute %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, attribute.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, attribute.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -283,7 +283,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set attribute %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set attribute %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, attribute.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, attribute.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -300,7 +300,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set collection %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set collection %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, collection.Set_tx(ctx, tx, if err := importCheckResultAndApply(ctx, tx, collection.Set_tx(ctx, tx,
e.ModuleId, e.Id, e.IconId, e.Name, e.Columns, e.Query, e.InHeader), e.ModuleId, e.Id, e.IconId, e.Name, e.Columns, e.Query, e.InHeader),
@@ -319,7 +319,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set API %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set API %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, api.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, api.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -335,7 +335,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set variable %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set variable %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, variable.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, variable.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -351,7 +351,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set widget %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set widget %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, widget.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, widget.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -367,7 +367,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set PG function %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set PG function %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, pgFunction.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, pgFunction.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -383,7 +383,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set trigger %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set trigger %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, pgTrigger.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, pgTrigger.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -400,7 +400,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set index %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set index %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, pgIndex.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, pgIndex.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -417,7 +417,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set form %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set form %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, form.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, form.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -433,7 +433,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set login form %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set login form %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, loginForm.Set_tx( if err := importCheckResultAndApply(ctx, tx, loginForm.Set_tx(
ctx, tx, e.ModuleId, e.Id, e.AttributeIdLogin, e.AttributeIdLookup, ctx, tx, e.ModuleId, e.Id, e.AttributeIdLogin, e.AttributeIdLookup,
@@ -452,7 +452,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set menu tab %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set menu tab %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, menuTab.Set_tx(ctx, tx, i, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, menuTab.Set_tx(ctx, tx, i, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -468,7 +468,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set role %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set role %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, role.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, role.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -484,7 +484,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set JS function %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set JS function %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, jsFunction.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, jsFunction.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -501,7 +501,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set client event %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set client event %s", e.Id))
if err := importCheckResultAndApply(ctx, tx, clientEvent.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, clientEvent.Set_tx(ctx, tx, e), e.Id, idMapSkipped); err != nil {
return err return err
@@ -522,13 +522,13 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun
if !run { if !run {
continue continue
} }
log.Info("transfer", fmt.Sprintf("set preset %s", e.Id)) log.Info(log.ContextTransfer, fmt.Sprintf("set preset %s", e.Id))
// special case // special case
// presets can fail import because referenced, unprotected presets were deleted or unique constraints are broken // presets can fail import because referenced, unprotected presets were deleted or unique constraints are broken
// if preset itself is unprotected, we try until the last loop and then give up // if preset itself is unprotected, we try until the last loop and then give up
if lastRun && !e.Protected { if lastRun && !e.Protected {
log.Info("transfer", "import failed to resolve unprotected preset until last loop, it will be ignored") log.Info(log.ContextTransfer, "import failed to resolve unprotected preset until last loop, it will be ignored")
if err := importCheckResultAndApply(ctx, tx, nil, e.Id, idMapSkipped); err != nil { if err := importCheckResultAndApply(ctx, tx, nil, e.Id, idMapSkipped); err != nil {
return err return err
} }
@@ -579,7 +579,7 @@ func importCheckResultAndApply(ctx context.Context, tx pgx.Tx, resultErr error,
} }
// error case // error case
log.Info("transfer", fmt.Sprintf("skipped entity on this run, error: %s", resultErr)) log.Info(log.ContextTransfer, fmt.Sprintf("skipped entity on this run, error: %s", resultErr))
if _, err := tx.Exec(ctx, `ROLLBACK TO SAVEPOINT transfer_import`); err != nil { if _, err := tx.Exec(ctx, `ROLLBACK TO SAVEPOINT transfer_import`); err != nil {
return err return err
@@ -594,7 +594,7 @@ func parseModulesFromPaths_tx(ctx context.Context, tx pgx.Tx, filePaths []string
modules := make([]types.Module, 0) modules := make([]types.Module, 0)
log.Info("transfer", fmt.Sprintf("import is parsing %d module files", len(filePaths))) log.Info(log.ContextTransfer, fmt.Sprintf("import is parsing %d module files", len(filePaths)))
// read all modules from file paths // read all modules from file paths
for _, filePath := range filePaths { for _, filePath := range filePaths {
@@ -617,7 +617,7 @@ func parseModulesFromPaths_tx(ctx context.Context, tx pgx.Tx, filePaths []string
} }
moduleId := fileData.Content.Module.Id moduleId := fileData.Content.Module.Id
log.Info("transfer", fmt.Sprintf("import is validating module '%s' v%d", log.Info(log.ContextTransfer, fmt.Sprintf("import is validating module '%s' v%d",
fileData.Content.Module.Name, fileData.Content.Module.ReleaseBuild)) fileData.Content.Module.Name, fileData.Content.Module.ReleaseBuild))
// verify application compatibility // verify application compatibility
@@ -633,7 +633,7 @@ func parseModulesFromPaths_tx(ctx context.Context, tx pgx.Tx, filePaths []string
// check for newer version of installed module // check for newer version of installed module
if exModule.ReleaseBuild >= fileData.Content.Module.ReleaseBuild { if exModule.ReleaseBuild >= fileData.Content.Module.ReleaseBuild {
log.Info("transfer", fmt.Sprintf("import of module '%s' not required, same or newer version (%d -> %d) installed", log.Info(log.ContextTransfer, fmt.Sprintf("import of module '%s' not required, same or newer version (%d -> %d) installed",
fileData.Content.Module.Name, exModule.ReleaseBuild, fileData.Content.Module.Name, exModule.ReleaseBuild,
fileData.Content.Module.ReleaseBuild)) fileData.Content.Module.ReleaseBuild))
@@ -647,7 +647,7 @@ func parseModulesFromPaths_tx(ctx context.Context, tx pgx.Tx, filePaths []string
} }
if hashedStr == hashedStrEx { if hashedStr == hashedStrEx {
log.Info("transfer", fmt.Sprintf("import of module '%s' not required, no changes", log.Info(log.ContextTransfer, fmt.Sprintf("import of module '%s' not required, no changes",
fileData.Content.Module.Name)) fileData.Content.Module.Name))
continue continue
@@ -657,7 +657,7 @@ func parseModulesFromPaths_tx(ctx context.Context, tx pgx.Tx, filePaths []string
// check whether module was added previously (multiple import files used with similar modules) // check whether module was added previously (multiple import files used with similar modules)
if _, exists := moduleIdMapImportMeta[moduleId]; exists { if _, exists := moduleIdMapImportMeta[moduleId]; exists {
if moduleIdMapImportMeta[moduleId].module.ReleaseBuild >= fileData.Content.Module.ReleaseBuild { if moduleIdMapImportMeta[moduleId].module.ReleaseBuild >= fileData.Content.Module.ReleaseBuild {
log.Info("transfer", fmt.Sprintf("import of module '%s' not required, same or newer version (%d -> %d) to be added", log.Info(log.ContextTransfer, fmt.Sprintf("import of module '%s' not required, same or newer version (%d -> %d) to be added",
fileData.Content.Module.Name, moduleIdMapImportMeta[moduleId].module.ReleaseBuild, fileData.Content.Module.Name, moduleIdMapImportMeta[moduleId].module.ReleaseBuild,
fileData.Content.Module.ReleaseBuild)) fileData.Content.Module.ReleaseBuild))
@@ -665,7 +665,7 @@ func parseModulesFromPaths_tx(ctx context.Context, tx pgx.Tx, filePaths []string
} }
} }
log.Info("transfer", fmt.Sprintf("import will install module '%s' v%d", log.Info(log.ContextTransfer, fmt.Sprintf("import will install module '%s' v%d",
fileData.Content.Module.Name, fileData.Content.Module.ReleaseBuild)) fileData.Content.Module.Name, fileData.Content.Module.ReleaseBuild))
moduleIdMapImportMeta[moduleId] = importMeta{ moduleIdMapImportMeta[moduleId] = importMeta{
@@ -714,7 +714,7 @@ func parseModulesFromPaths_tx(ctx context.Context, tx pgx.Tx, filePaths []string
addModule(id) addModule(id)
} }
log.Info("transfer", fmt.Sprintf("import has decided on installation order: %s", log.Info(log.ContextTransfer, fmt.Sprintf("import has decided on installation order: %s",
strings.Join(moduleNames, ", "))) strings.Join(moduleNames, ", ")))
return modules, nil return modules, nil

View File

@@ -53,8 +53,8 @@ let MyAdminLoginRolesAssign = {
</table> </table>
<div> <div>
<my-button image="add.png" <my-button image="add.png"
v-if="!readonly"
@trigger="add" @trigger="add"
:active="!readonly"
:caption="capGen.button.add" :caption="capGen.button.add"
/> />
</div> </div>

View File

@@ -168,7 +168,7 @@ let MyAdminOauthClient = {
<span>{{ capApp.claimRolesHint }}</span> <span>{{ capApp.claimRolesHint }}</span>
<my-admin-login-roles-assign <my-admin-login-roles-assign
v-model="inputs.loginRolesAssign" v-model="inputs.loginRolesAssign"
:readonly="readonly || inputs.claimRoles === ''" :readonly="readonly || !isClaimRolesSet"
/> />
</div> </div>
</td> </td>
@@ -231,7 +231,7 @@ let MyAdminOauthClient = {
(!s.isFlowAuthCodePkce || s.inputs.claimUsername !== '') && (!s.isFlowAuthCodePkce || s.inputs.claimUsername !== '') &&
(!s.isFlowAuthCodePkce || s.inputs.providerUrl !== '') && (!s.isFlowAuthCodePkce || s.inputs.providerUrl !== '') &&
(!s.isFlowAuthCodePkce || s.inputs.redirectUrl !== '') && (!s.isFlowAuthCodePkce || s.inputs.redirectUrl !== '') &&
(!s.isFlowClientCreds || s.inputs.tokenUrl !== ''), (!s.isFlowClientCreds || s.isTokenUrlSet),
inputsOrg:(s) => s.isNew ? { inputsOrg:(s) => s.isNew ? {
id:0, id:0,
name:'', name:'',
@@ -252,8 +252,10 @@ let MyAdminOauthClient = {
// simple states // simple states
hasChanges: (s) => !s.deepIsEqual(s.inputsOrg,s.inputs), hasChanges: (s) => !s.deepIsEqual(s.inputsOrg,s.inputs),
isClaimRolesSet: (s) => s.inputs.claimRoles !== null && s.inputs.claimRoles !== '',
isFlowAuthCodePkce:(s) => s.inputs.flow === 'authCodePkce', isFlowAuthCodePkce:(s) => s.inputs.flow === 'authCodePkce',
isFlowClientCreds: (s) => s.inputs.flow === 'clientCreds', isFlowClientCreds: (s) => s.inputs.flow === 'clientCreds',
isTokenUrlSet: (s) => s.inputs.tokenUrl !== null && s.inputs.tokenUrl !== '',
isNew: (s) => s.id === 0, isNew: (s) => s.id === 0,
// stores // stores
@@ -316,7 +318,7 @@ let MyAdminOauthClient = {
}); });
}, },
del() { del() {
ws.send('oauthClient','del',{id:this.id},true).then( ws.send('oauthClient','del',this.id,true).then(
this.reloadAndClose, this.reloadAndClose,
this.$root.genericError this.$root.genericError
); );
@@ -327,6 +329,7 @@ let MyAdminOauthClient = {
ws.send('oauthClient','set',{ ws.send('oauthClient','set',{
id:this.id, id:this.id,
name:this.inputs.name, name:this.inputs.name,
flow:this.inputs.flow,
clientId:this.inputs.clientId, clientId:this.inputs.clientId,
clientSecret:this.inputs.clientSecret, clientSecret:this.inputs.clientSecret,
dateExpiry:this.inputs.dateExpiry, dateExpiry:this.inputs.dateExpiry,

View File

@@ -391,39 +391,49 @@ let MyLogin = {
}, },
// authentication against external identity provider // authentication against external identity provider
authenticateExternalOpenId:async function(c) { authenticateExternalOpenId(c) {
this.loading = true; this.loading = true;
const url = new URL(c.providerUrl); const url = new URL(c.providerUrl);
const as = await oauth.discoveryRequest(url,{algorithm:'oidc'}).then( const errFnc = msg => {
res => oauth.processDiscoveryResponse(url,res), console.warn(msg);
console.warn this.loading = false;
};
oauth.discoveryRequest(url,{algorithm:'oidc'}).then(
res => {
oauth.processDiscoveryResponse(url,res).then(
as => {
const state = this.getRandomString(64);
const verifier = oauth.generateRandomCodeVerifier();
oauth.calculatePKCECodeChallenge(verifier).then(
challenge => {
this.$store.commit('local/openIdAuthDetails',{
codeVerifier:verifier,
oauthClientId:c.id,
state:state
});
const urlEndpoint = new URL(as.authorization_endpoint);
urlEndpoint.searchParams.set('client_id',c.clientId);
urlEndpoint.searchParams.set('redirect_uri',c.redirectUrl);
urlEndpoint.searchParams.set('response_type','code');
urlEndpoint.searchParams.set('scope','openid');
urlEndpoint.searchParams.set('code_challenge',challenge);
urlEndpoint.searchParams.set('code_challenge_method','S256');
// encode state with base64, some characters are not correctly returned in redirect URL (example: Azure AD '§')
urlEndpoint.searchParams.set('state',btoa(state));
window.location.replace(urlEndpoint.toString());
this.loading = false;
},
errFnc
);
},
errFnc
);
},
errFnc
); );
if(as === undefined)
return this.loading = false;
const verifier = oauth.generateRandomCodeVerifier();
const challenge = await oauth.calculatePKCECodeChallenge(verifier);
const state = this.getRandomString(64);
this.$store.commit('local/openIdAuthDetails',{
codeVerifier:verifier,
oauthClientId:c.id,
state:state
});
const urlEndpoint = new URL(as.authorization_endpoint);
urlEndpoint.searchParams.set('client_id',c.clientId);
urlEndpoint.searchParams.set('redirect_uri',c.redirectUrl);
urlEndpoint.searchParams.set('response_type','code');
urlEndpoint.searchParams.set('scope','openid');
urlEndpoint.searchParams.set('code_challenge',challenge);
urlEndpoint.searchParams.set('code_challenge_method','S256');
// encode state with base64, some characters are not correctly returned in redirect URL (example: Azure AD '§')
urlEndpoint.searchParams.set('state',btoa(state));
window.location.replace(urlEndpoint.toString());
this.loading = false;
}, },
// authentication against backend // authentication against backend