github.com/aacfactory/fns-contrib/databases/sql@v1.2.84/dac/specifications/audit.go (about)

     1  package specifications
     2  
     3  import (
     4  	stdsql "database/sql"
     5  	"fmt"
     6  	"github.com/aacfactory/errors"
     7  	ssql "github.com/aacfactory/fns-contrib/databases/sql"
     8  	"github.com/aacfactory/fns/commons/uid"
     9  	"github.com/aacfactory/fns/context"
    10  	"github.com/aacfactory/fns/services/authorizations"
    11  	"reflect"
    12  	"time"
    13  )
    14  
    15  func setupAudit[T any](by *Column, at *Column, auth authorizations.Authorization, entries []T) {
    16  	for i, entry := range entries {
    17  		rv := reflect.ValueOf(&entry)
    18  		if by != nil {
    19  			rby := by.ReadValue(rv.Elem())
    20  			if rby.IsZero() {
    21  				if by.Type.Name == StringType {
    22  					rby.SetString(auth.Id.String())
    23  				} else if by.Type.Name == IntType {
    24  					rby.SetInt(auth.Id.Int())
    25  				}
    26  			}
    27  		}
    28  		if at != nil {
    29  			rat := at.ReadValue(rv.Elem())
    30  			if at.Type.Value.ConvertibleTo(datetimeType) {
    31  				rat.Set(reflect.ValueOf(time.Now()))
    32  			} else if at.Type.Value.ConvertibleTo(nullTimeType) {
    33  				rat.Set(reflect.ValueOf(stdsql.NullTime{
    34  					Time:  time.Now(),
    35  					Valid: true,
    36  				}))
    37  			} else if at.Type.Value.ConvertibleTo(nullDatetimeType) {
    38  				rat.Set(reflect.ValueOf(ssql.NullDatetime{
    39  					NullTime: stdsql.NullTime{
    40  						Time:  time.Now(),
    41  						Valid: true,
    42  					},
    43  				}))
    44  			} else if at.Type.Value.ConvertibleTo(intType) {
    45  				rat.SetInt(time.Now().UnixMilli())
    46  			} else if at.Type.Value.ConvertibleTo(nullInt64Type) {
    47  				rat.Set(reflect.ValueOf(stdsql.NullInt64{
    48  					Int64: time.Now().UnixMilli(),
    49  					Valid: true,
    50  				}))
    51  			}
    52  		}
    53  		entries[i] = entry
    54  	}
    55  	return
    56  }
    57  
    58  func TrySetupAuditCreation[T any](ctx context.Context, spec *Specification, entries []T) (err error) {
    59  	// id
    60  	pk, hasPk := spec.Pk()
    61  	// creation
    62  	by, at, has := spec.AuditCreation()
    63  	if !has {
    64  		if hasPk && !pk.Incr() {
    65  			for i, entry := range entries {
    66  				rv := reflect.ValueOf(&entry)
    67  				pkf := pk.ReadValue(rv.Elem())
    68  				if pkf.IsZero() {
    69  					pkf.SetString(uid.UID())
    70  					entries[i] = entry
    71  				}
    72  			}
    73  		}
    74  		return
    75  	}
    76  	auth, hasAuth, loadErr := authorizations.Load(ctx)
    77  	if loadErr != nil {
    78  		err = errors.Warning(fmt.Sprintf("sql: %s need audit creation", spec.Key)).WithCause(loadErr)
    79  		return
    80  	}
    81  	if !hasAuth {
    82  		err = errors.Warning(fmt.Sprintf("sql: %s need audit creation", spec.Key)).WithCause(fmt.Errorf("authorization was not found"))
    83  		return
    84  	}
    85  	if !auth.Exist() {
    86  		err = errors.Warning(fmt.Sprintf("sql: %s need audit creation", spec.Key)).WithCause(authorizations.ErrUnauthorized)
    87  		return
    88  	}
    89  	for i, entry := range entries {
    90  		rv := reflect.ValueOf(&entry)
    91  		if by != nil {
    92  			rby := by.ReadValue(rv.Elem())
    93  			if rby.IsZero() {
    94  				if by.Type.Name == StringType {
    95  					rby.SetString(auth.Id.String())
    96  				} else if by.Type.Name == IntType {
    97  					rby.SetInt(auth.Id.Int())
    98  				}
    99  			}
   100  		}
   101  		if at != nil {
   102  			rat := at.ReadValue(rv.Elem())
   103  			if at.Type.Value.ConvertibleTo(datetimeType) {
   104  				rat.Set(reflect.ValueOf(time.Now()))
   105  			} else if at.Type.Value.ConvertibleTo(nullTimeType) {
   106  				rat.Set(reflect.ValueOf(stdsql.NullTime{
   107  					Time:  time.Now(),
   108  					Valid: true,
   109  				}))
   110  			} else if at.Type.Value.ConvertibleTo(nullDatetimeType) {
   111  				rat.Set(reflect.ValueOf(ssql.NullDatetime{
   112  					NullTime: stdsql.NullTime{
   113  						Time:  time.Now(),
   114  						Valid: true,
   115  					},
   116  				}))
   117  			} else if at.Type.Value.ConvertibleTo(intType) {
   118  				rat.SetInt(time.Now().UnixMilli())
   119  			} else if at.Type.Value.ConvertibleTo(nullInt64Type) {
   120  				rat.Set(reflect.ValueOf(stdsql.NullInt64{
   121  					Int64: time.Now().UnixMilli(),
   122  					Valid: true,
   123  				}))
   124  			}
   125  		}
   126  		if hasPk && !pk.Incr() {
   127  			pkf := pk.ReadValue(rv.Elem())
   128  			if pkf.IsZero() {
   129  				pkf.SetString(uid.UID())
   130  			}
   131  		}
   132  		entries[i] = entry
   133  	}
   134  	return
   135  }
   136  
   137  func TrySetupAuditModification[T any](ctx context.Context, spec *Specification, entries []T) (err error) {
   138  	by, at, has := spec.AuditModification()
   139  	if !has {
   140  		return
   141  	}
   142  	auth, hasAuth, loadErr := authorizations.Load(ctx)
   143  	if loadErr != nil {
   144  		err = errors.Warning(fmt.Sprintf("sql: %s need audit modification", spec.Key)).WithCause(loadErr)
   145  		return
   146  	}
   147  	if !hasAuth {
   148  		err = errors.Warning(fmt.Sprintf("sql: %s need audit modification", spec.Key)).WithCause(fmt.Errorf("authorization was not found"))
   149  		return
   150  	}
   151  	if !auth.Exist() {
   152  		err = errors.Warning(fmt.Sprintf("sql: %s need audit modification", spec.Key)).WithCause(authorizations.ErrUnauthorized)
   153  		return
   154  	}
   155  	setupAudit[T](by, at, auth, entries)
   156  	return
   157  }
   158  
   159  func TrySetupAuditDeletion[T any](ctx context.Context, spec *Specification, entries []T) (err error) {
   160  	by, at, has := spec.AuditDeletion()
   161  	if !has {
   162  		return
   163  	}
   164  	auth, hasAuth, loadErr := authorizations.Load(ctx)
   165  	if loadErr != nil {
   166  		err = errors.Warning(fmt.Sprintf("sql: %s need audit deletion", spec.Key)).WithCause(loadErr)
   167  		return
   168  	}
   169  	if !hasAuth {
   170  		err = errors.Warning(fmt.Sprintf("sql: %s need audit deletion", spec.Key)).WithCause(fmt.Errorf("authorization was not found"))
   171  		return
   172  	}
   173  	if !auth.Exist() {
   174  		err = errors.Warning(fmt.Sprintf("sql: %s need audit deletion", spec.Key)).WithCause(authorizations.ErrUnauthorized)
   175  		return
   176  	}
   177  	setupAudit[T](by, at, auth, entries)
   178  	return
   179  }
   180  
   181  func TrySetupAuditVersion[T any](ctx context.Context, entries []T) (err error) {
   182  	spec, specErr := GetSpecification(ctx, entries[0])
   183  	if specErr != nil {
   184  		err = specErr
   185  		return
   186  	}
   187  	column, has := spec.AuditVersion()
   188  	if !has {
   189  		return
   190  	}
   191  	for i, entry := range entries {
   192  		rv := reflect.ValueOf(&entry)
   193  		rvt := column.ReadValue(rv.Elem())
   194  		pv := rvt.Int()
   195  		rvt.SetInt(pv + 1)
   196  		entries[i] = entry
   197  	}
   198  	return
   199  }
   200  
   201  func TrySetupLastInsertId[T any](ctx context.Context, entry T, id int64) (v T, err error) {
   202  	spec, specErr := GetSpecification(ctx, entry)
   203  	if specErr != nil {
   204  		err = specErr
   205  		return
   206  	}
   207  	column, has := spec.Pk()
   208  	if !has {
   209  		err = errors.Warning(fmt.Sprintf("sql: %s has no pk", spec.Key))
   210  		return
   211  	}
   212  	if !column.Incr() {
   213  		err = errors.Warning(fmt.Sprintf("sql: %s has no incr pk", spec.Key))
   214  		return
   215  	}
   216  	rv := reflect.ValueOf(&entry)
   217  	rvt := column.ReadValue(rv.Elem())
   218  	rvt.SetInt(id)
   219  	v = rv.Elem().Interface().(T)
   220  	return
   221  }