/
common.go
181 lines (145 loc) · 4.09 KB
/
common.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package frame
import (
"context"
"database/sql"
"fmt"
"github.com/kelseyhightower/envconfig"
"github.com/rs/xid"
"gorm.io/gorm"
"net"
"net/http"
"os"
"strings"
"time"
)
type BaseModelI interface {
GetID() string
GetVersion() uint
}
// BaseModel base table struct to be extended by other models
type BaseModel struct {
ID string `gorm:"type:varchar(50);primary_key"`
CreatedAt time.Time
ModifiedAt time.Time
Version uint `gorm:"DEFAULT 0"`
TenantID string `gorm:"type:varchar(50);"`
PartitionID string `gorm:"type:varchar(50);"`
AccessID string `gorm:"type:varchar(50);"`
DeletedAt gorm.DeletedAt `sql:"index"`
}
func (model *BaseModel) GetID() string {
return model.ID
}
// GenID creates a new id for model if its not existent
func (model *BaseModel) GenID(ctx context.Context) {
if model.ID != "" {
return
}
model.ID = xid.New().String()
authClaim := ClaimsFromContext(ctx)
if authClaim == nil {
return
}
if model.AccessID == "" && authClaim.AccessId() != "" {
model.AccessID = authClaim.AccessId()
}
if model.PartitionID == "" && authClaim.PartitionId() != "" {
model.PartitionID = authClaim.PartitionId()
}
if model.TenantID == "" && authClaim.TenantId() != "" {
model.TenantID = authClaim.TenantId()
}
}
// ValidXID Validates that the supplied string is an xid
func (model *BaseModel) ValidXID(id string) bool {
_, err := xid.FromString(id)
return err == nil
}
func (model *BaseModel) GetVersion() uint {
return model.Version
}
// BeforeSave Ensures we update a migrations time stamps
func (model *BaseModel) BeforeSave(db *gorm.DB) error {
return model.BeforeCreate(db)
}
func (model *BaseModel) BeforeCreate(db *gorm.DB) error {
if model.Version <= 0 {
model.CreatedAt = time.Now()
model.ModifiedAt = time.Now()
model.Version = 1
}
model.GenID(db.Statement.Context)
return nil
}
// BeforeUpdate Updates time stamp every time we update status of a migration
func (model *BaseModel) BeforeUpdate(db *gorm.DB) error {
model.ModifiedAt = time.Now()
model.Version += 1
return nil
}
func (model *BaseModel) CopyPartitionInfo(parent *BaseModel) {
if parent == nil {
return
}
if model.TenantID == "" || model.PartitionID == "" {
model.TenantID = parent.TenantID
model.PartitionID = parent.PartitionID
model.AccessID = parent.AccessID
}
}
// Migration Our simple table holding all the migration data
type Migration struct {
BaseModel
Name string `gorm:"type:varchar(50);uniqueIndex:idx_migrations_name"`
Patch string `gorm:"type:text"`
AppliedAt sql.NullTime
}
// GetIp convenience method to extract the remote ip address from our inbound request
func GetIp(r *http.Request) string {
sourceIp := r.Header.Get("X-FORWARDED-FOR")
if sourceIp == "" {
sourceIp, _, _ = net.SplitHostPort(r.RemoteAddr)
}
return sourceIp
}
// GetEnv Obtains the environment key or returns the default value
func GetEnv(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok {
return value
}
return fallback
}
// GetLocalIP convenince method that obtains the non localhost ip address for machine running app
func GetLocalIP() string {
addrs, _ := net.InterfaceAddrs()
currentIP := ""
for _, address := range addrs {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
currentIP = ipnet.IP.String()
break
} else {
currentIP = ipnet.IP.String()
}
}
return currentIP
}
// GetMacAddress convenience method to get some unique address based on the network interfaces the application is running on.
func GetMacAddress() string {
currentIP := GetLocalIP()
interfaces, _ := net.Interfaces()
for _, interf := range interfaces {
if addrs, err := interf.Addrs(); err == nil {
for _, addr := range addrs {
// only interested in the name with current IP address
if strings.Contains(addr.String(), currentIP) {
return fmt.Sprintf("%s:%s", interf.Name, interf.HardwareAddr.String())
}
}
}
}
return ""
}
// ConfigProcess convenience method to processFunc configs
func ConfigProcess(prefix string, config any) error {
return envconfig.Process(prefix, config)
}