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 }