Commit 9933169c81dffadf646a7825aa721e8e297f772f

Authored by Marko Tikvić
1 parent ff2508880c
Exists in master and in 1 other branch v2

localization support

1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "encoding/json" 4 "encoding/json"
5 "net/http" 5 "net/http"
6 ) 6 )
7 7
8 type webError struct {
9 Request string `json:"request"`
10 Error string `json:"error"`
11 }
12
13 // NotFoundHandler writes HTTP error 404 to w.
14 func NotFoundHandler(w http.ResponseWriter, req *http.Request) {
15 SetDefaultHeaders(w)
16 if req.Method == "OPTIONS" {
17 return
18 }
19 ErrorResponse(w, req, http.StatusNotFound, []HttpErrorDesc{
20 {"en", "Not found."},
21 {"rs", "Traženi resurs ne postoji."},
22 })
23 }
24
25 // SetDefaultHeaders set's default headers for an HTTP response.
26 func SetDefaultHeaders(w http.ResponseWriter) {
27 w.Header().Set("Access-Control-Allow-Origin", "*")
28 w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS")
29 w.Header().Set("Access-Control-Allow-Headers", `Accept, Content-Type,
30 Content-Length, Accept-Encoding, X-CSRF-Token, Authorization`)
31 w.Header().Set("Content-Type", "application/json; charset=utf-8")
32 }
33
34 // 2xx
35 func Success(w http.ResponseWriter, payload *Payload, code int) {
36 w.WriteHeader(code)
37 if payload != nil {
38 json.NewEncoder(w).Encode(*payload)
39 }
40 }
41
42 // 200
43 func OK(w http.ResponseWriter, payload *Payload) {
44 Success(w, payload, http.StatusOK)
45 }
46
47 // 201
48 func Created(w http.ResponseWriter, payload *Payload) {
49 Success(w, payload, http.StatusCreated)
50 }
51
52 // 4xx; 5xx
53 func Error(w http.ResponseWriter, r *http.Request, code int, err string) {
54 werr := webError{Error: err, Request: r.Method + " " + r.RequestURI}
55 w.WriteHeader(code)
56 json.NewEncoder(w).Encode(werr)
57 }
58
59 // 400
60 func BadRequest(w http.ResponseWriter, r *http.Request, err string) {
61 Error(w, r, http.StatusBadRequest, err)
62 }
63
64 // 404
65 func NotFound(w http.ResponseWriter, r *http.Request, err string) {
66 Error(w, r, http.StatusNotFound, err)
67 }
68
69 // 401
70 func Unauthorized(w http.ResponseWriter, r *http.Request, err string) {
71 Error(w, r, http.StatusUnauthorized, err)
72 }
73
74 // 403
75 func Forbidden(w http.ResponseWriter, r *http.Request, err string) {
76 Error(w, r, http.StatusForbidden, err)
77 }
78
79 // 403
80 func Conflict(w http.ResponseWriter, r *http.Request, err string) {
81 Error(w, r, http.StatusConflict, err)
82 }
83
84 // 500
85 func InternalServerError(w http.ResponseWriter, r *http.Request, err string) {
86 Error(w, r, http.StatusInternalServerError, err)
87 }
88
89 ///
90 /// Old API
91 ///
92
8 const ( 93 const (
9 templateHttpErr500_EN = "An internal server error has occurred." 94 templateHttpErr500_EN = "An internal server error has occurred."
10 templateHttpErr500_RS = "Došlo je do greške na serveru." 95 templateHttpErr500_RS = "Došlo je do greške na serveru."
11 templateHttpErr400_EN = "Bad request." 96 templateHttpErr400_EN = "Bad request."
12 templateHttpErr400_RS = "Neispravan zahtev." 97 templateHttpErr400_RS = "Neispravan zahtev."
13 templateHttpErr404_EN = "Resource not found." 98 templateHttpErr404_EN = "Resource not found."
14 templateHttpErr404_RS = "Objekat nije pronadjen." 99 templateHttpErr404_RS = "Resurs nije pronadjen."
15 templateHttpErr401_EN = "Unauthorized request." 100 templateHttpErr401_EN = "Unauthorized request."
16 templateHttpErr401_RS = "Neautorizovan zahtev." 101 templateHttpErr401_RS = "Neautorizovan zahtev."
17 ) 102 )
18 103
19 type httpError struct { 104 type httpError struct {
20 Error []HttpErrorDesc `json:"error"` 105 Error []HttpErrorDesc `json:"error"`
21 Request string `json:"request"` 106 Request string `json:"request"`
22 } 107 }
23 108
24 type HttpErrorDesc struct { 109 type HttpErrorDesc struct {
25 Lang string `json:"lang"` 110 Lang string `json:"lang"`
26 Desc string `json:"description"` 111 Desc string `json:"description"`
27 } 112 }
28 113
29 // DeliverPayload encodes payload as JSON to w. 114 // DeliverPayload encodes payload as JSON to w.
30 func DeliverPayload(w http.ResponseWriter, payload Payload) { 115 func DeliverPayload(w http.ResponseWriter, payload Payload) {
31 // Don't write status OK in the headers here. Leave it up for the caller. 116 // Don't write status OK in the headers here. Leave it up for the caller.
32 // E.g. Status 201. 117 // E.g. Status 201.
33 json.NewEncoder(w).Encode(payload) 118 json.NewEncoder(w).Encode(payload)
34 payload.Data = nil 119 payload.Data = nil
35 } 120 }
36 121
37 // ErrorResponse writes HTTP error to w. 122 // ErrorResponse writes HTTP error to w.
38 func ErrorResponse(w http.ResponseWriter, r *http.Request, code int, desc []HttpErrorDesc) { 123 func ErrorResponse(w http.ResponseWriter, r *http.Request, code int, desc []HttpErrorDesc) {
39 err := httpError{desc, r.Method + " " + r.RequestURI} 124 err := httpError{desc, r.Method + " " + r.RequestURI}
40 w.WriteHeader(code) 125 w.WriteHeader(code)
41 json.NewEncoder(w).Encode(err) 126 json.NewEncoder(w).Encode(err)
42 } 127 }
43 128
44 // NotFoundResponse writes HTTP error 404 to w. 129 // NotFoundResponse writes HTTP error 404 to w.
45 func NotFoundResponse(w http.ResponseWriter, req *http.Request) { 130 func NotFoundResponse(w http.ResponseWriter, req *http.Request) {
46 ErrorResponse(w, req, http.StatusNotFound, []HttpErrorDesc{ 131 ErrorResponse(w, req, http.StatusNotFound, []HttpErrorDesc{
47 {"en", templateHttpErr404_EN}, 132 {"en", templateHttpErr404_EN},
48 {"rs", templateHttpErr404_RS}, 133 {"rs", templateHttpErr404_RS},
49 }) 134 })
50 } 135 }
51 136
52 // BadRequestResponse writes HTTP error 400 to w. 137 // BadRequestResponse writes HTTP error 400 to w.
53 func BadRequestResponse(w http.ResponseWriter, req *http.Request) { 138 func BadRequestResponse(w http.ResponseWriter, req *http.Request) {
54 ErrorResponse(w, req, http.StatusBadRequest, []HttpErrorDesc{ 139 ErrorResponse(w, req, http.StatusBadRequest, []HttpErrorDesc{
55 {"en", templateHttpErr400_EN}, 140 {"en", templateHttpErr400_EN},
56 {"rs", templateHttpErr400_RS}, 141 {"rs", templateHttpErr400_RS},
57 }) 142 })
58 } 143 }
59 144
60 // InternalSeverErrorResponse writes HTTP error 500 to w. 145 // InternalSeverErrorResponse writes HTTP error 500 to w.
61 func InternalServerErrorResponse(w http.ResponseWriter, req *http.Request) { 146 func InternalServerErrorResponse(w http.ResponseWriter, req *http.Request) {
62 ErrorResponse(w, req, http.StatusInternalServerError, []HttpErrorDesc{ 147 ErrorResponse(w, req, http.StatusInternalServerError, []HttpErrorDesc{
63 {"en", templateHttpErr500_EN}, 148 {"en", templateHttpErr500_EN},
64 {"rs", templateHttpErr500_RS}, 149 {"rs", templateHttpErr500_RS},
65 }) 150 })
66 } 151 }
67 152
68 // UnauthorizedError writes HTTP error 401 to w. 153 // UnauthorizedError writes HTTP error 401 to w.
69 func UnauthorizedResponse(w http.ResponseWriter, req *http.Request) { 154 func UnauthorizedResponse(w http.ResponseWriter, req *http.Request) {
70 w.Header().Set("WWW-Authenticate", "Bearer") 155 w.Header().Set("WWW-Authenticate", "Bearer")
71 ErrorResponse(w, req, http.StatusUnauthorized, []HttpErrorDesc{ 156 ErrorResponse(w, req, http.StatusUnauthorized, []HttpErrorDesc{
72 {"en", templateHttpErr401_EN}, 157 {"en", templateHttpErr401_EN},
73 {"rs", templateHttpErr401_RS}, 158 {"rs", templateHttpErr401_RS},
74 }) 159 })
75 } 160 }
76
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 "fmt" 6 "fmt"
7 "io" 7 "io"
8 "net/http" 8 "net/http"
9 "sync" 9 "sync"
10 "time" 10 "time"
11 11
12 "git.to-net.rs/marko.tikvic/gologger" 12 "git.to-net.rs/marko.tikvic/gologger"
13 ) 13 )
14 14
15 var ( 15 var (
16 mu = &sync.Mutex{} 16 mu = &sync.Mutex{}
17 metadata = make(map[string]Payload) 17 metadata = make(map[string]Payload)
18 updateQue = make(map[string][]byte) 18 updateQue = make(map[string][]byte)
19 19
20 metadataDB *sql.DB 20 metadataDB *sql.DB
21 activeProject string 21 activeProject string
22 22
23 inited bool 23 inited bool
24 ) 24 )
25 25
26 var logger *gologger.Logger 26 var logger *gologger.Logger
27 27
28 func init() { 28 func init() {
29 var err error 29 var err error
30 logger, err = gologger.New("metadata", gologger.MaxLogSize100KB) 30 logger, err = gologger.New("metadata", gologger.MaxLogSize100KB)
31 if err != nil { 31 if err != nil {
32 fmt.Printf("webutility: %s\n", err.Error()) 32 fmt.Printf("webutility: %s\n", err.Error())
33 } 33 }
34 } 34 }
35 35
36 type LangMap map[string]map[string]string 36 type LangMap map[string]map[string]string
37 37
38 type Field struct { 38 type Field struct {
39 Parameter string `json:"param"` 39 Parameter string `json:"param"`
40 Type string `json:"type"` 40 Type string `json:"type"`
41 Visible bool `json:"visible"` 41 Visible bool `json:"visible"`
42 Editable bool `json:"editable"` 42 Editable bool `json:"editable"`
43 } 43 }
44 44
45 type CorrelationField struct { 45 type CorrelationField struct {
46 Result string `json:"result"` 46 Result string `json:"result"`
47 Elements []string `json:"elements"` 47 Elements []string `json:"elements"`
48 Type string `json:"type"` 48 Type string `json:"type"`
49 } 49 }
50 50
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 type Payload struct { 56 type Payload struct {
57 Method string `json:"method"` 57 Method string `json:"method"`
58 Params map[string]string `json:"params"` 58 Params map[string]string `json:"params"`
59 Lang []Translation `json:"lang"` 59 Lang []Translation `json:"lang"`
60 Fields []Field `json:"fields"` 60 Fields []Field `json:"fields"`
61 Correlations []CorrelationField `json:"correlationFields"` 61 Correlations []CorrelationField `json:"correlationFields"`
62 IdField string `json:"idField"` 62 IdField string `json:"idField"`
63 63
64 // Data holds JSON payload. It can't be used for itteration. 64 // Data holds JSON payload.
65 // It can't be used for itteration.
65 Data interface{} `json:"data"` 66 Data interface{} `json:"data"`
66 } 67 }
67 68
68 // NewPayload returs a payload sceleton for entity described with etype. 69 // NewPayload returs a payload sceleton for entity described with etype.
69 func NewPayload(r *http.Request, etype string) Payload { 70 func NewPayload(r *http.Request, etype string) Payload {
70 pload := metadata[etype] 71 pload := metadata[etype]
71 pload.Method = r.Method + " " + r.RequestURI 72 pload.Method = r.Method + " " + r.RequestURI
72 return pload 73 return pload
73 } 74 }
74 75
75 // DecodeJSON decodes JSON data from r to v. 76 // DecodeJSON decodes JSON data from r to v.
76 // Returns an error if it fails. 77 // Returns an error if it fails.
77 func DecodeJSON(r io.Reader, v interface{}) error { 78 func DecodeJSON(r io.Reader, v interface{}) error {
78 return json.NewDecoder(r).Decode(v) 79 return json.NewDecoder(r).Decode(v)
79 } 80 }
80 81
81 // LoadPayloadsdetaData loads all payloads' information into 'metadata' variable. 82 // LoadPayloadsdetaData loads all payloads' information into 'metadata' variable.
82 func LoadPayloadsMetadata(db *sql.DB, project string) error { 83 func LoadPayloadsMetadata(db *sql.DB, project string) error {
83 metadataDB = db 84 metadataDB = db
84 activeProject = project 85 activeProject = project
85 86
86 mu.Lock() 87 mu.Lock()
87 defer mu.Unlock() 88 defer mu.Unlock()
88 err := initMetadata(project) 89 err := initMetadata(project)
89 if err != nil { 90 if err != nil {
90 return err 91 return err
91 } 92 }
92 inited = true 93 inited = true
93 94
94 return nil 95 return nil
95 } 96 }
96 97
97 func EnableHotloading(interval int) { 98 func EnableHotloading(interval int) {
98 if interval > 0 { 99 if interval > 0 {
99 go hotload(interval) 100 go hotload(interval)
100 } 101 }
101 } 102 }
102 103
103 func GetMetadataForAllEntities() map[string]Payload { 104 func GetMetadataForAllEntities() map[string]Payload {
104 return metadata 105 return metadata
105 } 106 }
106 107
107 func GetMetadataForEntity(t string) (Payload, bool) { 108 func GetMetadataForEntity(t string) (Payload, bool) {
108 p, ok := metadata[t] 109 p, ok := metadata[t]
109 return p, ok 110 return p, ok
110 } 111 }
111 112
112 func QueEntityModelUpdate(entityType string, v interface{}) { 113 func QueEntityModelUpdate(entityType string, v interface{}) {
113 updateQue[entityType], _ = json.Marshal(v) 114 updateQue[entityType], _ = json.Marshal(v)
114 } 115 }
115 116
116 func initMetadata(project string) error { 117 func initMetadata(project string) error {
117 rows, err := metadataDB.Query(`select 118 rows, err := metadataDB.Query(`select
118 entity_type, 119 entity_type,
119 metadata 120 metadata
120 from entities 121 from entities
121 where projekat = ` + fmt.Sprintf("'%s'", project)) 122 where projekat = ` + fmt.Sprintf("'%s'", project))
122 if err != nil { 123 if err != nil {
123 return err 124 return err
124 } 125 }
125 defer rows.Close() 126 defer rows.Close()
126 127
127 count := 0 128 count := 0
128 success := 0 129 success := 0
129 if len(metadata) > 0 { 130 if len(metadata) > 0 {
130 metadata = nil 131 metadata = nil
131 } 132 }
132 metadata = make(map[string]Payload) 133 metadata = make(map[string]Payload)
133 for rows.Next() { 134 for rows.Next() {
134 var name, load string 135 var name, load string
135 rows.Scan(&name, &load) 136 rows.Scan(&name, &load)
136 137
137 p := Payload{} 138 p := Payload{}
138 err := json.Unmarshal([]byte(load), &p) 139 err := json.Unmarshal([]byte(load), &p)
139 if err != nil { 140 if err != nil {
140 logger.Log("couldn't init: '%s' metadata: %s\n%s\n", name, err.Error(), load) 141 logger.Log("couldn't init: '%s' metadata: %s\n%s\n", name, err.Error(), load)
141 } else { 142 } else {
142 success++ 143 success++
143 metadata[name] = p 144 metadata[name] = p
144 } 145 }
145 count++ 146 count++
146 } 147 }
147 perc := float32(success/count) * 100.0 148 perc := float32(success/count) * 100.0
148 logger.Log("loaded %d/%d (%.1f%%) entities\n", success, count, perc) 149 logger.Log("loaded %d/%d (%.1f%%) entities\n", success, count, perc)
149 150
150 return nil 151 return nil
151 } 152 }
152 153
153 func hotload(n int) { 154 func hotload(n int) {
154 entityScan := make(map[string]int64) 155 entityScan := make(map[string]int64)
155 firstCheck := true 156 firstCheck := true
156 for { 157 for {
157 time.Sleep(time.Duration(n) * time.Second) 158 time.Sleep(time.Duration(n) * time.Second)
158 rows, err := metadataDB.Query(`select 159 rows, err := metadataDB.Query(`select
159 ora_rowscn, 160 ora_rowscn,
160 entity_type 161 entity_type
161 from entities where projekat = ` + fmt.Sprintf("'%s'", activeProject)) 162 from entities where projekat = ` + fmt.Sprintf("'%s'", activeProject))
162 if err != nil { 163 if err != nil {
163 logger.Log("hotload failed: %v\n", err) 164 logger.Log("hotload failed: %v\n", err)
164 time.Sleep(time.Duration(n) * time.Second) 165 time.Sleep(time.Duration(n) * time.Second)
165 continue 166 continue
166 } 167 }
167 168
168 var toRefresh []string 169 var toRefresh []string
169 for rows.Next() { 170 for rows.Next() {
170 var scanID int64 171 var scanID int64
171 var entity string 172 var entity string
172 rows.Scan(&scanID, &entity) 173 rows.Scan(&scanID, &entity)
173 oldID, ok := entityScan[entity] 174 oldID, ok := entityScan[entity]
174 if !ok || oldID != scanID { 175 if !ok || oldID != scanID {
175 entityScan[entity] = scanID 176 entityScan[entity] = scanID
176 toRefresh = append(toRefresh, entity) 177 toRefresh = append(toRefresh, entity)
177 } 178 }
178 } 179 }
179 rows.Close() 180 rows.Close()
180 181
181 if rows.Err() != nil { 182 if rows.Err() != nil {
182 logger.Log("hotload rset error: %v\n", rows.Err()) 183 logger.Log("hotload rset error: %v\n", rows.Err())
183 time.Sleep(time.Duration(n) * time.Second) 184 time.Sleep(time.Duration(n) * time.Second)
184 continue 185 continue
185 } 186 }
186 187
187 if len(toRefresh) > 0 && !firstCheck { 188 if len(toRefresh) > 0 && !firstCheck {
188 mu.Lock() 189 mu.Lock()
189 refreshMetadata(toRefresh) 190 refreshMetadata(toRefresh)
190 mu.Unlock() 191 mu.Unlock()
191 } 192 }
192 if firstCheck { 193 if firstCheck {
193 firstCheck = false 194 firstCheck = false
194 } 195 }
195 } 196 }
196 } 197 }
197 198
198 func refreshMetadata(entities []string) { 199 func refreshMetadata(entities []string) {
199 for _, e := range entities { 200 for _, e := range entities {
200 fmt.Printf("refreshing %s\n", e) 201 fmt.Printf("refreshing %s\n", e)
201 rows, err := metadataDB.Query(`select 202 rows, err := metadataDB.Query(`select
202 metadata 203 metadata
203 from entities 204 from entities
204 where projekat = ` + fmt.Sprintf("'%s'", activeProject) + 205 where projekat = ` + fmt.Sprintf("'%s'", activeProject) +
205 ` and entity_type = ` + fmt.Sprintf("'%s'", e)) 206 ` and entity_type = ` + fmt.Sprintf("'%s'", e))
206 207
207 if err != nil { 208 if err != nil {
208 logger.Log("webutility: refresh: prep: %v\n", err) 209 logger.Log("webutility: refresh: prep: %v\n", err)
209 rows.Close() 210 rows.Close()
210 continue 211 continue
211 } 212 }
212 213
213 for rows.Next() { 214 for rows.Next() {
214 var load string 215 var load string
215 rows.Scan(&load) 216 rows.Scan(&load)
216 p := Payload{} 217 p := Payload{}
217 err := json.Unmarshal([]byte(load), &p) 218 err := json.Unmarshal([]byte(load), &p)
218 if err != nil { 219 if err != nil {
219 logger.Log("couldn't refresh: '%s' metadata: %s\n%s\n", e, err.Error(), load) 220 logger.Log("couldn't refresh: '%s' metadata: %s\n%s\n", e, err.Error(), load)
220 } else { 221 } else {
221 metadata[e] = p 222 metadata[e] = p
222 } 223 }
223 } 224 }
224 rows.Close() 225 rows.Close()
225 } 226 }
226 } 227 }
227 228
228 /* 229 /*
229 func UpdateEntityModels(command string) (total, upd, add int, err error) { 230 func UpdateEntityModels(command string) (total, upd, add int, err error) {
230 if command != "force" && command != "missing" { 231 if command != "force" && command != "missing" {
231 return total, 0, 0, errors.New("uknown command: " + command) 232 return total, 0, 0, errors.New("uknown command: " + command)
232 } 233 }
233 234
234 if !inited { 235 if !inited {
235 return 0, 0, 0, errors.New("webutil: metadata not initialized but update was tried.") 236 return 0, 0, 0, errors.New("webutil: metadata not initialized but update was tried.")
236 } 237 }
237 238
238 total = len(updateQue) 239 total = len(updateQue)
239 240
240 forUpdate := make([]string, 0) 241 forUpdate := make([]string, 0)
241 forAdd := make([]string, 0) 242 forAdd := make([]string, 0)
242 243
243 for k, _ := range updateQue { 244 for k, _ := range updateQue {
244 if _, exists := metadata[k]; exists { 245 if _, exists := metadata[k]; exists {
245 if command == "force" { 246 if command == "force" {
246 forUpdate = append(forUpdate, k) 247 forUpdate = append(forUpdate, k)
247 } 248 }
248 } else { 249 } else {
249 forAdd = append(forAdd, k) 250 forAdd = append(forAdd, k)
250 } 251 }
251 } 252 }
252 253
253 for _, k := range forUpdate { 254 for _, k := range forUpdate {
254 _, err := metadataDB.PrepAndExe(`update entities set 255 _, err := metadataDB.PrepAndExe(`update entities set
255 entity_model = :1 256 entity_model = :1
256 where entity_type = :2`, 257 where entity_type = :2`,
257 string(updateQue[k]), 258 string(updateQue[k]),
258 k) 259 k)
259 260
260 if err != nil { 261 if err != nil {
261 logger.Log("webutility: update metadata: prep and exe: %v\n", err) 262 logger.Log("webutility: update metadata: prep and exe: %v\n", err)
262 continue 263 continue
263 } 264 }
264 upd++ 265 upd++
265 logger.Log("webutility: updated %s payload model\n", k) 266 logger.Log("webutility: updated %s payload model\n", k)
266 } 267 }
267 268
268 blankPayload, _ := json.Marshal(Payload{}) 269 blankPayload, _ := json.Marshal(Payload{})
269 for _, k := range forAdd { 270 for _, k := range forAdd {
270 _, err := metadataDB.PrepAndExe(`insert into entities 271 _, err := metadataDB.PrepAndExe(`insert into entities
271 (projekat, metadata, entity_type, entity_model) 272 (projekat, metadata, entity_type, entity_model)
272 values(:1, :2, :3, :4)`, 273 values(:1, :2, :3, :4)`,
273 activeProject, 274 activeProject,
274 string(blankPayload), 275 string(blankPayload),
275 k, 276 k,
276 string(updateQue[k])) 277 string(updateQue[k]))
277 278
278 if err != nil { 279 if err != nil {
279 logger.Log("webutility: add metadata: prep and exe: %v\n", err) 280 logger.Log("webutility: add metadata: prep and exe: %v\n", err)
280 continue 281 continue
281 } 282 }
282 metadata[k] = Payload{} 283 metadata[k] = Payload{}
283 add++ 284 add++
284 logger.Log("webutility: added %s to the payload models\n", k) 285 logger.Log("webutility: added %s to the payload models\n", k)
285 286
286 } 287 }
287 288
288 return total, upd, add, nil 289 return total, upd, add, nil
289 } 290 }
290 291
291 func ModifyMetadataForEntity(entityType string, p *Payload) error { 292 func ModifyMetadataForEntity(entityType string, p *Payload) error {
292 md, err := json.Marshal(*p) 293 md, err := json.Marshal(*p)
293 if err != nil { 294 if err != nil {
294 return err 295 return err
295 } 296 }
296 297
297 mu.Lock() 298 mu.Lock()
298 defer mu.Unlock() 299 defer mu.Unlock()
299 _, err = metadataDB.PrepAndExe(`update entities set 300 _, err = metadataDB.PrepAndExe(`update entities set
300 metadata = :1 301 metadata = :1
301 where projekat = :2 302 where projekat = :2
302 and entity_type = :3`, 303 and entity_type = :3`,
303 string(md), 304 string(md),
304 activeProject, 305 activeProject,
305 entityType) 306 entityType)
306 if err != nil { 307 if err != nil {
307 return err 308 return err
308 } 309 }
309 return nil 310 return nil
310 } 311 }
311 312
312 func DeleteEntityModel(entityType string) error { 313 func DeleteEntityModel(entityType string) error {
313 _, err := metadataDB.PrepAndExe("delete from entities where entity_type = :1", entityType) 314 _, err := metadataDB.PrepAndExe("delete from entities where entity_type = :1", entityType)
314 if err == nil { 315 if err == nil {
315 mu.Lock() 316 mu.Lock()
316 delete(metadata, entityType) 317 delete(metadata, entityType)
317 mu.Unlock() 318 mu.Unlock()
318 } 319 }
319 return err 320 return err
320 } 321 }
321 */ 322 */
322 323
locale_utility.go
File was created 1 package webutility
2
3 import (
4 "encoding/json"
5 "io/ioutil"
6 )
7
8 var locales = map[string]map[string]string{}
9
10 func LoadLocale(loc, filePath string) error {
11 file, err := ioutil.ReadFile(filePath)
12 if err != nil {
13 return err
14 }
15
16 var data interface{}
17 err = json.Unmarshal(file, &data)
18 if err != nil {
19 return err
20 }
21
22 l := map[string]string{}
23 for k, v := range data.(map[string]interface{}) {
24 l[k] = v.(string)
25 }
26 locales[loc] = l
27
28 return nil
29 }
30
31 func Translate(loc, key string) string {
32 return locales[loc][key]
33 }
34