Commit 1b7dfab733de136a9d3547b16f7373d8f8252803

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

Payload changed to inteface{}

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