Fixed multiple bugs, cleaned up logging calls

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

View File

@@ -33,14 +33,14 @@ func Run() error {
config.GetUint64("backupWeekly") == 0 &&
config.GetUint64("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 {

2
cache/cache_cert.go vendored
View File

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

View File

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

32
cache/cache_schema.go vendored
View File

@@ -152,14 +152,14 @@ func updateSchemaCache_tx(ctx context.Context, tx pgx.Tx, moduleIds []uuid.UUID)
Schema_mx.Lock()
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 {

View File

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

View File

@@ -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") != "" {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -93,7 +93,7 @@ func SetLdapLogin(ldap types.Ldap, ldapKey string, name string,
roleIdsEx = roleIds
}
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)
}

View File

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

View File

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

14
r3.go
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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, &section); 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -168,7 +168,7 @@ let MyAdminOauthClient = {
<span>{{ capApp.claimRolesHint }}</span>
<my-admin-login-roles-assign
v-model="inputs.loginRolesAssign"
:readonly="readonly || inputs.claimRoles === ''"
:readonly="readonly || !isClaimRolesSet"
/>
</div>
</td>
@@ -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,

View File

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