From 8b3587f536692a367b4321c91eac0dd0d9fd2053 Mon Sep 17 00:00:00 2001 From: Gabriel Herbert Date: Tue, 20 May 2025 12:16:10 +0200 Subject: [PATCH] Fixed multiple bugs, cleaned up logging calls --- backup/backup.go | 28 +++--- cache/cache_cert.go | 2 +- cache/cache_oauthClient.go | 5 +- cache/cache_schema.go | 32 +++---- cluster/cluster_tasks.go | 4 +- config/config.go | 26 +++--- config/config_activation.go | 18 ++-- config/config_store.go | 6 +- data/data_image/data_image.go | 8 +- data/data_import/data_import.go | 2 +- db/embedded/embedded_windows.go | 4 +- db/upgrade/upgrade.go | 16 ++-- handler/api/api.go | 4 +- handler/api_auth/api_auth.go | 10 +-- handler/cache_download/cache_download.go | 10 +-- handler/client_download/client_download.go | 12 ++- .../client_download/client_download_config.go | 20 ++--- handler/csv_download/csv_download.go | 72 +++++++-------- handler/csv_upload/csv_upload.go | 27 +++--- handler/data_access/data_access.go | 23 +++-- handler/data_auth/data_auth.go | 8 +- handler/data_download/data_download.go | 14 ++- .../data_download_thumb.go | 16 ++-- handler/data_upload/data_upload.go | 16 ++-- handler/handler.go | 47 ++++++++-- handler/icon_upload/icon_upload.go | 22 +++-- handler/ics_download/ics_download.go | 28 +++--- handler/license_upload/license_upload.go | 20 ++--- .../manifest_download/manifest_download.go | 51 +++++------ handler/transfer_export/transfer_export.go | 14 +-- handler/transfer_import/transfer_import.go | 4 +- handler/websocket/websocket.go | 28 +++--- ldap/ldap.go | 9 +- ldap/ldap_auth/ldap_auth.go | 10 +-- ldap/ldap_conn/ldap_conn.go | 2 +- ldap/ldap_import/ldap_import.go | 10 +-- log/log.go | 89 +++++++++++++------ login/login.go | 20 +++-- login/login_auth/login_auth_openId.go | 2 +- .../login_clusterEvent/login_clusterEvent.go | 12 +-- login/login_external/login_external.go | 18 ++++ login/login_ldap.go | 6 +- login/login_metaMap/login_metaMap.go | 13 +-- login/login_roleAssign/login_roleAssign.go | 13 +-- r3.go | 14 +-- request/request.go | 12 +-- request/request_oauth_client.go | 16 ++-- scheduler/scheduler.go | 22 ++--- scheduler/scheduler_adminMails.go | 4 +- scheduler/scheduler_cleanup.go | 10 +-- scheduler/scheduler_cluster.go | 2 +- scheduler/scheduler_update.go | 4 +- spooler/mail_receive/mail_receive.go | 14 +-- spooler/mail_send/mail_send.go | 14 +-- spooler/rest_send/rest_send.go | 6 +- transfer/transfer_delete/transfer_delete.go | 42 ++++----- transfer/transfer_export.go | 4 +- transfer/transfer_import.go | 68 +++++++------- www/comps/admin/adminLoginRolesAssign.js | 2 +- www/comps/admin/adminOauthClient.js | 9 +- www/comps/login.js | 72 ++++++++------- 61 files changed, 589 insertions(+), 527 deletions(-) create mode 100644 login/login_external/login_external.go diff --git a/backup/backup.go b/backup/backup.go index 0af22879..0796a09c 100644 --- a/backup/backup.go +++ b/backup/backup.go @@ -33,14 +33,14 @@ func Run() error { config.GetUint64("backupWeekly") == 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 } // initialize state if config.GetString("backupDir") == "" { err := errors.New("backup directory not defined") - log.Error("backup", "could not start", err) + log.Error(log.ContextBackup, "could not start", err) return err } @@ -55,7 +55,7 @@ func Run() error { jobRan := false // limit to one job per run 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 for _, backup := range tocFile.Backups { @@ -65,16 +65,16 @@ func Run() error { } 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 } 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 } 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 } jobRan = true @@ -101,10 +101,10 @@ func Run() 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)) - 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 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 // 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) - 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) if err != nil { @@ -151,12 +151,12 @@ func jobCleanup(tocFile *types.BackupTocFile, jobName string, countKeep uint64) if err := tocFileWrite(*tocFile); err != nil { 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 } 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() jobDir := getBackupJobDir(newTimestamp, jobName) @@ -203,7 +203,7 @@ func jobBackup(tocFile *types.BackupTocFile, jobName string) error { if err := tocFileWrite(*tocFile); err != nil { 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 } @@ -230,7 +230,7 @@ func TocFileReadCreate() (types.BackupTocFile, error) { exists, err := tools.Exists(path) 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 } if !exists { diff --git a/cache/cache_cert.go b/cache/cache_cert.go index 2817cb2d..d4b24481 100644 --- a/cache/cache_cert.go +++ b/cache/cache_cert.go @@ -58,7 +58,7 @@ func CheckRenewCert() error { } 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) if err != nil { diff --git a/cache/cache_oauthClient.go b/cache/cache_oauthClient.go index 8a08c0ce..47387a15 100644 --- a/cache/cache_oauthClient.go +++ b/cache/cache_oauthClient.go @@ -3,6 +3,7 @@ package cache import ( "context" "fmt" + "r3/login/login_external" "r3/login/login_metaMap" "r3/login/login_roleAssign" "r3/types" @@ -88,11 +89,11 @@ func LoadOauthClientMap_tx(ctx context.Context, tx pgx.Tx) error { // retrieve login meta mapping for k, c := range oauthClientIdMap { 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 { 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 { return err } diff --git a/cache/cache_schema.go b/cache/cache_schema.go index ccafea33..5a5ce165 100644 --- a/cache/cache_schema.go +++ b/cache/cache_schema.go @@ -152,14 +152,14 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) Schema_mx.Lock() 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) if err != nil { return err } 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.Forms = make([]types.Form, 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) // get articles - log.Info("cache", "load articles") + log.Info(log.ContextCache, "load articles") mod.Articles, err = article.Get_tx(ctx, tx, mod.Id) if err != nil { @@ -185,7 +185,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // get relations - log.Info("cache", "load relations") + log.Info(log.ContextCache, "load relations") rels, err := relation.Get_tx(ctx, tx, mod.Id) if err != nil { @@ -224,7 +224,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // 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{}) if err != nil { @@ -232,7 +232,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // 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) if err != nil { @@ -240,7 +240,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // get icons - log.Info("cache", "load icons") + log.Info(log.ContextCache, "load icons") mod.Icons, err = icon.Get_tx(ctx, tx, mod.Id) if err != nil { @@ -248,7 +248,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // get roles - log.Info("cache", "load roles") + log.Info(log.ContextCache, "load roles") mod.Roles, err = role.Get_tx(ctx, tx, mod.Id) if err != nil { @@ -261,7 +261,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // 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) if err != nil { @@ -275,7 +275,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // 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) if err != nil { @@ -286,7 +286,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // 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) if err != nil { @@ -294,7 +294,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // get collections - log.Info("cache", "load collections") + log.Info(log.ContextCache, "load collections") mod.Collections, err = collection.Get_tx(ctx, tx, mod.Id) if err != nil { @@ -302,7 +302,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // 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) if err != nil { @@ -314,7 +314,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // 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) if err != nil { @@ -325,7 +325,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // get variables - log.Info("cache", "load variables") + log.Info(log.ContextCache, "load variables") mod.Variables, err = variable.Get_tx(ctx, tx, mod.Id) if err != nil { @@ -333,7 +333,7 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID) } // get widgets - log.Info("cache", "load widgets") + log.Info(log.ContextCache, "load widgets") mod.Widgets, err = widget.Get_tx(ctx, tx, mod.Id) if err != nil { diff --git a/cluster/cluster_tasks.go b/cluster/cluster_tasks.go index 01169d56..bab579ea 100644 --- a/cluster/cluster_tasks.go +++ b/cluster/cluster_tasks.go @@ -41,7 +41,7 @@ func CheckInNode() error { } 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 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 } 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) // reload scheduler as most events should only be executed by the cluster master diff --git a/config/config.go b/config/config.go index af74482e..8d9f200a 100644 --- a/config/config.go +++ b/config/config.go @@ -155,19 +155,19 @@ func SetLicense(l types.License) { license = l } func SetLogLevels() { - log.SetLogLevel("api", int(GetUint64("logApi"))) - log.SetLogLevel("backup", int(GetUint64("logBackup"))) - log.SetLogLevel("cache", int(GetUint64("logCache"))) - log.SetLogLevel("cluster", int(GetUint64("logCluster"))) - log.SetLogLevel("csv", int(GetUint64("logCsv"))) - log.SetLogLevel("imager", int(GetUint64("logImager"))) - log.SetLogLevel("ldap", int(GetUint64("logLdap"))) - log.SetLogLevel("mail", int(GetUint64("logMail"))) - log.SetLogLevel("module", int(GetUint64("logModule"))) - log.SetLogLevel("scheduler", int(GetUint64("logScheduler"))) - log.SetLogLevel("server", int(GetUint64("logServer"))) - log.SetLogLevel("transfer", int(GetUint64("logTransfer"))) - log.SetLogLevel("websocket", int(GetUint64("logWebsocket"))) + log.SetLogLevel(log.ContextApi, int(GetUint64("logApi"))) + log.SetLogLevel(log.ContextBackup, int(GetUint64("logBackup"))) + log.SetLogLevel(log.ContextCache, int(GetUint64("logCache"))) + log.SetLogLevel(log.ContextCluster, int(GetUint64("logCluster"))) + log.SetLogLevel(log.ContextCsv, int(GetUint64("logCsv"))) + log.SetLogLevel(log.ContextImager, int(GetUint64("logImager"))) + log.SetLogLevel(log.ContextLdap, int(GetUint64("logLdap"))) + log.SetLogLevel(log.ContextMail, int(GetUint64("logMail"))) + log.SetLogLevel(log.ContextModule, int(GetUint64("logModule"))) + log.SetLogLevel(log.ContextScheduler, int(GetUint64("logScheduler"))) + log.SetLogLevel(log.ContextServer, int(GetUint64("logServer"))) + log.SetLogLevel(log.ContextTransfer, int(GetUint64("logTransfer"))) + log.SetLogLevel(log.ContextWebsocket, int(GetUint64("logWebsocket"))) } func SetInstanceIdIfEmpty_tx(ctx context.Context, tx pgx.Tx) error { if GetString("instanceId") != "" { diff --git a/config/config_activation.go b/config/config_activation.go index 6f8fd5ad..fa0709e1 100644 --- a/config/config_activation.go +++ b/config/config_activation.go @@ -67,7 +67,7 @@ vCPF8QXc4V/wgJZtn6vdSXGR5W0dByItU5TLOlk6kLX4Aj6G8T+J//7NX5InD5Q/ func ActivateLicense() { 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 SetLicense(types.License{}) @@ -77,13 +77,13 @@ func ActivateLicense() { var licFile types.LicenseFile 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 } licenseJson, err := json.Marshal(licFile.License) if err != nil { - log.Error("server", "could not marshal license data", err) + log.Error(log.ContextServer, "could not marshal license data", err) return } hashed := sha256.Sum256(licenseJson) @@ -91,34 +91,34 @@ func ActivateLicense() { // get license signature signature, err := base64.URLEncoding.DecodeString(licFile.Signature) if err != nil { - log.Error("server", "could not decode license signature", err) + log.Error(log.ContextServer, "could not decode license signature", err) return } // verify signature data, _ := pem.Decode([]byte(publicKey)) 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 } key, err := x509.ParsePKCS1PublicKey(data.Bytes) 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 } 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 } // check if license has been revoked 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 } // set license - log.Info("server", "setting license") + log.Info(log.ContextServer, "setting license") SetLicense(licFile.License) } diff --git a/config/config_store.go b/config/config_store.go index abf2e470..ae8f7bd2 100644 --- a/config/config_store.go +++ b/config/config_store.go @@ -94,7 +94,7 @@ func GetString(name string) string { defer access_mx.RUnlock() 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)) return "" @@ -106,7 +106,7 @@ func GetUint64(name string) uint64 { defer access_mx.RUnlock() 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)) return 0 @@ -118,7 +118,7 @@ func GetUint64Slice(name string) []uint64 { defer access_mx.RUnlock() 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)) return make([]uint64, 0) diff --git a/data/data_image/data_image.go b/data/data_image/data_image.go index 4701491a..8eb58b66 100644 --- a/data/data_image/data_image.go +++ b/data/data_image/data_image.go @@ -30,7 +30,7 @@ var ( func PrepareProcessing(filePathOverwrite string) { 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 { @@ -86,7 +86,7 @@ func processFile(fileId uuid.UUID, ext string, src string, dst string) { // clean extension 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() { fileIdMapQueue_mx.Lock() @@ -107,7 +107,7 @@ func processFile(fileId uuid.UUID, ext string, src string, dst string) { fileIdMapFailed[fileId] = true fileIdMapFailed_mx.Unlock() - log.Warning("imager", "failed to create thumbnail", returnErr) + log.Warning(log.ContextImager, "failed to create thumbnail", returnErr) } // 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} 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 } diff --git a/data/data_import/data_import.go b/data/data_import/data_import.go index 3f9fa018..25adf28e 100644 --- a/data/data_import/data_import.go +++ b/data/data_import/data_import.go @@ -229,7 +229,7 @@ func FromInterfaceValues_tx(ctx context.Context, tx pgx.Tx, loginId int64, if !atr.Nullable && setAtr.Value == nil { 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)) badNulls = true diff --git a/db/embedded/embedded_windows.go b/db/embedded/embedded_windows.go index f5ebfba5..2e3aef98 100644 --- a/db/embedded/embedded_windows.go +++ b/db/embedded/embedded_windows.go @@ -58,7 +58,7 @@ func Stop() error { } if !state { - log.Info("server", "embedded database already stopped") + log.Info(log.ContextServer, "embedded database already stopped") return nil } @@ -126,7 +126,7 @@ func execWaitFor(call string, args []string, waitFor []string, waitTime int) (st if err != nil { if err != io.EOF { // 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 } diff --git a/db/upgrade/upgrade.go b/db/upgrade/upgrade.go index 282cf9ef..bddb4d96 100644 --- a/db/upgrade/upgrade.go +++ b/db/upgrade/upgrade.go @@ -38,19 +38,19 @@ func RunIfRequired() error { // loop upgrade procedure until DB version matches application version 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 { // abort when versions match 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 } if err := oneIteration(config.GetDbVersionCut()); err != nil { return err } - log.Info("server", "upgrade successful") + log.Info(log.ContextServer, "upgrade successful") } return nil } @@ -67,7 +67,7 @@ func oneIteration(dbVersionCut string) error { // log before upgrade because changes to log table index // 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)) // execute known DB upgrades @@ -77,7 +77,7 @@ func oneIteration(dbVersionCut string) error { } dbVersionCutNew, err := upgradeFunctions[dbVersionCut](ctx, tx) if err != nil { - log.Error("server", "upgrade NOT successful", err) + log.Error(log.ContextServer, "upgrade NOT successful", 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 FOREIGN KEY (oauth_client_id) REFERENCES instance.oauth_client (id) MATCH SIMPLE - ON UPDATE NO ACTION - ON DELETE NO ACTION; + ON UPDATE CASCADE + ON DELETE CASCADE; 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); @@ -3084,7 +3084,7 @@ var upgradeFunctions = map[string]func(ctx context.Context, tx pgx.Tx) (string, filepath.Join(config.File.Paths.Files, 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) } } diff --git a/handler/api/api.go b/handler/api/api.go index e848151b..5049735e 100644 --- a/handler/api/api.go +++ b/handler/api/api.go @@ -47,7 +47,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { if errToLog == nil { 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(), @@ -120,7 +120,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { } // 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)) // resolve API by module+API names diff --git a/handler/api_auth/api_auth.go b/handler/api_auth/api_auth.go index 84d3d5fe..a9521133 100644 --- a/handler/api_auth/api_auth.go +++ b/handler/api_auth/api_auth.go @@ -15,8 +15,6 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) -var logContext = "api_auth" - func Handler(w http.ResponseWriter, r *http.Request) { 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") 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") return @@ -39,7 +37,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { Password string `json:"password"` } 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") return @@ -53,7 +51,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate requestor res, err := login_auth.User(ctx, req.Username, req.Password, pgtype.Int4{}, pgtype.Text{}) if err != nil { - handler.AbortRequestWithCode(w, logContext, http.StatusUnauthorized, + handler.AbortRequestWithCode(w, handler.ContextApiAuth, http.StatusUnauthorized, err, handler.ErrAuthFailed) bruteforce.BadAttempt(r) @@ -61,7 +59,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { } 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") return diff --git a/handler/cache_download/cache_download.go b/handler/cache_download/cache_download.go index d0670494..6fbbeb3e 100644 --- a/handler/cache_download/cache_download.go +++ b/handler/cache_download/cache_download.go @@ -9,28 +9,24 @@ import ( "time" ) -var ( - handlerContext = "cache_download" -) - func Handler(w http.ResponseWriter, r *http.Request) { // parse getters moduleId, err := handler.ReadUuidGetterFromUrl(r, "module_id") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCacheDownload, err, handler.ErrGeneral) return } dateChange, err := handler.ReadInt64GetterFromUrl(r, "date") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCacheDownload, err, handler.ErrGeneral) return } // load JSON cache for requested module json, err := cache.GetModuleCacheJson(moduleId) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCacheDownload, err, handler.ErrGeneral) return } diff --git a/handler/client_download/client_download.go b/handler/client_download/client_download.go index 99ce4586..b397555a 100644 --- a/handler/client_download/client_download.go +++ b/handler/client_download/client_download.go @@ -11,8 +11,6 @@ import ( "time" ) -var logContext = "client_download" - func Handler(w http.ResponseWriter, r *http.Request) { if blocked := bruteforce.Check(r); blocked { @@ -23,7 +21,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // get authentication token token, err := handler.ReadGetterFromUrl(r, "token") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } @@ -34,7 +32,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate via token 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) return } @@ -42,7 +40,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // parse getters requestedOs, err := handler.ReadGetterFromUrl(r, "os") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } @@ -62,12 +60,12 @@ func Handler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Disposition", "attachment; filename=r3_client.dmg") _, err = w.Write(cache.Client_amd64_mac) default: - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } } diff --git a/handler/client_download/client_download_config.go b/handler/client_download/client_download_config.go index ba4064d4..6543e971 100644 --- a/handler/client_download/client_download_config.go +++ b/handler/client_download/client_download_config.go @@ -23,7 +23,7 @@ func HandlerConfig(w http.ResponseWriter, r *http.Request) { // get authentication token token, err := handler.ReadGetterFromUrl(r, "token") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } @@ -35,7 +35,7 @@ func HandlerConfig(w http.ResponseWriter, r *http.Request) { // check token login, err := login_auth.Token(ctx, token) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrAuthFailed) bruteforce.BadAttempt(r) return } @@ -43,32 +43,32 @@ func HandlerConfig(w http.ResponseWriter, r *http.Request) { // parse getters tokenFixed, err := handler.ReadGetterFromUrl(r, "tokenFixed") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } hostName, err := handler.ReadGetterFromUrl(r, "hostName") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } hostPort, err := handler.ReadInt64GetterFromUrl(r, "hostPort") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } languageCode, err := handler.ReadGetterFromUrl(r, "languageCode") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } deviceName, err := handler.ReadGetterFromUrl(r, "deviceName") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } ssl, err := handler.ReadInt64GetterFromUrl(r, "ssl") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } @@ -114,12 +114,12 @@ func HandlerConfig(w http.ResponseWriter, r *http.Request) { fJson, err := json.MarshalIndent(f, "", "\t") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } if _, err := w.Write(fJson); err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextClientDownload, err, handler.ErrGeneral) return } } diff --git a/handler/csv_download/csv_download.go b/handler/csv_download/csv_download.go index b00ebd0a..6ab97882 100644 --- a/handler/csv_download/csv_download.go +++ b/handler/csv_download/csv_download.go @@ -26,10 +26,6 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) -var ( - handlerContext = "csv_download" -) - func Handler(w http.ResponseWriter, r *http.Request) { if blocked := bruteforce.Check(r); blocked { @@ -42,77 +38,77 @@ func Handler(w http.ResponseWriter, r *http.Request) { // read getters from URL token, err := handler.ReadGetterFromUrl(r, "token") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } commaChar, err := handler.ReadGetterFromUrl(r, "comma_char") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } dateFormat, err := handler.ReadGetterFromUrl(r, "date_format") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } timezone, err := handler.ReadGetterFromUrl(r, "timezone") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } boolFalse, err := handler.ReadGetterFromUrl(r, "bool_false") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } boolTrue, err := handler.ReadGetterFromUrl(r, "bool_true") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } ignoreHeaderString, err := handler.ReadGetterFromUrl(r, "ignore_header") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } relationIdString, err := handler.ReadGetterFromUrl(r, "relation_id") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } joinsString, err := handler.ReadGetterFromUrl(r, "joins") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } expressionsString, err := handler.ReadGetterFromUrl(r, "expressions") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } filtersString, err := handler.ReadGetterFromUrl(r, "filters") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } ordersString, err := handler.ReadGetterFromUrl(r, "orders") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } totalLimitString, err := handler.ReadGetterFromUrl(r, "total_limit") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } columnsString, err := handler.ReadGetterFromUrl(r, "columns") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } var columns []types.Column 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 } @@ -121,36 +117,36 @@ func Handler(w http.ResponseWriter, r *http.Request) { get.RelationId, err = uuid.FromString(relationIdString) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } 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 } 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 } 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 } 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 } totalLimit, err := strconv.Atoi(totalLimitString) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } ignoreHeader := ignoreHeaderString == "true" // check invalid parameters 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) return @@ -164,7 +160,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate via token login, err := login_auth.Token(ctx, token) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrUnauthorized) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrUnauthorized) bruteforce.BadAttempt(r) return } @@ -176,15 +172,15 @@ func Handler(w http.ResponseWriter, r *http.Request) { // prepare CSV file filePath, err := tools.GetUniqueFilePath(config.File.Paths.Temp, 8999999, 9999999) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) 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) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } defer file.Close() @@ -212,7 +208,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // fallback to attribute title atr, exists := cache.AttributeIdMap[expr.AttributeId.Bytes] 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 } @@ -224,13 +220,13 @@ func Handler(w http.ResponseWriter, r *http.Request) { // fallback to attribute + relation name rel, exists := cache.RelationIdMap[atr.RelationId] if !exists { - handler.AbortRequest(w, handlerContext, handler.ErrSchemaUnknownRelation(atr.RelationId), handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, handler.ErrSchemaUnknownRelation(atr.RelationId), handler.ErrGeneral) return } columnNames[i] = rel.Name + "." + atr.Name } if err := writer.Write(columnNames); err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } } @@ -245,7 +241,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // load user location based on timezone for datetime values locUser, err := time.LoadLocation(timezone) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } @@ -254,7 +250,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { for i, column := range columns { atr, exists := cache.AttributeIdMap[column.AttributeId] if !exists { - handler.AbortRequest(w, handlerContext, nil, + handler.AbortRequest(w, handler.ContextCsvDownload, nil, handler.ErrSchemaUnknownAttribute(column.AttributeId).Error()) return @@ -267,7 +263,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { dateFormat, columnAttributeContentUse, login.Id) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } @@ -280,11 +276,11 @@ func Handler(w http.ResponseWriter, r *http.Request) { writer.Flush() if err := writer.Error(); err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } if err := file.Close(); err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvDownload, err, handler.ErrGeneral) return } diff --git a/handler/csv_upload/csv_upload.go b/handler/csv_upload/csv_upload.go index 350c57c9..3714e0b7 100644 --- a/handler/csv_upload/csv_upload.go +++ b/handler/csv_upload/csv_upload.go @@ -27,8 +27,6 @@ import ( "github.com/jackc/pgx/v5" ) -var handlerContext = "csv_upload" - func Handler(w http.ResponseWriter, r *http.Request) { if blocked := bruteforce.Check(r); blocked { @@ -40,7 +38,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { reader, err := r.MultipartReader() if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral) return } @@ -73,17 +71,17 @@ func Handler(w http.ResponseWriter, r *http.Request) { token = handler.GetStringFromPart(part) case "columns": 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 } case "joins": 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 } case "lookups": 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 } case "boolTrue": @@ -110,7 +108,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate via token login, err := login_auth.Token(ctx, token) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrUnauthorized) + handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrUnauthorized) bruteforce.BadAttempt(r) return } @@ -122,20 +120,20 @@ func Handler(w http.ResponseWriter, r *http.Request) { // store file in temporary directory filePath, err := tools.GetUniqueFilePath(config.File.Paths.Temp, 8999999, 9999999) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral) return } dest, err := os.Create(filePath) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral) return } defer os.Remove(filePath) defer dest.Close() if _, err := io.Copy(dest, part); err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral) return } @@ -148,14 +146,15 @@ func Handler(w http.ResponseWriter, r *http.Request) { res.Error = err.Error() 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) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextCsvUpload, err, handler.ErrGeneral) return } 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, 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) if err != nil { @@ -217,7 +216,7 @@ func importFromCsv(ctx context.Context, filePath string, loginId int64, boolTrue 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, values, columns, joins, lookups, indexMapPgIndexAttributeIds); err != nil { diff --git a/handler/data_access/data_access.go b/handler/data_access/data_access.go index d8cbe4d4..13c7e20f 100644 --- a/handler/data_access/data_access.go +++ b/handler/data_access/data_access.go @@ -24,10 +24,7 @@ type accessRequest struct { Request json.RawMessage `json:"request"` } -var ( - allowedActions = []string{"del", "get", "set"} - handlerContext = "data_access" -) +var allowedActions = []string{"del", "get", "set"} 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") 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") return @@ -48,12 +45,12 @@ func Handler(w http.ResponseWriter, r *http.Request) { // parse body var req accessRequest 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 } 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") return @@ -67,7 +64,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate requestor login, err := login_auth.Token(ctx, req.Token) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrAuthFailed) + handler.AbortRequest(w, handler.ContextDataAccess, err, handler.ErrAuthFailed) bruteforce.BadAttempt(r) return } @@ -75,29 +72,29 @@ func Handler(w http.ResponseWriter, r *http.Request) { // execute request tx, err := db.Pool.Begin(ctx) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataAccess, err, handler.ErrGeneral) return } 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, types.WebsocketClientDeviceBrowser, login.NoAuth, "data", req.Action, req.Request) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataAccess, err, handler.ErrGeneral) return } if err := tx.Commit(ctx); err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataAccess, err, handler.ErrGeneral) return } resJson, err := json.Marshal(res) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataAccess, err, handler.ErrGeneral) return } w.Write(resJson) diff --git a/handler/data_auth/data_auth.go b/handler/data_auth/data_auth.go index 00534e53..fdc1177b 100644 --- a/handler/data_auth/data_auth.go +++ b/handler/data_auth/data_auth.go @@ -15,8 +15,6 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) -var logContext = "data_auth" - func Handler(w http.ResponseWriter, r *http.Request) { 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") 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") return @@ -39,7 +37,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { Password string `json:"password"` } 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 } @@ -51,7 +49,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate requestor res, err := login_auth.User(ctx, req.Username, req.Password, pgtype.Int4{}, pgtype.Text{}) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) + handler.AbortRequest(w, handler.ContextDataAuth, err, handler.ErrAuthFailed) bruteforce.BadAttempt(r) return } diff --git a/handler/data_download/data_download.go b/handler/data_download/data_download.go index bd1d4864..fef969c5 100644 --- a/handler/data_download/data_download.go +++ b/handler/data_download/data_download.go @@ -14,8 +14,6 @@ import ( "time" ) -var logContext = "data_download" - func Handler(w http.ResponseWriter, r *http.Request) { if blocked := bruteforce.Check(r); blocked { @@ -26,7 +24,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // get authentication token token, err := handler.ReadGetterFromUrl(r, "token") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataDownload, err, handler.ErrGeneral) return } @@ -38,7 +36,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate via token login, err := login_auth.Token(ctx, token) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) + handler.AbortRequest(w, handler.ContextDataDownload, err, handler.ErrAuthFailed) bruteforce.BadAttempt(r) return } @@ -46,18 +44,18 @@ func Handler(w http.ResponseWriter, r *http.Request) { // parse other getters attributeId, err := handler.ReadUuidGetterFromUrl(r, "attribute_id") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataDownload, err, handler.ErrGeneral) return } fileId, err := handler.ReadUuidGetterFromUrl(r, "file_id") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataDownload, err, handler.ErrGeneral) return } // check file access privilege 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 } @@ -70,7 +68,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { if version == -1 { version, err = data.FileGetLatestVersion(fileId) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataDownload, err, handler.ErrGeneral) return } } diff --git a/handler/data_download_thumb/data_download_thumb.go b/handler/data_download_thumb/data_download_thumb.go index eaeb1b67..0c895446 100644 --- a/handler/data_download_thumb/data_download_thumb.go +++ b/handler/data_download_thumb/data_download_thumb.go @@ -15,8 +15,6 @@ import ( "time" ) -var logContext = "data_download_thumb" - func Handler(w http.ResponseWriter, r *http.Request) { if blocked := bruteforce.Check(r); blocked { @@ -33,7 +31,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // get authentication token token, err := handler.ReadGetterFromUrl(r, "token") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrGeneral) return } @@ -45,7 +43,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate via token login, err := login_auth.Token(ctx, token) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) + handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrAuthFailed) bruteforce.BadAttempt(r) return } @@ -53,18 +51,18 @@ func Handler(w http.ResponseWriter, r *http.Request) { // parse other getters attributeId, err := handler.ReadUuidGetterFromUrl(r, "attribute_id") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrGeneral) return } fileId, err := handler.ReadUuidGetterFromUrl(r, "file_id") if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrGeneral) return } // check file access privilege 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 } @@ -73,7 +71,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { _, err = os.Stat(filePath) if err != nil && !os.IsNotExist(err) { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrGeneral) return } @@ -84,7 +82,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { version, err := data.FileGetLatestVersion(fileId) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataDownloadThumb, err, handler.ErrGeneral) return } filePathSrc := data.GetFilePathVersion(fileId, version) diff --git a/handler/data_upload/data_upload.go b/handler/data_upload/data_upload.go index 7157b4b3..e3f658ce 100644 --- a/handler/data_upload/data_upload.go +++ b/handler/data_upload/data_upload.go @@ -16,8 +16,6 @@ import ( "github.com/gofrs/uuid" ) -var logContext = "data_upload" - func Handler(w http.ResponseWriter, r *http.Request) { if blocked := bruteforce.Check(r); blocked { @@ -29,7 +27,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { reader, err := r.MultipartReader() if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrGeneral) return } @@ -74,7 +72,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate via token login, err := login_auth.Token(ctx, token) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) + handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrAuthFailed) bruteforce.BadAttempt(r) return } @@ -82,14 +80,14 @@ func Handler(w http.ResponseWriter, r *http.Request) { // parse attribute ID attributeId, err := uuid.FromString(attributeIdString) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrGeneral) return } // parse file ID fileId, err := uuid.FromString(fileIdString) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrGeneral) return } @@ -98,13 +96,13 @@ func Handler(w http.ResponseWriter, r *http.Request) { if isNewFile { fileId, err = uuid.NewV4() if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrGeneral) return } } 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 } response.Id = fileId @@ -112,7 +110,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { responseJson, err := json.Marshal(response) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextDataUpload, err, handler.ErrGeneral) return } w.Write(responseJson) diff --git a/handler/handler.go b/handler/handler.go index 4eacf33d..c869fd70 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -12,7 +12,46 @@ import ( "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 ( + 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 ) @@ -53,14 +92,12 @@ func SetNoImage(v []byte) { 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) } -func AbortRequestWithCode(w http.ResponseWriter, context string, - httpCode int, errToLog error, errMessageUser string) { - - log.Error("server", fmt.Sprintf("aborted %s request", context), errToLog) +func AbortRequestWithCode(w http.ResponseWriter, context handlerContext, httpCode int, errToLog error, errMessageUser string) { + log.Error(log.ContextServer, fmt.Sprintf("aborted %s request", ContextNameMap[context]), errToLog) w.Header().Set("Content-Type", "application/json") w.WriteHeader(httpCode) diff --git a/handler/icon_upload/icon_upload.go b/handler/icon_upload/icon_upload.go index 468eb25f..19ac4a96 100644 --- a/handler/icon_upload/icon_upload.go +++ b/handler/icon_upload/icon_upload.go @@ -17,8 +17,6 @@ import ( "github.com/gofrs/uuid" ) -var logContext = "icon_upload" - func Handler(w http.ResponseWriter, r *http.Request) { if blocked := bruteforce.Check(r); blocked { @@ -30,7 +28,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { reader, err := r.MultipartReader() if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral) return } @@ -71,56 +69,56 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate via token login, err := login_auth.Token(ctx, token) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) + handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrAuthFailed) bruteforce.BadAttempt(r) return } if !login.Admin { - handler.AbortRequest(w, logContext, err, handler.ErrUnauthorized) + handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrUnauthorized) return } // parse module ID moduleId, err := uuid.FromString(moduleIdString) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral) return } // parse icon ID iconId, err := uuid.FromString(iconIdString) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral) return } // insert/update icon tx, err := db.Pool.Begin(ctx) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral) return } defer tx.Rollback(ctx) buf := new(bytes.Buffer) if _, err := buf.ReadFrom(part); err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral) return } // check size 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 } 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 } if err := tx.Commit(ctx); err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIconUpload, err, handler.ErrGeneral) return } } diff --git a/handler/ics_download/ics_download.go b/handler/ics_download/ics_download.go index e1f954b8..54a5d448 100644 --- a/handler/ics_download/ics_download.go +++ b/handler/ics_download/ics_download.go @@ -25,8 +25,6 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) -var handlerContext = "ics_download" - func Handler(w http.ResponseWriter, r *http.Request) { if config.GetUint64("icsDownload") != 1 { @@ -45,17 +43,17 @@ func Handler(w http.ResponseWriter, r *http.Request) { // parse getters fieldId, err := handler.ReadUuidGetterFromUrl(r, "field_id") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral) return } loginIdRequested, err := handler.ReadInt64GetterFromUrl(r, "login_id") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral) return } tokenFixed, err := handler.ReadGetterFromUrl(r, "token_fixed") if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral) return } @@ -67,7 +65,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate via fixed token login, err := login_auth.TokenFixed(ctx, loginIdRequested, "ics", tokenFixed) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrAuthFailed) + handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrAuthFailed) bruteforce.BadAttempt(r) return } @@ -75,20 +73,20 @@ func Handler(w http.ResponseWriter, r *http.Request) { // start DB transaction tx, err := db.Pool.Begin(ctx) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral) return } defer tx.Rollback(ctx) 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 } // get calendar field details from cache f, err := cache.GetCalendarField_tx(ctx, tx, fieldId) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral) return } @@ -198,7 +196,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { atr, exists := cache.AttributeIdMap[column.AttributeId] if !exists { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral) return } if schema.IsContentFiles(atr.Content) { @@ -213,11 +211,11 @@ func Handler(w http.ResponseWriter, r *http.Request) { var query string results, _, err := data.Get_tx(ctx, tx, dataGet, login.Id, &query) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral) return } if err := tx.Commit(ctx); err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral) return } @@ -240,7 +238,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { WHERE id = $1 ) `, f.OpenForm.FormIdOpen).Scan(&modName, &modNameParent); err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextIcsUpload, err, handler.ErrGeneral) return } @@ -270,7 +268,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { recordId, exists := result.IndexRecordIds[f.IndexDate0] 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) return @@ -290,7 +288,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { reflect.TypeOf(result.Values[0]).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) return diff --git a/handler/license_upload/license_upload.go b/handler/license_upload/license_upload.go index 96bacd24..0b5dafba 100644 --- a/handler/license_upload/license_upload.go +++ b/handler/license_upload/license_upload.go @@ -15,8 +15,6 @@ import ( "time" ) -var logContext = "license_upload" - func Handler(w http.ResponseWriter, r *http.Request) { if blocked := bruteforce.Check(r); blocked { @@ -28,7 +26,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { reader, err := r.MultipartReader() if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrGeneral) return } @@ -57,47 +55,47 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate via token login, err := login_auth.Token(ctx, token) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrAuthFailed) + handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrAuthFailed) bruteforce.BadAttempt(r) return } if !login.Admin { - handler.AbortRequest(w, logContext, err, handler.ErrUnauthorized) + handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrUnauthorized) return } // read file into buffer buf := new(bytes.Buffer) if _, err := buf.ReadFrom(part); err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrGeneral) return } // check size 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 } // set license tx, err := db.Pool.Begin(ctx) if err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrGeneral) return } defer tx.Rollback(ctx) 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 } 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 } if err := tx.Commit(ctx); err != nil { - handler.AbortRequest(w, logContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextLicenseUpload, err, handler.ErrGeneral) return } } diff --git a/handler/manifest_download/manifest_download.go b/handler/manifest_download/manifest_download.go index 9815e1ef..3a3c30c5 100644 --- a/handler/manifest_download/manifest_download.go +++ b/handler/manifest_download/manifest_download.go @@ -38,26 +38,23 @@ type manifest struct { StartUrl string `json:"start_url"` } -var ( - handlerContext = "manifest_download" - manifestDefault = manifest{ - Id: "platform", - Name: "REI3", - ShortName: "REI3", - Scope: "/", - StartUrl: "/", - Display: "standalone", - Orientation: "any", - BackgroundColor: "#f5f5f5", - ThemeColor: "#444444", - Icons: []icon{ - {Purpose: "any", Sizes: "192x192", Src: "/images/icon_fav192.png", Type: "image/png"}, - {Purpose: "any", Sizes: "512x512", Src: "/images/icon_fav512.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"}, - }, - } -) +var manifestDefault = manifest{ + Id: "platform", + Name: "REI3", + ShortName: "REI3", + Scope: "/", + StartUrl: "/", + Display: "standalone", + Orientation: "any", + BackgroundColor: "#f5f5f5", + ThemeColor: "#444444", + Icons: []icon{ + {Purpose: "any", Sizes: "192x192", Src: "/images/icon_fav192.png", Type: "image/png"}, + {Purpose: "any", Sizes: "512x512", Src: "/images/icon_fav512.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) { @@ -103,7 +100,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { payloadJson, err := json.Marshal(manifestApp) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextManifestDownload, err, handler.ErrGeneral) return } @@ -120,13 +117,13 @@ func Handler(w http.ResponseWriter, r *http.Request) { moduleId, err := uuid.FromString(elements[2]) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextManifestDownload, err, handler.ErrGeneral) return } module, exists := cache.ModuleIdMap[moduleId] if !exists { - handler.AbortRequest(w, handlerContext, handler.ErrSchemaUnknownModule(moduleId), handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextManifestDownload, handler.ErrSchemaUnknownModule(moduleId), handler.ErrGeneral) return } @@ -135,7 +132,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { if module.ParentId.Valid { parent, exists := cache.ModuleIdMap[module.ParentId.Bytes] 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 } parentName = parent.Name @@ -162,12 +159,12 @@ func Handler(w http.ResponseWriter, r *http.Request) { if module.IconIdPwa1.Valid && module.IconIdPwa2.Valid { iconPwa1, err := cache.GetPwaIcon(module.IconIdPwa1.Bytes) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextManifestDownload, err, handler.ErrGeneral) return } iconPwa2, err := cache.GetPwaIcon(module.IconIdPwa2.Bytes) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextManifestDownload, err, handler.ErrGeneral) return } @@ -179,7 +176,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { payloadJson, err := json.Marshal(manifestMod) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextManifestDownload, err, handler.ErrGeneral) return } diff --git a/handler/transfer_export/transfer_export.go b/handler/transfer_export/transfer_export.go index 90b567ac..5c9fffff 100644 --- a/handler/transfer_export/transfer_export.go +++ b/handler/transfer_export/transfer_export.go @@ -21,7 +21,7 @@ func Handler(w http.ResponseWriter, r *http.Request) { // get authentication token token, err := handler.ReadGetterFromUrl(r, "token") if err != nil { - log.Error("server", genErr, err) + log.Error(log.ContextServer, genErr, err) return } @@ -31,34 +31,34 @@ func Handler(w http.ResponseWriter, r *http.Request) { // authenticate via token login, err := login_auth.Token(ctx, token) if err != nil { - log.Error("server", genErr, err) + log.Error(log.ContextServer, genErr, err) return } if !login.Admin { - log.Error("server", genErr, errors.New(handler.ErrUnauthorized)) + log.Error(log.ContextServer, genErr, errors.New(handler.ErrUnauthorized)) return } // get module ID moduleId, err := handler.ReadUuidGetterFromUrl(r, "module_id") if err != nil { - log.Error("server", genErr, err) + log.Error(log.ContextServer, genErr, err) return } filePath, err := tools.GetUniqueFilePath(config.File.Paths.Temp, 8999999, 9999999) if err != nil { - log.Error("server", genErr, err) + log.Error(log.ContextServer, genErr, err) return } if err := transfer.ExportToFile(ctx, moduleId, filePath); err != nil { - log.Error("server", genErr, err) + log.Error(log.ContextServer, genErr, err) return } http.ServeFile(w, r, filePath) 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) } } diff --git a/handler/transfer_import/transfer_import.go b/handler/transfer_import/transfer_import.go index 81e9bb3d..25220803 100644 --- a/handler/transfer_import/transfer_import.go +++ b/handler/transfer_import/transfer_import.go @@ -25,7 +25,7 @@ func Handler(res http.ResponseWriter, req *http.Request) { if err != nil { 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 { @@ -35,7 +35,7 @@ func Handler(res http.ResponseWriter, req *http.Request) { responseJson, err := json.Marshal(response) 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{}) return } diff --git a/handler/websocket/websocket.go b/handler/websocket/websocket.go index 8e15a94a..00f51b21 100644 --- a/handler/websocket/websocket.go +++ b/handler/websocket/websocket.go @@ -55,8 +55,6 @@ var ( ReadBufferSize: 1024, WriteBufferSize: 1024} - handlerContext = "websocket" - hub = hubType{ clients: make(map[*clientType]bool), clientAdd: make(chan *clientType), @@ -87,21 +85,21 @@ func Handler(w http.ResponseWriter, r *http.Request) { // get client host address host, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextWebsocket, err, handler.ErrGeneral) return } // create unique client ID for session tracking clientId, err := uuid.NewV4() if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextWebsocket, err, handler.ErrGeneral) return } // upgrade to websocket ws, err := clientUpgrader.Upgrade(w, r, nil) if err != nil { - handler.AbortRequest(w, handlerContext, err, handler.ErrGeneral) + handler.AbortRequest(w, handler.ContextWebsocket, err, handler.ErrGeneral) return } @@ -147,15 +145,15 @@ func (hub *hubType) start() { delete(hub.clients, client) 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 { - 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() { // 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 { - 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 { - log.Error(handlerContext, "could not prepare unrequested transaction", err) + log.Error(log.ContextWebsocket, "could not prepare unrequested transaction", err) 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) 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("{}") } - 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)) // 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 { - log.Warning(handlerContext, "failed to authenticate user", err) + log.Warning(log.ContextWebsocket, "failed to authenticate user", err) bruteforce.BadAttemptByHost(client.address) 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 // in this case the login ID is still 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 { - 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 resTransJson, err := json.Marshal(resTrans) if err != nil { - log.Error(handlerContext, "cannot marshal responses", err) + log.Error(log.ContextWebsocket, "cannot marshal responses", err) return []byte("{}") } return resTransJson diff --git a/ldap/ldap.go b/ldap/ldap.go index 2d200279..54848e9b 100644 --- a/ldap/ldap.go +++ b/ldap/ldap.go @@ -4,6 +4,7 @@ import ( "context" "r3/cache" "r3/login" + "r3/login/login_external" "r3/login/login_metaMap" "r3/login/login_roleAssign" "r3/types" @@ -13,7 +14,7 @@ import ( 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 } @@ -84,7 +85,7 @@ func Get_tx(ctx context.Context, tx pgx.Tx) ([]types.Ldap, error) { } 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 { 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 } - 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 nil diff --git a/ldap/ldap_auth/ldap_auth.go b/ldap/ldap_auth/ldap_auth.go index e79137cc..82a490ff 100644 --- a/ldap/ldap_auth/ldap_auth.go +++ b/ldap/ldap_auth/ldap_auth.go @@ -14,7 +14,7 @@ func Check(ldapId int32, username string, password string) error { ldapConn, ldap, err := ldap_conn.ConnectAndBind(ldapId) if err != nil { - log.Error("ldap", "failed to connect or bind", err) + log.Error(log.ContextLdap, "failed to connect or bind", err) return err } defer ldapConn.Close() @@ -30,22 +30,22 @@ func Check(ldapId int32, username string, password string) error { )) if err != nil { - log.Error("ldap", "failed to execute search", err) + log.Error(log.ContextLdap, "failed to execute search", err) return err } if len(search.Entries) != 1 { 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 } // authenticate user by attempting bind with their credentials 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 } - 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 } diff --git a/ldap/ldap_conn/ldap_conn.go b/ldap/ldap_conn/ldap_conn.go index 4a3e97d1..79450196 100644 --- a/ldap/ldap_conn/ldap_conn.go +++ b/ldap/ldap_conn/ldap_conn.go @@ -31,7 +31,7 @@ func ConnectAndBind(ldapId int32) (*goldap.Conn, types.Ldap, error) { 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 if ldap.Tls { diff --git a/ldap/ldap_import/ldap_import.go b/ldap/ldap_import/ldap_import.go index e65b5e5d..135874a7 100644 --- a/ldap/ldap_import/ldap_import.go +++ b/ldap/ldap_import/ldap_import.go @@ -34,7 +34,7 @@ func RunAll() error { ldapIdMap := cache.GetLdapIdMap() 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 } @@ -146,7 +146,7 @@ func run(ldapId int32) error { pagingControl := goldap.NewControlPaging(pageSize) controls := []goldap.Control{pagingControl} 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)) response, err := ldapConn.Search(goldap.NewSearchRequest( @@ -246,14 +246,14 @@ func run(ldapId int32) error { // import 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 { - 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 } } - 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 } diff --git a/log/log.go b/log/log.go index 266ade06..a57a87b9 100644 --- a/log/log.go +++ b/log/log.go @@ -14,28 +14,62 @@ import ( "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 ( + access_mx = sync.RWMutex{} + nodeId = pgtype.UUID{} // ID of the current node + // simple options, accessible without lock debug atomic.Bool outputCli atomic.Bool // write logs also to command line - // log levels - access_mx = sync.RWMutex{} - nodeId = pgtype.UUID{} // ID of the current node - contextLevel = map[string]int{ - "api": 1, - "backup": 1, - "cache": 1, - "cluster": 1, - "csv": 1, - "imager": 1, - "mail": 1, - "module": 1, - "ldap": 1, - "scheduler": 1, - "server": 1, - "transfer": 1, - "websocket": 1, + logContextLevel = map[logContext]int{ + ContextApi: 1, + ContextBackup: 1, + ContextCache: 1, + ContextCluster: 1, + ContextCsv: 1, + ContextImager: 1, + ContextLdap: 1, + ContextMail: 1, + ContextModule: 1, + ContextScheduler: 1, + ContextServer: 1, + ContextTransfer: 1, + ContextWebsocket: 1, + } + logContextName = map[logContext]string{ + 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) { outputCli.Store(state) } -func SetLogLevel(context string, level int) { +func SetLogLevel(context logContext, level int) { access_mx.Lock() defer access_mx.Unlock() - if _, exists := contextLevel[context]; !exists { - return + if _, exists := logContextLevel[context]; exists { + logContextLevel[context] = level } - contextLevel[context] = level } func SetNodeId(id uuid.UUID) { access_mx.Lock() @@ -142,20 +175,20 @@ func SetNodeId(id uuid.UUID) { access_mx.Unlock() } -func Info(context string, message string) { +func Info(context logContext, message string) { 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) } -func Error(context string, message string, err error) { +func Error(context logContext, message string, err error) { 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() nodeIdLocal := nodeId - levelActive, exists := contextLevel[logContext] + levelActive, exists := logContextLevel[logContext] access_mx.RUnlock() if !exists { @@ -177,7 +210,7 @@ func write(level int, logContext string, message string, err error) { // log to CLI if available 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 @@ -195,7 +228,7 @@ func write(level int, logContext string, message string, err error) { if _, err := db.Pool.Exec(ctx, ` INSERT INTO instance.log (level, context, message, date_milli, node_id) 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 outputCli.Load() { diff --git a/login/login.go b/login/login.go index 250ce2f9..3aa7ae91 100644 --- a/login/login.go +++ b/login/login.go @@ -9,6 +9,7 @@ import ( "r3/db" "r3/handler" "r3/log" + "r3/login/login_external" "r3/login/login_meta" "r3/login/login_role" "r3/login/login_setting" @@ -33,15 +34,19 @@ func Del_tx(ctx context.Context, tx pgx.Tx, id int64) error { return err } -// delete all logins for LDAP connector -func DelByLdap_tx(ctx context.Context, tx pgx.Tx, ldapId int32) error { +// delete all logins for external login provider +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) - rows, err := tx.Query(ctx, ` + rows, err := tx.Query(ctx, fmt.Sprintf(` SELECT id FROM instance.login - WHERE ldap_id = $1 - `, ldapId) + WHERE %s_id = $1 + `, entity), entityId) if err != nil { 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 func syncLogin_tx(ctx context.Context, tx pgx.Tx, action string, id int64) { - logContext := "server" logErr := "failed to execute user sync" 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 } @@ -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 { - log.Error(logContext, logErr, err) + log.Error(log.ContextServer, logErr, err) } } cache.Schema_mx.RUnlock() diff --git a/login/login_auth/login_auth_openId.go b/login/login_auth/login_auth_openId.go index cce2a758..b0f44eeb 100644 --- a/login/login_auth/login_auth_openId.go +++ b/login/login_auth/login_auth_openId.go @@ -196,7 +196,7 @@ func OpenId(ctx context.Context, oauthClientId int32, code string, codeVerifier return types.LoginAuthResult{}, err } 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 { return types.LoginAuthResult{}, err diff --git a/login/login_clusterEvent/login_clusterEvent.go b/login/login_clusterEvent/login_clusterEvent.go index 649d375c..cd15674f 100644 --- a/login/login_clusterEvent/login_clusterEvent.go +++ b/login/login_clusterEvent/login_clusterEvent.go @@ -9,18 +9,18 @@ import ( "github.com/jackc/pgx/v5" ) -func Kick_tx(ctx context.Context, tx pgx.Tx, logContext string, loginId int64, loginName string) { - log.Info(logContext, fmt.Sprintf("user account '%s' is locked, kicking active sessions", loginName)) +func Kick_tx(ctx context.Context, tx pgx.Tx, loginId int64, loginName string) { + 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 { - 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) { - log.Info(logContext, fmt.Sprintf("user account '%s' received new roles, renewing access permissions", loginName)) +func Reauth_tx(ctx context.Context, tx pgx.Tx, loginId int64, loginName string) { + 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 { - 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) } } diff --git a/login/login_external/login_external.go b/login/login_external/login_external.go new file mode 100644 index 00000000..68851e79 --- /dev/null +++ b/login/login_external/login_external.go @@ -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 +} diff --git a/login/login_ldap.go b/login/login_ldap.go index 5a181f54..5a53c4df 100644 --- a/login/login_ldap.go +++ b/login/login_ldap.go @@ -93,7 +93,7 @@ func SetLdapLogin(ldap types.Ldap, ldapKey string, name string, 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{}, 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 { - login_clusterEvent.Reauth_tx(ctx, tx, "ldap", loginId, name) + login_clusterEvent.Reauth_tx(ctx, tx, loginId, name) } if !active && activeEx { - login_clusterEvent.Kick_tx(ctx, tx, "ldap", loginId, name) + login_clusterEvent.Kick_tx(ctx, tx, loginId, name) } return tx.Commit(ctx) } diff --git a/login/login_metaMap/login_metaMap.go b/login/login_metaMap/login_metaMap.go index 4811cf01..4e5bbca3 100644 --- a/login/login_metaMap/login_metaMap.go +++ b/login/login_metaMap/login_metaMap.go @@ -3,24 +3,17 @@ package login_metaMap import ( "context" "fmt" + "r3/login/login_external" "r3/types" - "slices" "strings" "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) { var m types.LoginMeta - if err := validateEntity(entity); err != nil { + if err := login_external.ValidateEntity(entity); err != nil { 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 { - if err := validateEntity(entity); err != nil { + if err := login_external.ValidateEntity(entity); err != nil { return err } diff --git a/login/login_roleAssign/login_roleAssign.go b/login/login_roleAssign/login_roleAssign.go index 5980d4f0..0fb33fd0 100644 --- a/login/login_roleAssign/login_roleAssign.go +++ b/login/login_roleAssign/login_roleAssign.go @@ -3,23 +3,16 @@ package login_roleAssign import ( "context" "fmt" + "r3/login/login_external" "r3/types" - "slices" "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) { roles := make([]types.LoginRoleAssign, 0) - if err := validateEntity(entity); err != nil { + if err := login_external.ValidateEntity(entity); err != nil { 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 { - if err := validateEntity(entity); err != nil { + if err := login_external.ValidateEntity(entity); err != nil { return err } diff --git a/r3.go b/r3.go index e33dec82..037ae31a 100644 --- a/r3.go +++ b/r3.go @@ -395,7 +395,7 @@ func (prg *program) execute(svc service.Service) { // prepare image processing 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) go scheduler.Start() @@ -453,7 +453,7 @@ func (prg *program) execute(svc service.Service) { IdleTimeout: 120 * 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 cli.open && config.File.Web.Port != 0 { @@ -498,7 +498,7 @@ func (prg *program) execute(svc service.Service) { case "1.3": prg.webServer.TLSConfig.MinVersion = tls.VersionTLS13 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)) } 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) 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.Commit(ctx) @@ -635,7 +635,7 @@ func (prg *program) Stop(svc service.Service) error { if err := prg.webServer.Shutdown(ctx); err != nil { 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 @@ -644,7 +644,7 @@ func (prg *program) Stop(svc service.Service) error { prg.logger.Error(err) } db.Close() - log.Info("server", "stopped database handler") + log.Info(log.ContextServer, "stopped database handler") } // stop embedded database if owned @@ -652,7 +652,7 @@ func (prg *program) Stop(svc service.Service) error { if err := embedded.Stop(); err != nil { prg.logger.Error(err) } - log.Info("server", "stopped embedded database") + log.Info(log.ContextServer, "stopped embedded database") } return nil } diff --git a/request/request.go b/request/request.go index a8670940..720cc298 100644 --- a/request/request.go +++ b/request/request.go @@ -25,14 +25,14 @@ func ExecTransaction(ctx context.Context, address string, loginId int64, isAdmin tx, err := db.Pool.Begin(ctx) if err != nil { - log.Error("websocket", "cannot begin transaction", err) + log.Error(log.ContextWebsocket, "cannot begin transaction", err) return responses, errors.New(handler.ErrGeneral) } defer tx.Rollback(ctx) if clearDbCache { 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 } } @@ -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() 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) return responses, err @@ -49,14 +49,14 @@ func ExecTransaction(ctx context.Context, address string, loginId int64, isAdmin // work through 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)) payload, err := Exec_tx(ctx, tx, address, loginId, isAdmin, device, isNoAuth, req.Ressource, req.Action, req.Payload) if err != nil { returnErr, isExpected := handler.ConvertToErrCode(err, !isAdmin) 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) } return responses, returnErr @@ -73,7 +73,7 @@ func ExecTransaction(ctx context.Context, address string, loginId int64, isAdmin if err := tx.Commit(ctx); err != nil { returnErr, isExpected := handler.ConvertToErrCode(err, !isAdmin) 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) } return responses, returnErr diff --git a/request/request_oauth_client.go b/request/request_oauth_client.go index ebe5d56f..9165cde0 100644 --- a/request/request_oauth_client.go +++ b/request/request_oauth_client.go @@ -4,6 +4,8 @@ import ( "context" "encoding/json" "r3/cache" + "r3/login" + "r3/login/login_external" "r3/login/login_metaMap" "r3/login/login_roleAssign" "r3/types" @@ -12,17 +14,19 @@ import ( ) func OauthClientDel_tx(ctx context.Context, tx pgx.Tx, reqJson json.RawMessage) (interface{}, error) { - var req struct { - Id int64 `json:"id"` + var id int32 + 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 } _, err := tx.Exec(ctx, ` DELETE FROM instance.oauth_client WHERE id = $1 - `, req.Id) + `, id) return nil, err } @@ -66,10 +70,10 @@ func OauthClientSet_tx(ctx context.Context, tx pgx.Tx, reqJson json.RawMessage) 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 } - 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, nil diff --git a/scheduler/scheduler.go b/scheduler/scheduler.go index 8e2b42af..0692ec53 100644 --- a/scheduler/scheduler.go +++ b/scheduler/scheduler.go @@ -82,22 +82,22 @@ var ( func Start() { time.Sleep(loopIntervalStartWait) - log.Info("scheduler", "started") + log.Info(log.ContextScheduler, "started") for { time.Sleep(loopInterval) if loopStopping.Load() { - log.Info("scheduler", "stopped") + log.Info(log.ContextScheduler, "stopped") return } if err := runTasksBySchedule(); err != nil { - log.Error("scheduler", "failed to start tasks", err) + log.Error(log.ContextScheduler, "failed to start tasks", err) } } } func Stop() { loopStopping.Store(true) - log.Info("scheduler", "stopping") + log.Info(log.ContextScheduler, "stopping") } func init() { @@ -154,7 +154,7 @@ func runTasksBySchedule() error { 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)) } @@ -229,11 +229,11 @@ func runTaskByIndex(taskIndex int) { // run task and store schedule meta data 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))) 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) } @@ -245,12 +245,12 @@ func runTaskByIndex(taskIndex int) { if 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 { - log.Info("scheduler", fmt.Sprintf("task '%s' executed successfully", t.nameLog)) + log.Info(log.ContextScheduler, fmt.Sprintf("task '%s' executed successfully", t.nameLog)) } } 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 @@ -274,7 +274,7 @@ func runTaskByIndex(taskIndex int) { } func load() error { - log.Info("scheduler", "is updating its configuration") + log.Info(log.ContextScheduler, "is updating its configuration") tasks = nil // get system tasks and their states diff --git a/scheduler/scheduler_adminMails.go b/scheduler/scheduler_adminMails.go index e91f05f8..1191b2ef 100644 --- a/scheduler/scheduler_adminMails.go +++ b/scheduler/scheduler_adminMails.go @@ -38,7 +38,7 @@ func adminMails() error { var sendMail = func(subject string, body string, dateExpiration int64, reason string) error { // get mail receivers 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 } @@ -48,7 +48,7 @@ func adminMails() error { } 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 } diff --git a/scheduler/scheduler_cleanup.go b/scheduler/scheduler_cleanup.go index f3290588..aec51c1b 100644 --- a/scheduler/scheduler_cleanup.go +++ b/scheduler/scheduler_cleanup.go @@ -170,7 +170,7 @@ func cleanUpFiles() error { // if deletion fails, abort and keep its reference as file might be in access 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 } } @@ -190,7 +190,7 @@ func cleanUpFiles() error { 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)) // limit not reached this loop, we are done @@ -240,7 +240,7 @@ func cleanUpFiles() error { // referenced file version exists, attempt to delete it // if deletion fails, abort and keep its reference as file might be in access 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 } @@ -259,7 +259,7 @@ func cleanUpFiles() error { filePathThumb := data.GetFilePathThumb(fileId) if exists, _ := tools.Exists(filePathThumb); exists { 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 } } @@ -282,7 +282,7 @@ func cleanUpFiles() error { if tag.RowsAffected() == 0 { 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())) // limit not reached this loop, we are done diff --git a/scheduler/scheduler_cluster.go b/scheduler/scheduler_cluster.go index 23847895..ba961656 100644 --- a/scheduler/scheduler_cluster.go +++ b/scheduler/scheduler_cluster.go @@ -80,7 +80,7 @@ func clusterProcessEvents() 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 jsonPayload []byte diff --git a/scheduler/scheduler_update.go b/scheduler/scheduler_update.go index cc1ea6da..27afdf02 100644 --- a/scheduler/scheduler_update.go +++ b/scheduler/scheduler_update.go @@ -18,7 +18,7 @@ func updateCheck() error { } 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) if err != nil { @@ -61,6 +61,6 @@ func updateCheck() error { 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 } diff --git a/spooler/mail_receive/mail_receive.go b/spooler/mail_receive/mail_receive.go index 5c5049c7..587b5c18 100644 --- a/spooler/mail_receive/mail_receive.go +++ b/spooler/mail_receive/mail_receive.go @@ -32,7 +32,7 @@ var ( func DoAll() error { if !cache.GetMailAccountsExist() { - log.Info("mail", "cannot start retrieval, no accounts defined") + log.Info(log.ContextMail, "cannot start retrieval, no accounts defined") return nil } @@ -43,10 +43,10 @@ func DoAll() error { 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 { - 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 } } @@ -112,14 +112,14 @@ func do(ma types.MailAccount) error { 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)) if mbox.Messages == 0 { 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 seqDel := new(imap.SeqSet) // messages to delete @@ -145,7 +145,7 @@ func do(ma types.MailAccount) error { for msg := range messages { if err := processMessage(ma.Id, msg, §ion); err != nil { // 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 { // add to deletion sequence if processed successfully @@ -158,7 +158,7 @@ func do(ma types.MailAccount) error { 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))) // if database update was successful, execute mail deletion diff --git a/spooler/mail_send/mail_send.go b/spooler/mail_send/mail_send.go index 9be0b2b8..d44e50fb 100644 --- a/spooler/mail_send/mail_send.go +++ b/spooler/mail_send/mail_send.go @@ -27,7 +27,7 @@ var ( func DoAll() error { if !cache.GetMailAccountsExist() { - log.Info("mail", "cannot start sending, no accounts defined") + log.Info(log.ContextMail, "cannot start sending, no accounts defined") return nil } @@ -59,14 +59,14 @@ func DoAll() error { 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 { if err := do(m); err != nil { // 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) if _, err := db.Pool.Exec(context.Background(), ` @@ -80,7 +80,7 @@ func DoAll() error { } // 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(), ` DELETE FROM instance.mail_spool @@ -201,7 +201,7 @@ func do(m types.Mail) error { fileInfo, err := os.Stat(filePath) if err != nil { 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)) continue @@ -216,7 +216,7 @@ func do(m types.Mail) error { } // send mail - log.Info("mail", fmt.Sprintf("sending message (%d attachments)", + log.Info(log.ContextMail, fmt.Sprintf("sending message (%d attachments)", len(msg.GetAttachments()))) 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 { // 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 - 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 diff --git a/spooler/rest_send/rest_send.go b/spooler/rest_send/rest_send.go index 16aa44af..6dfb44fa 100644 --- a/spooler/rest_send/rest_send.go +++ b/spooler/rest_send/rest_send.go @@ -65,7 +65,7 @@ func DoAll() error { for _, c := range calls { 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(), ` UPDATE instance.rest_spool @@ -74,7 +74,7 @@ func DoAll() error { `, c.id) 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 } @@ -90,7 +90,7 @@ func DoAll() 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)) if err != nil { diff --git a/transfer/transfer_delete/transfer_delete.go b/transfer/transfer_delete/transfer_delete.go index 662e218a..8f6dc94b 100644 --- a/transfer/transfer_delete/transfer_delete.go +++ b/transfer/transfer_delete/transfer_delete.go @@ -137,7 +137,7 @@ func deleteLoginForms_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, log return err } 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 { return err } @@ -154,7 +154,7 @@ func deletePgTriggers_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, pgT return err } 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 { return err } @@ -171,7 +171,7 @@ func deleteRelations_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, rela return err } 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 { return err } @@ -190,7 +190,7 @@ func deleteRelationPgIndexes_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UU return err } 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 { return err } @@ -209,7 +209,7 @@ func deleteRelationAttributes_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.U return err } 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 { return err } @@ -228,7 +228,7 @@ func deleteRelationPresets_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID return err } 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 { return err } @@ -245,7 +245,7 @@ func deleteCollections_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, co return err } 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 { return err } @@ -262,7 +262,7 @@ func deleteRoles_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, roles [] return err } 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 { return err } @@ -279,7 +279,7 @@ func deleteMenuTabs_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, menuT return err } 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 { return err } @@ -296,7 +296,7 @@ func deleteForms_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, forms [] return err } 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 { return err } @@ -427,7 +427,7 @@ func deleteFormFields_tx(ctx context.Context, tx pgx.Tx, form types.Form) error return err } 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 { return err } @@ -439,7 +439,7 @@ func deleteFormFields_tx(ctx context.Context, tx pgx.Tx, form types.Form) error return err } 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 { return err } @@ -451,7 +451,7 @@ func deleteFormFields_tx(ctx context.Context, tx pgx.Tx, form types.Form) error return err } 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 { return err } @@ -468,7 +468,7 @@ func deleteIcons_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, icons [] return err } 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 { return err } @@ -485,7 +485,7 @@ func deleteArticles_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, artic return err } 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 { return err } @@ -502,7 +502,7 @@ func deleteApis_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, apis []ty return err } 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 { return err } @@ -519,7 +519,7 @@ func deleteClientEvents_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, c return err } 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 { return err } @@ -536,7 +536,7 @@ func deleteVariables_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, vari return err } 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 { return err } @@ -553,7 +553,7 @@ func deleteWidgets_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, widget return err } 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 { return err } @@ -570,7 +570,7 @@ func deletePgFunctions_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, pg return err } 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 { return err } @@ -587,7 +587,7 @@ func deleteJsFunctions_tx(ctx context.Context, tx pgx.Tx, moduleId uuid.UUID, js return err } 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 { return err } diff --git a/transfer/transfer_export.go b/transfer/transfer_export.go index 04a3d25d..0b3d623a 100644 --- a/transfer/transfer_export.go +++ b/transfer/transfer_export.go @@ -32,7 +32,7 @@ import ( // dependent app version, release date) will be updated 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 == "" { 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 } - 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)) // user is not owner, export original version diff --git a/transfer/transfer_import.go b/transfer/transfer_import.go index 905b3733..f0527fa4 100644 --- a/transfer/transfer_import.go +++ b/transfer/transfer_import.go @@ -57,7 +57,7 @@ func ImportFromFiles_tx(ctx context.Context, tx pgx.Tx, filePathsImport []string Import_mx.Lock() 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 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") } } - 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 { - 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 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 } } - 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 moduleIdsUpdated := make([]uuid.UUID, 0) @@ -186,7 +186,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun return err } 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)) 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 { 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, 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 { 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, 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 { 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 { return err @@ -261,7 +261,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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 { return err @@ -283,7 +283,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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 { return err @@ -300,7 +300,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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, 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 { 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 { return err @@ -335,7 +335,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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 { return err @@ -351,7 +351,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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 { return err @@ -367,7 +367,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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 { return err @@ -383,7 +383,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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 { return err @@ -400,7 +400,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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 { return err @@ -417,7 +417,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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 { return err @@ -433,7 +433,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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( 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 { 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 { return err @@ -468,7 +468,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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 { return err @@ -484,7 +484,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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 { return err @@ -501,7 +501,7 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { 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 { return err @@ -522,13 +522,13 @@ func importModule_tx(ctx context.Context, tx pgx.Tx, mod types.Module, firstRun if !run { continue } - log.Info("transfer", fmt.Sprintf("set preset %s", e.Id)) + log.Info(log.ContextTransfer, fmt.Sprintf("set preset %s", e.Id)) // special case // 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 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 { return err } @@ -579,7 +579,7 @@ func importCheckResultAndApply(ctx context.Context, tx pgx.Tx, resultErr error, } // 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 { return err @@ -594,7 +594,7 @@ func parseModulesFromPaths_tx(ctx context.Context, tx pgx.Tx, filePaths []string 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 for _, filePath := range filePaths { @@ -617,7 +617,7 @@ func parseModulesFromPaths_tx(ctx context.Context, tx pgx.Tx, filePaths []string } 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)) // 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 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.ReleaseBuild)) @@ -647,7 +647,7 @@ func parseModulesFromPaths_tx(ctx context.Context, tx pgx.Tx, filePaths []string } 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)) 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) if _, exists := moduleIdMapImportMeta[moduleId]; exists { 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.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)) moduleIdMapImportMeta[moduleId] = importMeta{ @@ -714,7 +714,7 @@ func parseModulesFromPaths_tx(ctx context.Context, tx pgx.Tx, filePaths []string 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, ", "))) return modules, nil diff --git a/www/comps/admin/adminLoginRolesAssign.js b/www/comps/admin/adminLoginRolesAssign.js index e1ac6465..44437ff9 100644 --- a/www/comps/admin/adminLoginRolesAssign.js +++ b/www/comps/admin/adminLoginRolesAssign.js @@ -53,8 +53,8 @@ let MyAdminLoginRolesAssign = {
diff --git a/www/comps/admin/adminOauthClient.js b/www/comps/admin/adminOauthClient.js index f3b70954..0f645029 100644 --- a/www/comps/admin/adminOauthClient.js +++ b/www/comps/admin/adminOauthClient.js @@ -168,7 +168,7 @@ let MyAdminOauthClient = { {{ capApp.claimRolesHint }} @@ -231,7 +231,7 @@ let MyAdminOauthClient = { (!s.isFlowAuthCodePkce || s.inputs.claimUsername !== '') && (!s.isFlowAuthCodePkce || s.inputs.providerUrl !== '') && (!s.isFlowAuthCodePkce || s.inputs.redirectUrl !== '') && - (!s.isFlowClientCreds || s.inputs.tokenUrl !== ''), + (!s.isFlowClientCreds || s.isTokenUrlSet), inputsOrg:(s) => s.isNew ? { id:0, name:'', @@ -252,8 +252,10 @@ let MyAdminOauthClient = { // simple states hasChanges: (s) => !s.deepIsEqual(s.inputsOrg,s.inputs), + isClaimRolesSet: (s) => s.inputs.claimRoles !== null && s.inputs.claimRoles !== '', isFlowAuthCodePkce:(s) => s.inputs.flow === 'authCodePkce', isFlowClientCreds: (s) => s.inputs.flow === 'clientCreds', + isTokenUrlSet: (s) => s.inputs.tokenUrl !== null && s.inputs.tokenUrl !== '', isNew: (s) => s.id === 0, // stores @@ -316,7 +318,7 @@ let MyAdminOauthClient = { }); }, del() { - ws.send('oauthClient','del',{id:this.id},true).then( + ws.send('oauthClient','del',this.id,true).then( this.reloadAndClose, this.$root.genericError ); @@ -327,6 +329,7 @@ let MyAdminOauthClient = { ws.send('oauthClient','set',{ id:this.id, name:this.inputs.name, + flow:this.inputs.flow, clientId:this.inputs.clientId, clientSecret:this.inputs.clientSecret, dateExpiry:this.inputs.dateExpiry, diff --git a/www/comps/login.js b/www/comps/login.js index 43435b2c..2d721414 100644 --- a/www/comps/login.js +++ b/www/comps/login.js @@ -391,39 +391,49 @@ let MyLogin = { }, // authentication against external identity provider - authenticateExternalOpenId:async function(c) { + authenticateExternalOpenId(c) { this.loading = true; - const url = new URL(c.providerUrl); - const as = await oauth.discoveryRequest(url,{algorithm:'oidc'}).then( - res => oauth.processDiscoveryResponse(url,res), - console.warn + const url = new URL(c.providerUrl); + const errFnc = msg => { + console.warn(msg); + 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