Commit ad8e9dd2af2320b920444b98a0d71d8c0a565734

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

added middleware and functions to support getting default values from nil interfaces

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