Commit f74a6c3491763d749b2725a7bbba215af1b98511
1 parent
707782344f
Exists in
master
refactored
Showing
3 changed files
with
9 additions
and
98 deletions
Show diff stats
default_values.go
1 | package webutility | File was deleted | |
2 | |||
3 | // Int32ValueOrDefault ... | ||
4 | func Int32ValueOrDefault(val *interface{}) (def int32) { | ||
5 | if *val != nil { | ||
6 | def = (*val).(int32) | ||
7 | } | ||
8 | return def | ||
9 | } | ||
10 | |||
11 | // Int64ValueOrDefault ... | ||
12 | func Int64ValueOrDefault(val *interface{}) (def int64) { | ||
13 | if *val != nil { | ||
14 | def = (*val).(int64) | ||
15 | } | ||
16 | return def | ||
17 | } | ||
18 | |||
19 | // Uint32ValueOrDefault ... | ||
20 | func Uint32ValueOrDefault(val *interface{}) (def uint32) { | ||
21 | if *val != nil { | ||
22 | def = (*val).(uint32) | ||
23 | } | ||
24 | return def | ||
25 | } | ||
26 | |||
27 | // Uint64ValueOrDefault ... | ||
28 | func Uint64ValueOrDefault(val *interface{}) (def uint64) { | ||
29 | if *val != nil { | ||
30 | def = (*val).(uint64) | ||
31 | } | ||
32 | return def | ||
33 | } | ||
34 | |||
35 | // Float32ValueOrDefault ... | ||
36 | func Float32ValueOrDefault(val *interface{}) (def float32) { | ||
37 | if *val != nil { | ||
38 | def = (*val).(float32) | ||
39 | } | ||
40 | return def | ||
41 | } | ||
42 | |||
43 | // Float64ValueOrDefault ... | ||
44 | func Float64ValueOrDefault(val *interface{}) (def float64) { | ||
45 | if *val != nil { | ||
46 | return (*val).(float64) | ||
47 | } | ||
48 | return def | ||
49 | } | ||
50 | |||
51 | // StringValueOrDefault ... | ||
52 | func StringValueOrDefault(val *interface{}) (def string) { | ||
53 | if *val != nil { | ||
54 | def = (*val).(string) | ||
55 | } | ||
56 | return def | ||
57 | } | ||
58 | |||
59 | 1 | package webutility |
payload.go
1 | package webutility | 1 | package webutility |
2 | 2 | ||
3 | import ( | 3 | import ( |
4 | "database/sql" | 4 | "database/sql" |
5 | "encoding/json" | 5 | "encoding/json" |
6 | "errors" | 6 | "errors" |
7 | "fmt" | 7 | "fmt" |
8 | "io" | 8 | "io" |
9 | "net/http" | 9 | "net/http" |
10 | "os" | ||
11 | "strings" | 10 | "strings" |
12 | "sync" | 11 | "sync" |
13 | "time" | 12 | "time" |
14 | 13 | ||
15 | "git.to-net.rs/marko.tikvic/gologger" | 14 | "git.to-net.rs/marko.tikvic/gologger" |
15 | "git.to-net.rs/marko.tikvic/util" | ||
16 | ) | 16 | ) |
17 | 17 | ||
18 | var ( | 18 | var ( |
19 | mu = &sync.Mutex{} | 19 | mu = &sync.Mutex{} |
20 | metadata = make(map[string]Payload) | 20 | metadata = make(map[string]Payload) |
21 | 21 | ||
22 | updateQue = make(map[string][]byte) | 22 | updateQue = make(map[string][]byte) |
23 | 23 | ||
24 | metadataDB *sql.DB | 24 | metadataDB *sql.DB |
25 | activeProject string | 25 | activeProject string |
26 | 26 | ||
27 | inited bool | 27 | inited bool |
28 | driver string | 28 | driver string |
29 | logger *gologger.Logger | 29 | logger *gologger.Logger |
30 | ) | 30 | ) |
31 | 31 | ||
32 | // LangMap ... | 32 | // LangMap ... |
33 | type LangMap map[string]map[string]string | 33 | type LangMap map[string]map[string]string |
34 | 34 | ||
35 | // Field ... | 35 | // Field ... |
36 | type Field struct { | 36 | type Field struct { |
37 | Parameter string `json:"param"` | 37 | Parameter string `json:"param"` |
38 | Type string `json:"type"` | 38 | Type string `json:"type"` |
39 | Visible bool `json:"visible"` | 39 | Visible bool `json:"visible"` |
40 | Editable bool `json:"editable"` | 40 | Editable bool `json:"editable"` |
41 | } | 41 | } |
42 | 42 | ||
43 | // CorrelationField ... | 43 | // CorrelationField ... |
44 | type CorrelationField struct { | 44 | type CorrelationField struct { |
45 | Result string `json:"result"` | 45 | Result string `json:"result"` |
46 | Elements []string `json:"elements"` | 46 | Elements []string `json:"elements"` |
47 | Type string `json:"type"` | 47 | Type string `json:"type"` |
48 | } | 48 | } |
49 | 49 | ||
50 | // Translation ... | 50 | // Translation ... |
51 | type Translation struct { | 51 | type Translation struct { |
52 | Language string `json:"language"` | 52 | Language string `json:"language"` |
53 | FieldsLabels map[string]string `json:"fieldsLabels"` | 53 | FieldsLabels map[string]string `json:"fieldsLabels"` |
54 | } | 54 | } |
55 | 55 | ||
56 | // PaginationLinks ... | 56 | // PaginationLinks ... |
57 | type PaginationLinks struct { | 57 | type PaginationLinks struct { |
58 | Base string `json:"base"` | 58 | Base string `json:"base"` |
59 | Next string `json:"next"` | 59 | Next string `json:"next"` |
60 | Prev string `json:"prev"` | 60 | Prev string `json:"prev"` |
61 | Self string `json:"self"` | 61 | Self string `json:"self"` |
62 | } | 62 | } |
63 | 63 | ||
64 | // PaginationParameters ... | 64 | // PaginationParameters ... |
65 | type PaginationParameters struct { | 65 | type PaginationParameters struct { |
66 | URL string `json:"-"` | 66 | URL string `json:"-"` |
67 | Offset int64 `json:"offset"` | 67 | Offset int64 `json:"offset"` |
68 | Limit int64 `json:"limit"` | 68 | Limit int64 `json:"limit"` |
69 | SortBy string `json:"sortBy"` | 69 | SortBy string `json:"sortBy"` |
70 | Order string `json:"order"` | 70 | Order string `json:"order"` |
71 | } | 71 | } |
72 | 72 | ||
73 | // GetPaginationParameters ... | 73 | // GetPaginationParameters ... |
74 | // TODO(marko) | 74 | // TODO(marko) |
75 | func GetPaginationParameters(req *http.Request) (p PaginationParameters) { | 75 | func GetPaginationParameters(req *http.Request) (p PaginationParameters) { |
76 | return p | 76 | return p |
77 | } | 77 | } |
78 | 78 | ||
79 | // TODO(marko) | 79 | // TODO(marko) |
80 | func (p *PaginationParameters) paginationLinks() (links PaginationLinks) { | 80 | func (p *PaginationParameters) paginationLinks() (links PaginationLinks) { |
81 | return links | 81 | return links |
82 | } | 82 | } |
83 | 83 | ||
84 | // Payload ... | 84 | // Payload ... |
85 | type Payload struct { | 85 | type Payload struct { |
86 | Method string `json:"method"` | 86 | Method string `json:"method"` |
87 | Params map[string]string `json:"params"` | 87 | Params map[string]string `json:"params"` |
88 | Lang []Translation `json:"lang"` | 88 | Lang []Translation `json:"lang"` |
89 | Fields []Field `json:"fields"` | 89 | Fields []Field `json:"fields"` |
90 | Correlations []CorrelationField `json:"correlationFields"` | 90 | Correlations []CorrelationField `json:"correlationFields"` |
91 | IDField string `json:"idField"` | 91 | IDField string `json:"idField"` |
92 | 92 | ||
93 | // Pagination | 93 | // Pagination |
94 | Count int64 `json:"count"` | 94 | Count int64 `json:"count"` |
95 | Total int64 `json:"total"` | 95 | Total int64 `json:"total"` |
96 | Links PaginationLinks `json:"_links"` | 96 | Links PaginationLinks `json:"_links"` |
97 | 97 | ||
98 | // Data holds JSON payload. It can't be used for itteration. | 98 | // Data holds JSON payload. It can't be used for itteration. |
99 | Data interface{} `json:"data"` | 99 | Data interface{} `json:"data"` |
100 | } | 100 | } |
101 | 101 | ||
102 | func (p *Payload) addLang(code string, labels map[string]string) { | 102 | func (p *Payload) addLang(code string, labels map[string]string) { |
103 | t := Translation{ | 103 | t := Translation{ |
104 | Language: code, | 104 | Language: code, |
105 | FieldsLabels: labels, | 105 | FieldsLabels: labels, |
106 | } | 106 | } |
107 | p.Lang = append(p.Lang, t) | 107 | p.Lang = append(p.Lang, t) |
108 | } | 108 | } |
109 | 109 | ||
110 | // SetData ... | 110 | // SetData ... |
111 | func (p *Payload) SetData(data interface{}) { | 111 | func (p *Payload) SetData(data interface{}) { |
112 | p.Data = data | 112 | p.Data = data |
113 | } | 113 | } |
114 | 114 | ||
115 | // SetPaginationInfo ... | 115 | // SetPaginationInfo ... |
116 | func (p *Payload) SetPaginationInfo(count, total int64, params PaginationParameters) { | 116 | func (p *Payload) SetPaginationInfo(count, total int64, params PaginationParameters) { |
117 | p.Count = count | 117 | p.Count = count |
118 | p.Total = total | 118 | p.Total = total |
119 | p.Links = params.paginationLinks() | 119 | p.Links = params.paginationLinks() |
120 | } | 120 | } |
121 | 121 | ||
122 | // NewPayload returs a payload sceleton for entity described with key. | 122 | // NewPayload returs a payload sceleton for entity described with key. |
123 | func NewPayload(r *http.Request, key string) Payload { | 123 | func NewPayload(r *http.Request, key string) Payload { |
124 | p := metadata[key] | 124 | p := metadata[key] |
125 | p.Method = r.Method + " " + r.RequestURI | 125 | p.Method = r.Method + " " + r.RequestURI |
126 | return p | 126 | return p |
127 | } | 127 | } |
128 | 128 | ||
129 | // DecodeJSON decodes JSON data from r to v. | 129 | // DecodeJSON decodes JSON data from r to v. |
130 | // Returns an error if it fails. | 130 | // Returns an error if it fails. |
131 | func DecodeJSON(r io.Reader, v interface{}) error { | 131 | func DecodeJSON(r io.Reader, v interface{}) error { |
132 | return json.NewDecoder(r).Decode(v) | 132 | return json.NewDecoder(r).Decode(v) |
133 | } | 133 | } |
134 | 134 | ||
135 | // InitPayloadsMetadata loads all payloads' information into 'metadata' variable. | 135 | // InitPayloadsMetadata loads all payloads' information into 'metadata' variable. |
136 | func InitPayloadsMetadata(drv string, db *sql.DB, project string) error { | 136 | func InitPayloadsMetadata(drv string, db *sql.DB, project string) error { |
137 | var err error | 137 | var err error |
138 | if drv != "ora" && drv != "mysql" { | 138 | if drv != "ora" && drv != "mysql" { |
139 | err = errors.New("driver not supported") | 139 | err = errors.New("driver not supported") |
140 | return err | 140 | return err |
141 | } | 141 | } |
142 | 142 | ||
143 | driver = drv | 143 | driver = drv |
144 | metadataDB = db | 144 | metadataDB = db |
145 | activeProject = project | 145 | activeProject = project |
146 | 146 | ||
147 | logger, err = gologger.New("metadata", gologger.MaxLogSize100KB) | 147 | logger, err = gologger.New("metadata", gologger.MaxLogSize100KB) |
148 | if err != nil { | 148 | if err != nil { |
149 | fmt.Printf("webutility: %s\n", err.Error()) | 149 | fmt.Printf("webutility: %s\n", err.Error()) |
150 | } | 150 | } |
151 | 151 | ||
152 | mu.Lock() | 152 | mu.Lock() |
153 | defer mu.Unlock() | 153 | defer mu.Unlock() |
154 | err = initMetadata(project) | 154 | err = initMetadata(project) |
155 | if err != nil { | 155 | if err != nil { |
156 | return err | 156 | return err |
157 | } | 157 | } |
158 | inited = true | 158 | inited = true |
159 | 159 | ||
160 | return nil | 160 | return nil |
161 | } | 161 | } |
162 | 162 | ||
163 | // EnableHotloading ... | 163 | // EnableHotloading ... |
164 | func EnableHotloading(interval int) { | 164 | func EnableHotloading(interval int) { |
165 | if interval > 0 { | 165 | if interval > 0 { |
166 | go hotload(interval) | 166 | go hotload(interval) |
167 | } | 167 | } |
168 | } | 168 | } |
169 | 169 | ||
170 | // GetMetadataForAllEntities ... | 170 | // GetMetadataForAllEntities ... |
171 | func GetMetadataForAllEntities() map[string]Payload { | 171 | func GetMetadataForAllEntities() map[string]Payload { |
172 | return metadata | 172 | return metadata |
173 | } | 173 | } |
174 | 174 | ||
175 | // GetMetadataForEntity ... | 175 | // GetMetadataForEntity ... |
176 | func GetMetadataForEntity(t string) (Payload, bool) { | 176 | func GetMetadataForEntity(t string) (Payload, bool) { |
177 | p, ok := metadata[t] | 177 | p, ok := metadata[t] |
178 | return p, ok | 178 | return p, ok |
179 | } | 179 | } |
180 | 180 | ||
181 | // QueEntityModelUpdate ... | 181 | // QueEntityModelUpdate ... |
182 | func QueEntityModelUpdate(entityType string, v interface{}) { | 182 | func QueEntityModelUpdate(entityType string, v interface{}) { |
183 | updateQue[entityType], _ = json.Marshal(v) | 183 | updateQue[entityType], _ = json.Marshal(v) |
184 | } | 184 | } |
185 | 185 | ||
186 | // UpdateEntityModels ... | 186 | // UpdateEntityModels ... |
187 | func UpdateEntityModels(command string) (total, upd, add int, err error) { | 187 | func UpdateEntityModels(command string) (total, upd, add int, err error) { |
188 | if command != "force" && command != "missing" { | 188 | if command != "force" && command != "missing" { |
189 | return total, 0, 0, errors.New("webutility: unknown command: " + command) | 189 | return total, 0, 0, errors.New("webutility: unknown command: " + command) |
190 | } | 190 | } |
191 | 191 | ||
192 | if !inited { | 192 | if !inited { |
193 | return 0, 0, 0, errors.New("webutility: metadata not initialized but update was tried") | 193 | return 0, 0, 0, errors.New("webutility: metadata not initialized but update was tried") |
194 | } | 194 | } |
195 | 195 | ||
196 | total = len(updateQue) | 196 | total = len(updateQue) |
197 | 197 | ||
198 | toUpdate := make([]string, 0) | 198 | toUpdate := make([]string, 0) |
199 | toAdd := make([]string, 0) | 199 | toAdd := make([]string, 0) |
200 | 200 | ||
201 | for k := range updateQue { | 201 | for k := range updateQue { |
202 | if _, exists := metadata[k]; exists { | 202 | if _, exists := metadata[k]; exists { |
203 | if command == "force" { | 203 | if command == "force" { |
204 | toUpdate = append(toUpdate, k) | 204 | toUpdate = append(toUpdate, k) |
205 | } | 205 | } |
206 | } else { | 206 | } else { |
207 | toAdd = append(toAdd, k) | 207 | toAdd = append(toAdd, k) |
208 | } | 208 | } |
209 | } | 209 | } |
210 | 210 | ||
211 | var uStmt *sql.Stmt | 211 | var uStmt *sql.Stmt |
212 | if driver == "ora" { | 212 | if driver == "ora" { |
213 | uStmt, err = metadataDB.Prepare("update entities set entity_model = :1 where entity_type = :2") | 213 | uStmt, err = metadataDB.Prepare("update entities set entity_model = :1 where entity_type = :2") |
214 | if err != nil { | 214 | if err != nil { |
215 | logger.Trace(err.Error()) | 215 | logger.Trace(err.Error()) |
216 | return | 216 | return |
217 | } | 217 | } |
218 | } else if driver == "mysql" { | 218 | } else if driver == "mysql" { |
219 | uStmt, err = metadataDB.Prepare("update entities set entity_model = ? where entity_type = ?") | 219 | uStmt, err = metadataDB.Prepare("update entities set entity_model = ? where entity_type = ?") |
220 | if err != nil { | 220 | if err != nil { |
221 | logger.Trace(err.Error()) | 221 | logger.Trace(err.Error()) |
222 | return | 222 | return |
223 | } | 223 | } |
224 | } | 224 | } |
225 | for _, k := range toUpdate { | 225 | for _, k := range toUpdate { |
226 | _, err = uStmt.Exec(string(updateQue[k]), k) | 226 | _, err = uStmt.Exec(string(updateQue[k]), k) |
227 | if err != nil { | 227 | if err != nil { |
228 | logger.Trace(err.Error()) | 228 | logger.Trace(err.Error()) |
229 | return | 229 | return |
230 | } | 230 | } |
231 | upd++ | 231 | upd++ |
232 | } | 232 | } |
233 | 233 | ||
234 | blankPayload, _ := json.Marshal(Payload{}) | 234 | blankPayload, _ := json.Marshal(Payload{}) |
235 | var iStmt *sql.Stmt | 235 | var iStmt *sql.Stmt |
236 | if driver == "ora" { | 236 | if driver == "ora" { |
237 | iStmt, err = metadataDB.Prepare("insert into entities(projekat, metadata, entity_type, entity_model) values(:1, :2, :3, :4)") | 237 | iStmt, err = metadataDB.Prepare("insert into entities(projekat, metadata, entity_type, entity_model) values(:1, :2, :3, :4)") |
238 | if err != nil { | 238 | if err != nil { |
239 | logger.Trace(err.Error()) | 239 | logger.Trace(err.Error()) |
240 | return | 240 | return |
241 | } | 241 | } |
242 | } else if driver == "mysql" { | 242 | } else if driver == "mysql" { |
243 | iStmt, err = metadataDB.Prepare("insert into entities(projekat, metadata, entity_type, entity_model) values(?, ?, ?, ?)") | 243 | iStmt, err = metadataDB.Prepare("insert into entities(projekat, metadata, entity_type, entity_model) values(?, ?, ?, ?)") |
244 | if err != nil { | 244 | if err != nil { |
245 | logger.Trace(err.Error()) | 245 | logger.Trace(err.Error()) |
246 | return | 246 | return |
247 | } | 247 | } |
248 | } | 248 | } |
249 | for _, k := range toAdd { | 249 | for _, k := range toAdd { |
250 | _, err = iStmt.Exec(activeProject, string(blankPayload), k, string(updateQue[k])) | 250 | _, err = iStmt.Exec(activeProject, string(blankPayload), k, string(updateQue[k])) |
251 | if err != nil { | 251 | if err != nil { |
252 | logger.Trace(err.Error()) | 252 | logger.Trace(err.Error()) |
253 | return | 253 | return |
254 | } | 254 | } |
255 | metadata[k] = Payload{} | 255 | metadata[k] = Payload{} |
256 | add++ | 256 | add++ |
257 | } | 257 | } |
258 | 258 | ||
259 | return total, upd, add, nil | 259 | return total, upd, add, nil |
260 | } | 260 | } |
261 | 261 | ||
262 | func initMetadata(project string) error { | 262 | func initMetadata(project string) error { |
263 | rows, err := metadataDB.Query(`select | 263 | rows, err := metadataDB.Query(`select |
264 | entity_type, | 264 | entity_type, |
265 | metadata | 265 | metadata |
266 | from entities | 266 | from entities |
267 | where projekat = ` + fmt.Sprintf("'%s'", project)) | 267 | where projekat = ` + fmt.Sprintf("'%s'", project)) |
268 | if err != nil { | 268 | if err != nil { |
269 | return err | 269 | return err |
270 | } | 270 | } |
271 | defer rows.Close() | 271 | defer rows.Close() |
272 | 272 | ||
273 | if len(metadata) > 0 { | 273 | if len(metadata) > 0 { |
274 | metadata = nil | 274 | metadata = nil |
275 | } | 275 | } |
276 | metadata = make(map[string]Payload) | 276 | metadata = make(map[string]Payload) |
277 | for rows.Next() { | 277 | for rows.Next() { |
278 | var name, load string | 278 | var name, load string |
279 | rows.Scan(&name, &load) | 279 | rows.Scan(&name, &load) |
280 | 280 | ||
281 | p := Payload{} | 281 | p := Payload{} |
282 | err := json.Unmarshal([]byte(load), &p) | 282 | err := json.Unmarshal([]byte(load), &p) |
283 | if err != nil { | 283 | if err != nil { |
284 | logger.Log("webutility: couldn't init: '%s' metadata: %s:\n%s\n", name, err.Error(), load) | 284 | logger.Log("webutility: couldn't init: '%s' metadata: %s:\n%s\n", name, err.Error(), load) |
285 | } else { | 285 | } else { |
286 | metadata[name] = p | 286 | metadata[name] = p |
287 | } | 287 | } |
288 | } | 288 | } |
289 | 289 | ||
290 | return nil | 290 | return nil |
291 | } | 291 | } |
292 | 292 | ||
293 | // LoadMetadataFromFile expects file in format: | 293 | // LoadMetadataFromFile expects file in format: |
294 | // | 294 | // |
295 | // [ payload A identifier ] | 295 | // [ payload A identifier ] |
296 | // key1 : value1 | 296 | // key1 : value1 |
297 | // key2 : value2 | 297 | // key2 : value2 |
298 | // ... | 298 | // ... |
299 | // [ payload B identifier ] | 299 | // [ payload B identifier ] |
300 | // key1 : value1 | 300 | // key1 : value1 |
301 | // key2 : value2 | 301 | // key2 : value2 |
302 | // ... | 302 | // ... |
303 | // | 303 | // |
304 | // TODO(marko): Currently supports only one hardcoded language... | 304 | // TODO(marko): Currently supports only one hardcoded language... |
305 | func LoadMetadataFromFile(path string) error { | 305 | func LoadMetadataFromFile(path string) error { |
306 | lines, err := ReadFileLines(path) | 306 | lines, err := util.ReadFileLines(path) |
307 | if err != nil { | 307 | if err != nil { |
308 | return err | 308 | return err |
309 | } | 309 | } |
310 | 310 | ||
311 | metadata = make(map[string]Payload) | 311 | metadata = make(map[string]Payload) |
312 | 312 | ||
313 | var name string | 313 | var name string |
314 | for i, l := range lines { | 314 | for i, l := range lines { |
315 | // skip empty lines | 315 | // skip empty lines |
316 | if l = trimSpaces(l); len(l) == 0 { | 316 | if l = strings.TrimSpace(l); len(l) == 0 { |
317 | continue | 317 | continue |
318 | } | 318 | } |
319 | 319 | ||
320 | if isWrappedWith(l, "[", "]") { | 320 | if util.IsWrappedWith(l, "[", "]") { |
321 | name = strings.Trim(l, "[]") | 321 | name = strings.Trim(l, "[]") |
322 | p := Payload{} | 322 | p := Payload{} |
323 | p.addLang("sr", make(map[string]string)) | 323 | p.addLang("sr", make(map[string]string)) |
324 | metadata[name] = p | 324 | metadata[name] = p |
325 | continue | 325 | continue |
326 | } | 326 | } |
327 | 327 | ||
328 | if name == "" { | 328 | if name == "" { |
329 | return fmt.Errorf("webutility: LoadMetadataFromFile: error on line %d: [no header] [%s]", i+1, l) | 329 | return fmt.Errorf("webutility: LoadMetadataFromFile: error on line %d: [no header] [%s]", i+1, l) |
330 | } | 330 | } |
331 | 331 | ||
332 | parts := strings.Split(l, ":") | 332 | parts := strings.Split(l, ":") |
333 | if len(parts) != 2 { | 333 | if len(parts) != 2 { |
334 | return fmt.Errorf("webutility: LoadMetadataFromFile: error on line %d: [invalid format] [%s]", i+1, l) | 334 | return fmt.Errorf("webutility: LoadMetadataFromFile: error on line %d: [invalid format] [%s]", i+1, l) |
335 | } | 335 | } |
336 | 336 | ||
337 | k := trimSpaces(parts[0]) | 337 | k := strings.TrimSpace(parts[0]) |
338 | v := trimSpaces(parts[1]) | 338 | v := strings.TrimSpace(parts[1]) |
339 | if v != "-" { | 339 | if v != "-" { |
340 | metadata[name].Lang[0].FieldsLabels[k] = v | 340 | metadata[name].Lang[0].FieldsLabels[k] = v |
341 | } | 341 | } |
342 | } | 342 | } |
343 | 343 | ||
344 | return nil | 344 | return nil |
345 | } | 345 | } |
346 | 346 | ||
347 | func isWrappedWith(src, begin, end string) bool { | ||
348 | return strings.HasPrefix(src, begin) && strings.HasSuffix(src, end) | ||
349 | } | ||
350 | |||
351 | func trimSpaces(s string) string { | ||
352 | return strings.TrimSpace(s) | ||
353 | } | ||
354 | |||
355 | // ReadFileLines ... | ||
356 | // TODO(marko): Move to separate package | ||
357 | func ReadFileLines(path string) ([]string, error) { | ||
358 | f, err := os.Open(path) | ||
359 | if err != nil { | ||
360 | return nil, err | ||
361 | } | ||
362 | defer f.Close() | ||
363 | |||
364 | var s strings.Builder | ||
365 | |||
366 | if _, err = io.Copy(&s, f); err != nil { | ||
367 | return nil, err | ||
368 | } | ||
369 | |||
370 | lines := strings.Split(s.String(), "\n") | ||
371 | |||
372 | return lines, nil | ||
373 | } | ||
374 | |||
375 | func hotload(n int) { | 347 | func hotload(n int) { |
376 | entityScan := make(map[string]int64) | 348 | entityScan := make(map[string]int64) |
377 | firstCheck := true | 349 | firstCheck := true |
378 | for { | 350 | for { |
379 | time.Sleep(time.Duration(n) * time.Second) | 351 | time.Sleep(time.Duration(n) * time.Second) |
380 | rows, err := metadataDB.Query(`select | 352 | rows, err := metadataDB.Query(`select |
381 | ora_rowscn, | 353 | ora_rowscn, |
382 | entity_type | 354 | entity_type |
383 | from entities where projekat = ` + fmt.Sprintf("'%s'", activeProject)) | 355 | from entities where projekat = ` + fmt.Sprintf("'%s'", activeProject)) |
384 | if err != nil { | 356 | if err != nil { |
385 | logger.Log("webutility: hotload failed: %v\n", err) | 357 | logger.Log("webutility: hotload failed: %v\n", err) |
386 | time.Sleep(time.Duration(n) * time.Second) | 358 | time.Sleep(time.Duration(n) * time.Second) |
387 | continue | 359 | continue |
388 | } | 360 | } |
389 | 361 | ||
390 | var toRefresh []string | 362 | var toRefresh []string |
391 | for rows.Next() { | 363 | for rows.Next() { |
392 | var scanID int64 | 364 | var scanID int64 |
393 | var entity string | 365 | var entity string |
394 | rows.Scan(&scanID, &entity) | 366 | rows.Scan(&scanID, &entity) |
395 | oldID, ok := entityScan[entity] | 367 | oldID, ok := entityScan[entity] |
396 | if !ok || oldID != scanID { | 368 | if !ok || oldID != scanID { |
397 | entityScan[entity] = scanID | 369 | entityScan[entity] = scanID |
398 | toRefresh = append(toRefresh, entity) | 370 | toRefresh = append(toRefresh, entity) |
399 | } | 371 | } |
400 | } | 372 | } |
401 | rows.Close() | 373 | rows.Close() |
402 | 374 | ||
403 | if rows.Err() != nil { | 375 | if rows.Err() != nil { |
404 | logger.Log("webutility: hotload rset error: %v\n", rows.Err()) | 376 | logger.Log("webutility: hotload rset error: %v\n", rows.Err()) |
405 | time.Sleep(time.Duration(n) * time.Second) | 377 | time.Sleep(time.Duration(n) * time.Second) |
406 | continue | 378 | continue |
407 | } | 379 | } |
408 | 380 | ||
409 | if len(toRefresh) > 0 && !firstCheck { | 381 | if len(toRefresh) > 0 && !firstCheck { |
410 | mu.Lock() | 382 | mu.Lock() |
411 | refreshMetadata(toRefresh) | 383 | refreshMetadata(toRefresh) |
412 | mu.Unlock() | 384 | mu.Unlock() |
413 | } | 385 | } |
414 | if firstCheck { | 386 | if firstCheck { |
415 | firstCheck = false | 387 | firstCheck = false |
416 | } | 388 | } |
417 | } | 389 | } |
418 | } | 390 | } |
419 | 391 | ||
420 | func refreshMetadata(entities []string) { | 392 | func refreshMetadata(entities []string) { |
421 | for _, e := range entities { | 393 | for _, e := range entities { |
422 | fmt.Printf("refreshing %s\n", e) | 394 | fmt.Printf("refreshing %s\n", e) |
423 | rows, err := metadataDB.Query(`select | 395 | rows, err := metadataDB.Query(`select |
424 | metadata | 396 | metadata |
425 | from entities | 397 | from entities |
426 | where projekat = ` + fmt.Sprintf("'%s'", activeProject) + | 398 | where projekat = ` + fmt.Sprintf("'%s'", activeProject) + |
427 | ` and entity_type = ` + fmt.Sprintf("'%s'", e)) | 399 | ` and entity_type = ` + fmt.Sprintf("'%s'", e)) |
428 | 400 | ||
429 | if err != nil { | 401 | if err != nil { |
430 | logger.Log("webutility: refresh: prep: %v\n", err) | 402 | logger.Log("webutility: refresh: prep: %v\n", err) |
431 | rows.Close() | 403 | rows.Close() |
432 | continue | 404 | continue |
433 | } | 405 | } |
434 | 406 | ||
435 | for rows.Next() { | 407 | for rows.Next() { |
436 | var load string | 408 | var load string |
437 | rows.Scan(&load) | 409 | rows.Scan(&load) |
438 | p := Payload{} | 410 | p := Payload{} |
439 | err := json.Unmarshal([]byte(load), &p) | 411 | err := json.Unmarshal([]byte(load), &p) |
440 | if err != nil { | 412 | if err != nil { |
441 | logger.Log("webutility: couldn't refresh: '%s' metadata: %s\n%s\n", e, err.Error(), load) | 413 | logger.Log("webutility: couldn't refresh: '%s' metadata: %s\n%s\n", e, err.Error(), load) |
442 | } else { | 414 | } else { |
443 | metadata[e] = p | 415 | metadata[e] = p |
444 | } | 416 | } |
445 | } | 417 | } |
446 | rows.Close() | 418 | rows.Close() |
447 | } | 419 | } |
448 | } | 420 | } |
449 | 421 | ||
450 | /* | 422 | /* |
451 | func ModifyMetadataForEntity(entityType string, p *Payload) error { | 423 | func ModifyMetadataForEntity(entityType string, p *Payload) error { |
452 | md, err := json.Marshal(*p) | 424 | md, err := json.Marshal(*p) |
453 | if err != nil { | 425 | if err != nil { |
454 | return err | 426 | return err |
455 | } | 427 | } |
456 | 428 | ||
457 | mu.Lock() | 429 | mu.Lock() |
458 | defer mu.Unlock() | 430 | defer mu.Unlock() |
459 | _, err = metadataDB.PrepAndExe(`update entities set | 431 | _, err = metadataDB.PrepAndExe(`update entities set |
460 | metadata = :1 | 432 | metadata = :1 |
461 | where projekat = :2 | 433 | where projekat = :2 |
462 | and entity_type = :3`, | 434 | and entity_type = :3`, |
463 | string(md), | 435 | string(md), |
464 | activeProject, | 436 | activeProject, |
465 | entityType) | 437 | entityType) |
466 | if err != nil { | 438 | if err != nil { |
467 | return err | 439 | return err |
468 | } | 440 | } |
469 | return nil | 441 | return nil |
470 | } | 442 | } |
471 | 443 | ||
472 | func DeleteEntityModel(entityType string) error { | 444 | func DeleteEntityModel(entityType string) error { |
473 | _, err := metadataDB.PrepAndExe("delete from entities where entity_type = :1", entityType) | 445 | _, err := metadataDB.PrepAndExe("delete from entities where entity_type = :1", entityType) |
474 | if err == nil { | 446 | if err == nil { |
475 | mu.Lock() | 447 | mu.Lock() |
476 | delete(metadata, entityType) | 448 | delete(metadata, entityType) |
477 | mu.Unlock() | 449 | mu.Unlock() |
478 | } | 450 | } |
479 | return err | 451 | return err |
480 | } | 452 | } |
481 | */ | 453 | */ |
string_sanitisation.go
1 | package webutility | 1 | package webutility |
2 | 2 | ||
3 | import "strings" | 3 | import "git.to-net.rs/marko.tikvic/util" |
4 | 4 | ||
5 | const patern = "\"';&*<>=\\`:" | 5 | const patern = "\"';&*<>=\\`:" |
6 | 6 | ||
7 | // SanitiseString removes characters from s found in patern and returns new modified string. | 7 | // SanitiseString removes characters from s found in patern and returns new modified string. |
8 | func SanitiseString(s string) (safe string) { | 8 | func SanitiseString(s string) string { |
9 | for _, c := range patern { | 9 | return util.ReplaceAny(s, patern, "") |
10 | safe = strings.Replace(s, string(c), "", -1) | ||
11 | } | ||
12 | return safe | ||
13 | } | 10 | } |
14 | 11 |