Commit 9933169c81dffadf646a7825aa721e8e297f772f
1 parent
ff2508880c
Exists in
master
and in
1 other branch
localization support
Showing
3 changed files
with
121 additions
and
23 deletions
Show diff stats
http_utility.go
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 |
json_utility.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 | "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 |