Commit 3f8e3c437433052f24b067ed433df8e83b98ec12

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

minor changes

Showing 3 changed files with 197 additions and 134 deletions   Show diff stats
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "crypto/rand" 4 "crypto/rand"
5 "crypto/sha256" 5 "crypto/sha256"
6 "encoding/hex" 6 "encoding/hex"
7 "errors" 7 "errors"
8 "net/http" 8 "net/http"
9 "strings" 9 "strings"
10 "time" 10 "time"
11 11
12 "github.com/dgrijalva/jwt-go" 12 "github.com/dgrijalva/jwt-go"
13 ) 13 )
14 14
15 var appName = "webutility" 15 var appName = "webutility"
16 var secret = "webutility" 16 var secret = "webutility"
17 17
18 type Role struct { 18 type Role struct {
19 Name string `json:"name"` 19 Name string `json:"name"`
20 ID int64 `json:"id"` 20 ID int64 `json:"id"`
21 } 21 }
22 22
23 // TokenClaims are JWT token claims. 23 // TokenClaims are JWT token claims.
24 type TokenClaims struct { 24 type TokenClaims struct {
25 // extending a struct 25 // extending a struct
26 jwt.StandardClaims 26 jwt.StandardClaims
27 27
28 // custom claims 28 // custom claims
29 Token string `json:"access_token"` 29 Token string `json:"access_token"`
30 TokenType string `json:"token_type"` 30 TokenType string `json:"token_type"`
31 Username string `json:"username"` 31 Username string `json:"username"`
32 Role string `json:"role"` 32 Role string `json:"role"`
33 RoleID int64 `json:"role_id"` 33 RoleID int64 `json:"role_id"`
34 ExpiresIn int64 `json:"expires_in"` 34 ExpiresIn int64 `json:"expires_in"`
35 } 35 }
36 36
37 func InitJWT(appName, secret string) { 37 func InitJWT(appName, secret string) {
38 appName = appName 38 appName = appName
39 secret = secret 39 secret = secret
40 } 40 }
41 41
42 // ValidateCredentials hashes pass and salt and returns comparison result with resultHash 42 // ValidateCredentials hashes pass and salt and returns comparison result with resultHash
43 func ValidateCredentials(pass, salt, resultHash string) (bool, error) { 43 func ValidateCredentials(pass, salt, resultHash string) (bool, error) {
44 hash, _, err := CreateHash(pass, salt) 44 hash, _, err := CreateHash(pass, salt)
45 if err != nil { 45 if err != nil {
46 return false, err 46 return false, err
47 } 47 }
48 res := hash == resultHash 48 res := hash == resultHash
49 return res, nil 49 return res, nil
50 } 50 }
51 51
52 // CreateHash hashes str using SHA256. 52 // CreateHash hashes str using SHA256.
53 // If the presalt parameter is not provided CreateHash will generate new salt string. 53 // If the presalt parameter is not provided CreateHash will generate new salt string.
54 // Returns hash and salt strings or an error if it fails. 54 // Returns hash and salt strings or an error if it fails.
55 func CreateHash(str, presalt string) (hash, salt string, err error) { 55 func CreateHash(str, presalt string) (hash, salt string, err error) {
56 // chech if message is presalted 56 // chech if message is presalted
57 if presalt == "" { 57 if presalt == "" {
58 salt, err = randomSalt() 58 salt, err = randomSalt()
59 if err != nil { 59 if err != nil {
60 return "", "", err 60 return "", "", err
61 } 61 }
62 } else { 62 } else {
63 salt = presalt 63 salt = presalt
64 } 64 }
65 65
66 // convert strings to raw byte slices 66 // convert strings to raw byte slices
67 rawstr := []byte(str) 67 rawstr := []byte(str)
68 rawsalt, err := hex.DecodeString(salt) 68 rawsalt, err := hex.DecodeString(salt)
69 if err != nil { 69 if err != nil {
70 return "", "", err 70 return "", "", err
71 } 71 }
72 72
73 rawdata := make([]byte, len(rawstr)+len(rawsalt)) 73 rawdata := make([]byte, len(rawstr)+len(rawsalt))
74 rawdata = append(rawdata, rawstr...) 74 rawdata = append(rawdata, rawstr...)
75 rawdata = append(rawdata, rawsalt...) 75 rawdata = append(rawdata, rawsalt...)
76 76
77 // hash message + salt 77 // hash message + salt
78 hasher := sha256.New() 78 hasher := sha256.New()
79 hasher.Write(rawdata) 79 hasher.Write(rawdata)
80 rawhash := hasher.Sum(nil) 80 rawhash := hasher.Sum(nil)
81 81
82 hash = hex.EncodeToString(rawhash) 82 hash = hex.EncodeToString(rawhash)
83 return hash, salt, nil 83 return hash, salt, nil
84 } 84 }
85 85
86 // CreateAuthToken returns JWT token with encoded username, role, expiration date and issuer claims. 86 // CreateAuthToken returns JWT token with encoded username, role, expiration date and issuer claims.
87 // It returns an error if it fails. 87 // It returns an error if it fails.
88 func CreateAuthToken(username string, role Role) (TokenClaims, error) { 88 func CreateAuthToken(username string, role Role) (TokenClaims, error) {
89 t0 := (time.Now()).Unix() 89 t0 := (time.Now()).Unix()
90 t1 := (time.Now().Add(time.Hour * 24 * 7)).Unix() 90 t1 := (time.Now().Add(time.Hour * 24 * 7)).Unix()
91 claims := TokenClaims{ 91 claims := TokenClaims{
92 TokenType: "Bearer", 92 TokenType: "Bearer",
93 Username: username, 93 Username: username,
94 Role: role.Name, 94 Role: role.Name,
95 RoleID: role.ID, 95 RoleID: role.ID,
96 ExpiresIn: t1 - t0, 96 ExpiresIn: t1 - t0,
97 } 97 }
98 // initialize jwt.StandardClaims fields (anonymous struct) 98 // initialize jwt.StandardClaims fields (anonymous struct)
99 claims.IssuedAt = t0 99 claims.IssuedAt = t0
100 claims.ExpiresAt = t1 100 claims.ExpiresAt = t1
101 claims.Issuer = appName 101 claims.Issuer = appName
102 102
103 jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) 103 jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
104 token, err := jwtToken.SignedString([]byte(secret)) 104 token, err := jwtToken.SignedString([]byte(secret))
105 if err != nil { 105 if err != nil {
106 return TokenClaims{}, err 106 return TokenClaims{}, err
107 } 107 }
108 claims.Token = token 108 claims.Token = token
109 return claims, nil 109 return claims, nil
110 } 110 }
111 111
112 // RefreshAuthToken returns new JWT token with same claims contained in tok but with prolonged expiration date. 112 // RefreshAuthToken returns new JWT token with same claims contained in tok but with prolonged expiration date.
113 // It returns an error if it fails. 113 // It returns an error if it fails.
114 func RefreshAuthToken(tok string) (TokenClaims, error) { 114 func RefreshAuthToken(tok string) (TokenClaims, error) {
115 token, err := jwt.ParseWithClaims(tok, &TokenClaims{}, secretFunc) 115 token, err := jwt.ParseWithClaims(tok, &TokenClaims{}, secretFunc)
116 if err != nil { 116 if err != nil {
117 if validation, ok := err.(*jwt.ValidationError); ok { 117 if validation, ok := err.(*jwt.ValidationError); ok {
118 // don't return error if token is expired 118 // don't return error if token is expired
119 // just extend it 119 // just extend it
120 if !(validation.Errors&jwt.ValidationErrorExpired != 0) { 120 if !(validation.Errors&jwt.ValidationErrorExpired != 0) {
121 return TokenClaims{}, err 121 return TokenClaims{}, err
122 } 122 }
123 } else { 123 } else {
124 return TokenClaims{}, err 124 return TokenClaims{}, err
125 } 125 }
126 } 126 }
127 127
128 // type assertion 128 // type assertion
129 claims, ok := token.Claims.(*TokenClaims) 129 claims, ok := token.Claims.(*TokenClaims)
130 if !ok { 130 if !ok {
131 return TokenClaims{}, errors.New("token is not valid") 131 return TokenClaims{}, errors.New("token is not valid")
132 } 132 }
133 133
134 // extend token expiration date 134 // extend token expiration date
135 return CreateAuthToken(claims.Username, Role{claims.Role, claims.RoleID}) 135 return CreateAuthToken(claims.Username, Role{claims.Role, claims.RoleID})
136 } 136 }
137 137
138 // AuthCheck returns JWT claims and boolean result of a check if req contains any role from roles. 138 func AuthCheck(req *http.Request, roles string) (*TokenClaims, error) {
139 // It checks if role extracted from reqest's Authorization header (JWT claims) matches any of
140 // provided comma-separated roles in roles. If roles is empty string check is skipped,
141 // otherwise role is extracted from token claims and compared against roles.
142 // If roles is "*" the check is automatically validated.
143 func AuthCheck(req *http.Request, roles string) (*TokenClaims, bool) {
144 if roles == "" {
145 return nil, true
146 }
147
148 // validate token and check expiration date 139 // validate token and check expiration date
149 claims, err := GetTokenClaims(req) 140 claims, err := GetTokenClaims(req)
150 if err != nil { 141 if err != nil {
151 return claims, false 142 return claims, err
143 }
144
145 if roles == "" {
146 return claims, nil
152 } 147 }
148
153 // check if token has expired 149 // check if token has expired
154 if claims.ExpiresAt < (time.Now()).Unix() { 150 if claims.ExpiresAt < (time.Now()).Unix() {
155 return claims, false 151 return claims, errors.New("token has expired")
156 } 152 }
157 153
158 if roles == "*" { 154 if roles == "*" {
159 return claims, true 155 return claims, nil
160 } 156 }
161 157
162 parts := strings.Split(roles, ",") 158 parts := strings.Split(roles, ",")
163 for i, _ := range parts { 159 for i, _ := range parts {
164 r := strings.Trim(parts[i], " ") 160 r := strings.Trim(parts[i], " ")
165 if claims.Role == r { 161 if claims.Role == r {
166 return claims, true 162 return claims, nil
167 } 163 }
168 } 164 }
169 165
170 return claims, false 166 return claims, nil
171 } 167 }
172 168
173 // GetTokenClaims extracts JWT claims from Authorization header of req. 169 // GetTokenClaims extracts JWT claims from Authorization header of req.
174 // Returns token claims or an error. 170 // Returns token claims or an error.
175 func GetTokenClaims(req *http.Request) (*TokenClaims, error) { 171 func GetTokenClaims(req *http.Request) (*TokenClaims, error) {
176 // check for and strip 'Bearer' prefix 172 // check for and strip 'Bearer' prefix
177 var tokstr string 173 var tokstr string
178 authHead := req.Header.Get("Authorization") 174 authHead := req.Header.Get("Authorization")
179 if ok := strings.HasPrefix(authHead, "Bearer "); ok { 175 if ok := strings.HasPrefix(authHead, "Bearer "); ok {
180 tokstr = strings.TrimPrefix(authHead, "Bearer ") 176 tokstr = strings.TrimPrefix(authHead, "Bearer ")
181 } else { 177 } else {
182 return &TokenClaims{}, errors.New("authorization header in incomplete") 178 return &TokenClaims{}, errors.New("authorization header in incomplete")
183 } 179 }
184 180
185 token, err := jwt.ParseWithClaims(tokstr, &TokenClaims{}, secretFunc) 181 token, err := jwt.ParseWithClaims(tokstr, &TokenClaims{}, secretFunc)
186 if err != nil { 182 if err != nil {
187 return &TokenClaims{}, err 183 return &TokenClaims{}, err
188 } 184 }
189 185
190 // type assertion 186 // type assertion
191 claims, ok := token.Claims.(*TokenClaims) 187 claims, ok := token.Claims.(*TokenClaims)
192 if !ok || !token.Valid { 188 if !ok || !token.Valid {
193 return &TokenClaims{}, errors.New("token is not valid") 189 return &TokenClaims{}, errors.New("token is not valid")
194 } 190 }
195 191
196 return claims, nil 192 return claims, nil
197 } 193 }
198 194
199 // randomSalt returns a string of 32 random characters. 195 // randomSalt returns a string of 32 random characters.
200 const saltSize = 32 196 const saltSize = 32
201 197
202 func randomSalt() (s string, err error) { 198 func randomSalt() (s string, err error) {
203 rawsalt := make([]byte, saltSize) 199 rawsalt := make([]byte, saltSize)
204 200
205 _, err = rand.Read(rawsalt) 201 _, err = rand.Read(rawsalt)
206 if err != nil { 202 if err != nil {
207 return "", err 203 return "", err
208 } 204 }
209 205
210 s = hex.EncodeToString(rawsalt) 206 s = hex.EncodeToString(rawsalt)
211 return s, nil 207 return s, nil
212 } 208 }
213 209
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "database/sql" 4 "database/sql"
5 "fmt" 5 "fmt"
6 ) 6 )
7 7
8 type ListOptions struct { 8 type ListOptions struct {
9 GlobalFilter bool `json:"globalFilter"` 9 GlobalFilter bool `json:"globalFilter"`
10 LocalFilters bool `json:"localFilters"` 10 LocalFilters bool `json:"localFilters"`
11 RemoteFilters bool `json:"remoteFilters"` 11 RemoteFilters bool `json:"remoteFilters"`
12 Pagination bool `json:"pagination"` 12 Pagination bool `json:"pagination"`
13 PageSize uint32 `json:"pageSize"` 13 PageSize uint32 `json:"pageSize"`
14 Pivot bool `json:"pivot"` 14 Pivot bool `json:"pivot"`
15 Detail bool `json:"detail"` 15 Detail bool `json:"detail"`
16 Total bool `json:"total"` 16 Total bool `json:"total"`
17 } 17 }
18 18
19 type ListFilter struct { 19 type ListFilter struct {
20 Position uint32 `json:"-"` 20 Position uint32 `json:"-"`
21 ObjectType string `json:"-"` 21 ObjectType string `json:"-"`
22 FiltersField string `json:"filtersField"` 22 FiltersField string `json:"filtersField"`
23 DefaultValues string `json:"defaultValues"` 23 DefaultValues string `json:"defaultValues"`
24 FiltersType string `json:"filtersType"` 24 FiltersType string `json:"filtersType"`
25 FiltersLabel string `json:"filtersLabel"` 25 FiltersLabel string `json:"filtersLabel"`
26 DropdownConfig Dropdown `json:"dropdownConfig"` 26 DropdownConfig Dropdown `json:"dropdownConfig"`
27 } 27 }
28 28
29 type Dropdown struct { 29 type Dropdown struct {
30 ObjectType string `json:"objectType"` 30 ObjectType string `json:"objectType"`
31 FiltersField string `json:"filtersField"` 31 FiltersField string `json:"filtersField"`
32 IDField string `json:"idField"` 32 IDField string `json:"idField"`
33 LabelField string `json:"labelField"` 33 LabelField string `json:"labelField"`
34 } 34 }
35 35
36 type ListGraph struct { 36 type ListGraph struct {
37 ObjectType string `json:"objectType"` 37 ObjectType string `json:"objectType"`
38 X string `json:"xField"` 38 X string `json:"xField"`
39 Y string `json:"yField"` 39 Y string `json:"yField"`
40 GroupField string `json:"groupField"` 40 GroupField string `json:"groupField"`
41 Label string `json:"label"` 41 Label string `json:"label"`
42 } 42 }
43 43
44 type ListActions struct { 44 type ListActions struct {
45 Create bool `json:"create"` 45 Create bool `json:"create"`
46 Update bool `json:"update"` 46 Update bool `json:"update"`
47 Delete bool `json:"delete"` 47 Delete bool `json:"delete"`
48 Export bool `json:"export"` 48 Export bool `json:"export"`
49 Print bool `json:"print"` 49 Print bool `json:"print"`
50 Graph bool `json:"graph"` 50 Graph bool `json:"graph"`
51 LiveGraph bool `json:"liveGraph"` 51 LiveGraph bool `json:"liveGraph"`
52 SaveFile bool `json:"saveFile"`
53 ShowFile bool `json:"showFile"`
52 } 54 }
53 55
54 type ListNavNode struct { 56 type ListNavNode struct {
55 ObjectType string `json:"objectType"` 57 ObjectType string `json:"objectType"`
56 LabelField string `json:"label"` 58 LabelField string `json:"label"`
57 Icon string `json:"icon"` 59 Icon string `json:"icon"`
58 ParentObjectType string `json:"parentObjectType"` 60 ParentObjectType string `json:"parentObjectType"`
59 ParentIDField string `json:"parentIdField"` 61 ParentIDField string `json:"parentIdField"`
60 ParentFilterField string `json:"parentFilterField"` 62 ParentFilterField string `json:"parentFilterField"`
61 } 63 }
62 64
63 type ListParentNode struct { 65 type ListParentNode struct {
64 ObjectType string `json:"objectType"` 66 ObjectType string `json:"objectType"`
65 LabelField string `json:"labelField"` 67 LabelField string `json:"labelField"`
66 FilterField string `json:"filterField"` 68 FilterField string `json:"filterField"`
67 } 69 }
68 70
69 type ListPivot struct { 71 type ListPivot struct {
70 ObjectType string `json:"objectType"` 72 ObjectType string `json:"objectType"`
71 GroupField string `json:"groupField"` 73 GroupField string `json:"groupField"`
72 DistinctField string `json:"distinctField"` 74 DistinctField string `json:"distinctField"`
73 Value string `json:"valueField"` 75 Value string `json:"valueField"`
74 } 76 }
75 77
76 type ListDetails struct { 78 type ListDetails struct {
77 ObjectType string `json:"objectType"` 79 ObjectType string `json:"objectType"`
78 ParentObjectType string `json:"parentObjectType"` 80 ParentObjectType string `json:"parentObjectType"`
79 ParentFilterField string `json:"parentFilterField"` 81 ParentFilterField string `json:"parentFilterField"`
80 SingleDetail bool `json:"singleDetail"` 82 SingleDetail bool `json:"singleDetail"`
81 } 83 }
82 84
83 type ListLiveGraph struct { 85 type ListLiveGraph struct {
84 ObjectType string `json:"objectType"` 86 ObjectType string `json:"objectType"`
85 ValueFields string `json:"valueFields"` 87 ValueFields string `json:"valueFields"`
86 LabelFields string `json:"labelFields"` 88 LabelFields string `json:"labelFields"`
87 } 89 }
88 90
89 type ListConfig struct { 91 type ListConfig struct {
90 ObjectType string `json:"objectType"` 92 ObjectType string `json:"objectType"`
91 Title string `json:"title"` 93 Title string `json:"title"`
92 LazyLoad bool `json:"lazyLoad"` 94 LazyLoad bool `json:"lazyLoad"`
93 InlineEdit bool `json:"inlineEdit"` 95 InlineEdit bool `json:"inlineEdit"`
94 Options ListOptions `json:"options"` 96 Options ListOptions `json:"options"`
95 Filters []ListFilter `json:"defaultFilters"` 97 Filters []ListFilter `json:"defaultFilters"`
96 Graphs []ListGraph `json:"graphs"` 98 Graphs []ListGraph `json:"graphs"`
97 Actions ListActions `json:"actions"` 99 Actions ListActions `json:"actions"`
98 Parent []ListParentNode `json:"parent"` 100 Parent []ListParentNode `json:"parent"`
99 Navigation []ListNavNode `json:"navigation"` 101 Navigation []ListNavNode `json:"navigation"`
100 Pivots []ListPivot `json:"pivots"` 102 Pivots []ListPivot `json:"pivots"`
101 Details ListDetails `json:"details"` 103 Details ListDetails `json:"details"`
102 LiveGraph ListLiveGraph `json:"liveGraphs"` 104 LiveGraph ListLiveGraph `json:"liveGraphs"`
103 } 105 }
104 106
105 // GetListConfig returns list configuration for the provided object type for the front-end application 107 // GetListConfig returns list configuration for the provided object type for the front-end application
106 // or an error if it fails. 108 // or an error if it fails.
107 func GetListConfig(db *sql.DB, objType string) (ListConfig, error) { 109 func GetListConfig(db *sql.DB, objType string) (ListConfig, error) {
108 resp := newDefaultList(objType) 110 list := NewListConfig(objType)
109 var err error 111
110 112 err := list.setParams(db, objType)
111 err = setListParams(db, &resp, objType) 113 err = list.SetNavigation(db, objType)
112 resp.Navigation, err = getListNavigation(db, objType) 114 err = list.SetActions(db, objType)
113 resp.Actions, err = getListActions(db, objType) 115 err = list.SetFilters(db, objType)
114 resp.Filters, err = getListFilters(db, objType) 116 err = list.SetOptions(db, objType)
115 resp.Options, err = getListOptions(db, objType) 117 err = list.SetParent(db, objType)
116 resp.Parent, err = getListParent(db, objType) 118 err = list.SetPivot(db, objType)
117 resp.Graphs, err = getListGraph(db, objType) 119 err = list.SetGraph(db, objType)
118 resp.Pivots, err = getListPivot(db, objType) 120 err = list.SetDetails(db, objType)
119 resp.Details, err = getListDetails(db, objType) 121 err = list.SetLiveGraph(db, objType)
120 resp.LiveGraph, err = getListLiveGraph(db, objType)
121 122
122 if err != nil { 123 if err != nil {
123 return ListConfig{}, err 124 return list, err
124 } 125 }
125 126
126 return resp, nil 127 return list, nil
127 } 128 }
128 129
129 // GetListConfigObjectIDField takes in database connection and an object type and it returns the 130 // GetListConfigObjectIDField takes in database connection and an object type and it returns the
130 // ID field name for the provided object type. 131 // ID field name for the provided object type.
131 func GetListConfigObjectIDField(db *sql.DB, otype string) string { 132 func GetListConfigObjectIDField(db *sql.DB, otype string) string {
132 var resp string 133 var resp string
133 134
134 rows, err := db.Query(`SELECT 135 rows, err := db.Query(`SELECT
135 ID_FIELD 136 ID_FIELD
136 FROM LIST_CONFIG_ID_FIELD 137 FROM LIST_CONFIG_ID_FIELD
137 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", otype)) 138 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", otype))
138 if err != nil { 139 if err != nil {
139 return "" 140 return ""
140 } 141 }
141 defer rows.Close() 142 defer rows.Close()
142 143
143 if rows.Next() { 144 if rows.Next() {
144 rows.Scan(&resp) 145 rows.Scan(&resp)
145 } 146 }
146 147
147 if rows.Err() != nil { 148 if rows.Err() != nil {
148 return "" 149 return ""
149 } 150 }
150 151
151 return resp 152 return resp
152 } 153 }
153 154
154 // newDefaultList returns default configuration for the provided object type. 155 // newDefaultList returns default configuration for the provided object type.
155 func newDefaultList(objType string) ListConfig { 156 func NewListConfig(objType string) ListConfig {
156 list := ListConfig{ 157 list := ListConfig{
157 ObjectType: objType, 158 ObjectType: objType,
158 Title: objType, 159 Title: objType,
159 LazyLoad: false, 160 LazyLoad: false,
160 Options: ListOptions{ 161 Options: ListOptions{
161 GlobalFilter: true, 162 GlobalFilter: true,
162 LocalFilters: true, 163 LocalFilters: true,
163 RemoteFilters: false, 164 RemoteFilters: false,
164 Pagination: true, 165 Pagination: true,
165 PageSize: 20, 166 PageSize: 20,
166 }, 167 },
167 Filters: nil, 168 Filters: nil,
168 Actions: ListActions{ 169 Actions: ListActions{
169 Create: false, 170 Create: false,
170 Update: false, 171 Update: false,
171 Delete: false, 172 Delete: false,
172 Export: false, 173 Export: false,
173 Print: false, 174 Print: false,
174 Graph: false, 175 Graph: false,
175 LiveGraph: false, 176 LiveGraph: false,
176 }, 177 },
177 Parent: nil, 178 Parent: nil,
178 Navigation: nil, 179 Navigation: nil,
179 } 180 }
180 181
181 return list 182 return list
182 } 183 }
183 184
184 // setListParams sets the default parameters of the provided configuration list for the provided object type. 185 // setListParams sets the default parameters of the provided configuration list for the provided object type.
185 func setListParams(db *sql.DB, list *ListConfig, objType string) error { 186 func (list *ListConfig) setParams(db *sql.DB, objType string) error {
186 rows, err := db.Query(`SELECT 187 rows, err := db.Query(`SELECT
187 OBJECT_TYPE, TITLE, LAZY_LOAD, INLINE_EDIT 188 OBJECT_TYPE,
189 TITLE,
190 LAZY_LOAD,
191 INLINE_EDIT
188 FROM LIST_CONFIG 192 FROM LIST_CONFIG
189 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 193 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
190 if err != nil { 194 if err != nil {
191 return err 195 return err
192 } 196 }
193 defer rows.Close() 197 defer rows.Close()
194 if rows.Next() { 198 if rows.Next() {
195 otype, title := "", "" 199 otype, title := "", ""
196 lazyLoad, inlineEdit := 0, 0 200 lazyLoad, inlineEdit := 0, 0
197 rows.Scan(&otype, &title, &lazyLoad, &inlineEdit) 201 rows.Scan(&otype, &title, &lazyLoad, &inlineEdit)
198 202
199 if otype != "" { 203 if otype != "" {
200 list.ObjectType = otype 204 list.ObjectType = otype
201 } 205 }
202 if title != "" { 206 if title != "" {
203 list.Title = title 207 list.Title = title
204 } 208 }
205 list.LazyLoad = lazyLoad != 0 209 list.LazyLoad = lazyLoad != 0
206 list.InlineEdit = inlineEdit != 0 210 list.InlineEdit = inlineEdit != 0
207 } 211 }
208 if rows.Err() != nil { 212 if rows.Err() != nil {
209 return rows.Err() 213 return rows.Err()
210 } 214 }
211 return nil 215 return nil
212 } 216 }
213 217
214 // getListNavigation returns list navigation node slice for the provided objectType. 218 // ListNavigation returns list navigation node slice for the provided objectType.
215 func getListNavigation(db *sql.DB, listObjType string) ([]ListNavNode, error) { 219 func (list *ListConfig) SetNavigation(db *sql.DB, listObjType string) error {
216 resp := make([]ListNavNode, 0) 220 list.Navigation = make([]ListNavNode, 0)
217 rows, err := db.Query(`SELECT 221 rows, err := db.Query(`SELECT
218 a.OBJECT_TYPE, a.PARENT_OBJECT_TYPE, a.LABEL, a.ICON, a.PARENT_FILTER_FIELD, b.PARENT_ID_FIELD 222 a.OBJECT_TYPE,
223 a.PARENT_OBJECT_TYPE,
224 a.LABEL,
225 a.ICON,
226 a.PARENT_FILTER_FIELD,
227 b.PARENT_ID_FIELD
219 FROM LIST_CONFIG_NAVIGATION b 228 FROM LIST_CONFIG_NAVIGATION b
220 JOIN LIST_CONFIG_CHILD a ON b.PARENT_CHILD_ID = a.PARENT_CHILD_ID 229 JOIN LIST_CONFIG_CHILD a ON b.PARENT_CHILD_ID = a.PARENT_CHILD_ID
221 WHERE b.LIST_OBJECT_TYPE = ` + fmt.Sprintf("'%s'", listObjType) + 230 WHERE b.LIST_OBJECT_TYPE = ` + fmt.Sprintf("'%s'", listObjType) +
222 ` ORDER BY b.RB ASC`) 231 ` ORDER BY b.RB ASC`)
223 if err != nil { 232 if err != nil {
224 return resp, err 233 return err
225 } 234 }
226 defer rows.Close() 235 defer rows.Close()
227 236
228 var node ListNavNode 237 var node ListNavNode
229 for rows.Next() { 238 for rows.Next() {
230 rows.Scan(&node.ObjectType, &node.ParentObjectType, &node.LabelField, &node.Icon, 239 rows.Scan(&node.ObjectType, &node.ParentObjectType, &node.LabelField, &node.Icon,
231 &node.ParentFilterField, &node.ParentIDField) 240 &node.ParentFilterField, &node.ParentIDField)
232 resp = append(resp, node) 241 list.Navigation = append(list.Navigation, node)
233 } 242 }
234 if rows.Err() != nil { 243 if rows.Err() != nil {
235 return nil, rows.Err() 244 return rows.Err()
236 } 245 }
237 246
238 return resp, nil 247 return nil
239 } 248 }
240 249
241 // getListActions returns list actions for the provided object type. 250 // getListActions returns list actions for the provided object type.
242 func getListActions(db *sql.DB, objType string) (ListActions, error) { 251 func (list *ListConfig) SetActions(db *sql.DB, objType string) error {
243 var resp ListActions
244 rows, err := db.Query(`SELECT 252 rows, err := db.Query(`SELECT
245 ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE, ACTION_EXPORT, 253 ACTION_CREATE,
246 ACTION_PRINT, ACTION_GRAPH, ACTION_LIVE_GRAPH 254 ACTION_UPDATE,
255 ACTION_DELETE,
256 ACTION_EXPORT,
257 ACTION_PRINT,
258 ACTION_GRAPH,
259 ACTION_LIVE_GRAPH,
260 ACTION_SAVE_FILE,
261 ACTION_SHOW_FILE
247 FROM LIST_CONFIG 262 FROM LIST_CONFIG
248 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 263 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
249 if err != nil { 264 if err != nil {
250 return ListActions{}, err 265 return err
251 } 266 }
252 defer rows.Close() 267 defer rows.Close()
253 268
254 var create, update, delete, export, print, graph, liveGraph uint32 269 var create, update, delete, export, print, graph, liveGraph, saveFile, showFile uint32
255 if rows.Next() { 270 if rows.Next() {
256 rows.Scan(&create, &update, &delete, &export, &print, &graph, &liveGraph) 271 rows.Scan(&create, &update, &delete, &export, &print, &graph, &liveGraph, &saveFile, &showFile)
257 resp.Create = create != 0 272 list.Actions.Create = create != 0
258 resp.Update = update != 0 273 list.Actions.Update = update != 0
259 resp.Delete = delete != 0 274 list.Actions.Delete = delete != 0
260 resp.Export = export != 0 275 list.Actions.Export = export != 0
261 resp.Print = print != 0 276 list.Actions.Print = print != 0
262 resp.Graph = graph != 0 277 list.Actions.Graph = graph != 0
263 resp.LiveGraph = liveGraph != 0 278 list.Actions.LiveGraph = liveGraph != 0
279 list.Actions.SaveFile = saveFile != 0
280 list.Actions.ShowFile = showFile != 0
264 } 281 }
265 if rows.Err() != nil { 282 if rows.Err() != nil {
266 return ListActions{}, rows.Err() 283 return rows.Err()
267 } 284 }
268 return resp, nil 285
286 return nil
269 } 287 }
270 288
271 // getListFiters returns list filter slice for the provided object type. 289 // getListFiters returns list filter slice for the provided object type.
272 func getListFilters(db *sql.DB, objType string) ([]ListFilter, error) { 290 func (list *ListConfig) SetFilters(db *sql.DB, objType string) error {
273 resp := make([]ListFilter, 0) 291 list.Filters = make([]ListFilter, 0)
274 filtersFields, err := getFilterFieldsAndPosition(db, objType) 292 filtersFields, err := list.GetFilterFieldsAndPosition(db, objType)
275 if err != nil { 293 if err != nil {
276 return nil, err 294 return err
277 } 295 }
278 for field, pos := range filtersFields { 296 for field, pos := range filtersFields {
279 filters, _ := getFiltersByFilterField(db, field) 297 filters, _ := list.GetFiltersByFilterField(db, field)
280 for _, filter := range filters { 298 for _, filter := range filters {
281 var f ListFilter 299 var f ListFilter
282 f.Position = pos 300 f.Position = pos
283 f.ObjectType = objType 301 f.ObjectType = objType
284 f.FiltersField = field 302 f.FiltersField = field
285 f.DefaultValues = filter.DefaultValues 303 f.DefaultValues = filter.DefaultValues
286 f.FiltersLabel = filter.Label 304 f.FiltersLabel = filter.Label
287 f.FiltersType = filter.Type 305 f.FiltersType = filter.Type
288 if filter.Type == "dropdown" { 306 if filter.Type == "dropdown" {
289 f.DropdownConfig, err = getFilterDropdownConfig(db, field) 307 err := f.SetDropdownConfig(db, field)
290 if err != nil { 308 if err != nil {
291 return nil, err 309 return err
292 } 310 }
293 } 311 }
294 resp = append(resp, f) 312 list.Filters = append(list.Filters, f)
295 } 313 }
296 } 314 }
297 315
298 sortFilters(resp) 316 list.sortFilters()
299 317
300 return resp, nil 318 return nil
301 } 319 }
302 320
303 // getFilterFieldsAndPosition returns a map of filter fields and their respective position in the menu. 321 // getFilterFieldsAndPosition returns a map of filter fields and their respective position in the menu.
304 func getFilterFieldsAndPosition(db *sql.DB, objType string) (map[string]uint32, error) { 322 func (list *ListConfig) GetFilterFieldsAndPosition(db *sql.DB, objType string) (map[string]uint32, error) {
305 filtersField := make(map[string]uint32, 0) 323 filtersField := make(map[string]uint32, 0)
306 rows, err := db.Query(`SELECT 324 rows, err := db.Query(`SELECT
307 FILTERS_FIELD, RB 325 FILTERS_FIELD,
326 RB
308 FROM LIST_CONFIG_FILTERS 327 FROM LIST_CONFIG_FILTERS
309 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 328 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
310 if err != nil { 329 if err != nil {
311 return nil, err 330 return nil, err
312 } 331 }
313 defer rows.Close() 332 defer rows.Close()
314 333
315 for rows.Next() { 334 for rows.Next() {
316 var field string 335 var field string
317 var rb uint32 336 var rb uint32
318 rows.Scan(&field, &rb) 337 rows.Scan(&field, &rb)
319 filtersField[field] = rb 338 filtersField[field] = rb
320 } 339 }
321 if rows.Err() != nil { 340 if rows.Err() != nil {
322 return nil, rows.Err() 341 return nil, rows.Err()
323 } 342 }
324 return filtersField, nil 343 return filtersField, nil
325 } 344 }
326 345
327 type _filter struct { 346 type _filter struct {
328 DefaultValues string 347 DefaultValues string
329 Label string 348 Label string
330 Type string 349 Type string
331 } 350 }
332 351
333 // getFiltersByFilterField returns filter slice for the provided filter field. 352 // getFiltersByFilterField returns filter slice for the provided filter field.
334 func getFiltersByFilterField(db *sql.DB, filtersField string) ([]_filter, error) { 353 func (list *ListConfig) GetFiltersByFilterField(db *sql.DB, filtersField string) ([]_filter, error) {
335 resp := make([]_filter, 0) 354 resp := make([]_filter, 0)
336 rows, err := db.Query(`SELECT 355 rows, err := db.Query(`SELECT
337 FILTERS_TYPE, FILTERS_LABEL, DEFAULT_VALUES 356 FILTERS_TYPE,
357 FILTERS_LABEL,
358 DEFAULT_VALUES
338 FROM LIST_FILTERS_FIELD 359 FROM LIST_FILTERS_FIELD
339 WHERE FILTERS_FIELD = ` + fmt.Sprintf("'%s'", filtersField)) 360 WHERE FILTERS_FIELD = ` + fmt.Sprintf("'%s'", filtersField))
340 if err != nil { 361 if err != nil {
341 return resp, err 362 return resp, err
342 } 363 }
343 defer rows.Close() 364 defer rows.Close()
344 365
345 var f _filter 366 var f _filter
346 for rows.Next() { 367 for rows.Next() {
347 rows.Scan(&f.Type, &f.Label, &f.DefaultValues) 368 rows.Scan(&f.Type, &f.Label, &f.DefaultValues)
348 resp = append(resp, f) 369 resp = append(resp, f)
349 } 370 }
350 if rows.Err() != nil { 371 if rows.Err() != nil {
351 return resp, rows.Err() 372 return resp, rows.Err()
352 } 373 }
353 return resp, nil 374 return resp, nil
354 } 375 }
355 376
356 // getFilterDropdownConfig returns dropdown menu for the provided filter field. 377 // getFilterDropdownConfig returns dropdown menu for the provided filter field.
357 func getFilterDropdownConfig(db *sql.DB, filtersField string) (Dropdown, error) { 378 func (f *ListFilter) SetDropdownConfig(db *sql.DB, filtersField string) error {
358 var resp Dropdown 379 var resp Dropdown
359 rows, err := db.Query(`SELECT 380 rows, err := db.Query(`SELECT
360 FILTERS_FIELD, OBJECT_TYPE, ID_FIELD, LABEL_FIELD 381 FILTERS_FIELD,
382 OBJECT_TYPE,
383 ID_FIELD,
384 LABEL_FIELD
361 FROM LIST_DROPDOWN_FILTER 385 FROM LIST_DROPDOWN_FILTER
362 WHERE FILTERS_FIELD = ` + fmt.Sprintf("'%s'", filtersField)) 386 WHERE FILTERS_FIELD = ` + fmt.Sprintf("'%s'", filtersField))
363 if err != nil { 387 if err != nil {
364 return resp, err 388 return err
365 } 389 }
366 defer rows.Close() 390 defer rows.Close()
367 if rows.Next() { 391 if rows.Next() {
368 rows.Scan(&resp.FiltersField, &resp.ObjectType, &resp.IDField, &resp.LabelField) 392 rows.Scan(&resp.FiltersField, &resp.ObjectType, &resp.IDField, &resp.LabelField)
369 } 393 }
370 if rows.Err() != nil { 394 if rows.Err() != nil {
371 return resp, rows.Err() 395 return rows.Err()
372 } 396 }
373 return resp, nil 397
398 f.DropdownConfig = resp
399
400 return nil
374 } 401 }
375 402
376 // sortFilters bubble sorts provided filters slice by position field. 403 // sortFilters bubble sorts provided filters slice by position field.
377 func sortFilters(filters []ListFilter) { 404 func (list *ListConfig) sortFilters() {
378 done := false 405 done := false
379 var temp ListFilter 406 var temp ListFilter
380 for !done { 407 for !done {
381 done = true 408 done = true
382 for i := 0; i < len(filters)-1; i++ { 409 for i := 0; i < len(list.Filters)-1; i++ {
383 if filters[i].Position > filters[i+1].Position { 410 if list.Filters[i].Position > list.Filters[i+1].Position {
384 done = false 411 done = false
385 temp = filters[i] 412 temp = list.Filters[i]
386 filters[i] = filters[i+1] 413 list.Filters[i] = list.Filters[i+1]
387 filters[i+1] = temp 414 list.Filters[i+1] = temp
388 } 415 }
389 } 416 }
390 } 417 }
391 } 418 }
392 419
393 // getListGraph return list graph slice for the provided object type. 420 // getListGraph return list graph slice for the provided object type.
394 func getListGraph(db *sql.DB, objType string) ([]ListGraph, error) { 421 func (list *ListConfig) SetGraph(db *sql.DB, objType string) error {
395 resp := make([]ListGraph, 0) 422 list.Graphs = make([]ListGraph, 0)
396 rows, err := db.Query(`SELECT 423 rows, err := db.Query(`SELECT
397 OBJECT_TYPE, X_FIELD, Y_FIELD, GROUP_FIELD, LABEL 424 OBJECT_TYPE,
425 X_FIELD,
426 Y_FIELD,
427 GROUP_FIELD,
428 LABEL
398 FROM LIST_GRAPHS 429 FROM LIST_GRAPHS
399 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 430 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
400 if err != nil { 431 if err != nil {
401 return resp, err 432 return err
402 } 433 }
403 defer rows.Close() 434 defer rows.Close()
404 435
405 var lg ListGraph 436 var lg ListGraph
406 for rows.Next() { 437 for rows.Next() {
407 rows.Scan(&lg.ObjectType, &lg.X, &lg.Y, &lg.GroupField, &lg.Label) 438 rows.Scan(&lg.ObjectType, &lg.X, &lg.Y, &lg.GroupField, &lg.Label)
408 resp = append(resp, lg) 439 list.Graphs = append(list.Graphs, lg)
409 } 440 }
410 if rows.Err() != nil { 441 if rows.Err() != nil {
411 return resp, rows.Err() 442 return rows.Err()
412 } 443 }
413 return resp, nil 444
445 return nil
414 } 446 }
415 447
416 // getListOptions returns list options for the provided object type. 448 // getListOptions returns list options for the provided object type.
417 func getListOptions(db *sql.DB, objType string) (ListOptions, error) { 449 func (list *ListConfig) SetOptions(db *sql.DB, objType string) error {
418 var resp ListOptions
419 rows, err := db.Query(`SELECT 450 rows, err := db.Query(`SELECT
420 GLOBAL_FILTER, LOCAL_FILTER, REMOTE_FILTER, PAGINATION, 451 GLOBAL_FILTER,
421 PAGE_SIZE, PIVOT, DETAIL, TOTAL 452 LOCAL_FILTER,
453 REMOTE_FILTER,
454 PAGINATION,
455 PAGE_SIZE,
456 PIVOT,
457 DETAIL,
458 TOTAL
422 FROM LIST_CONFIG 459 FROM LIST_CONFIG
423 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 460 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
424 if err != nil { 461 if err != nil {
425 return ListOptions{}, err 462 return err
426 } 463 }
427 defer rows.Close() 464 defer rows.Close()
465
428 if rows.Next() { 466 if rows.Next() {
429 var gfilter, lfilters, rfilters, pagination, pageSize, pivot, detail, total uint32 467 var gfilter, lfilters, rfilters, pagination, pageSize, pivot, detail, total uint32
430 rows.Scan(&gfilter, &lfilters, &rfilters, &pagination, &pageSize, &pivot, &detail, &total) 468 rows.Scan(&gfilter, &lfilters, &rfilters, &pagination, &pageSize, &pivot, &detail, &total)
431 resp.GlobalFilter = gfilter != 0 469 list.Options.GlobalFilter = gfilter != 0
432 resp.LocalFilters = lfilters != 0 470 list.Options.LocalFilters = lfilters != 0
433 resp.RemoteFilters = rfilters != 0 471 list.Options.RemoteFilters = rfilters != 0
434 resp.Pagination = pagination != 0 472 list.Options.Pagination = pagination != 0
435 resp.PageSize = pageSize 473 list.Options.PageSize = pageSize
436 resp.Pivot = pivot != 0 474 list.Options.Pivot = pivot != 0
437 resp.Detail = detail != 0 475 list.Options.Detail = detail != 0
438 resp.Total = total != 0 476 list.Options.Total = total != 0
439 } 477 }
440 if rows.Err() != nil { 478 if rows.Err() != nil {
441 return ListOptions{}, rows.Err() 479 return rows.Err()
442 } 480 }
443 return resp, nil 481
482 return nil
444 } 483 }
445 484
446 // getListParent returns list parent node slice for the provided object type. 485 // getListParent returns list parent node slice for the provided object type.
447 func getListParent(db *sql.DB, objType string) ([]ListParentNode, error) { 486 func (list *ListConfig) SetParent(db *sql.DB, objType string) error {
448 resp := make([]ListParentNode, 0) 487 list.Parent = make([]ListParentNode, 0)
449 rows, err := db.Query(`SELECT 488 rows, err := db.Query(`SELECT
450 PARENT_OBJECT_TYPE, PARENT_LABEL_FIELD, PARENT_FILTER_FIELD 489 PARENT_OBJECT_TYPE,
490 PARENT_LABEL_FIELD,
491 PARENT_FILTER_FIELD
451 FROM LIST_CONFIG_CHILD 492 FROM LIST_CONFIG_CHILD
452 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 493 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
453 if err != nil { 494 if err != nil {
454 return resp, err 495 return err
455 } 496 }
456 defer rows.Close() 497 defer rows.Close()
457 498
458 var pnode ListParentNode 499 var pnode ListParentNode
459 for rows.Next() { 500 for rows.Next() {
460 rows.Scan(&pnode.ObjectType, &pnode.LabelField, &pnode.FilterField) 501 rows.Scan(&pnode.ObjectType, &pnode.LabelField, &pnode.FilterField)
461 resp = append(resp, pnode) 502 list.Parent = append(list.Parent, pnode)
462 } 503 }
463 if rows.Err() != nil { 504 if rows.Err() != nil {
464 return nil, rows.Err() 505 return rows.Err()
465 } 506 }
466 507
467 return resp, nil 508 return nil
468 } 509 }
469 510
470 // getListPivot list pivot slice for the provided object type. 511 // getListPivot list pivot slice for the provided object type.
471 func getListPivot(db *sql.DB, objType string) ([]ListPivot, error) { 512 func (list *ListConfig) SetPivot(db *sql.DB, objType string) error {
472 resp := make([]ListPivot, 0) 513 list.Pivots = make([]ListPivot, 0)
473 rows, err := db.Query(`SELECT 514 rows, err := db.Query(`SELECT
474 OBJECT_TYPE, GROUP_FIELD, DISTINCT_FIELD, VALUE_FIELD 515 OBJECT_TYPE,
516 GROUP_FIELD,
517 DISTINCT_FIELD,
518 VALUE_FIELD
475 FROM LIST_PIVOTS 519 FROM LIST_PIVOTS
476 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 520 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
477 if err != nil { 521 if err != nil {
478 return resp, err 522 return err
479 } 523 }
480 defer rows.Close() 524 defer rows.Close()
481 525
482 var p ListPivot 526 var p ListPivot
483 for rows.Next() { 527 for rows.Next() {
484 rows.Scan(&p.ObjectType, &p.GroupField, &p.DistinctField, &p.Value) 528 rows.Scan(&p.ObjectType, &p.GroupField, &p.DistinctField, &p.Value)
485 resp = append(resp, p) 529 list.Pivots = append(list.Pivots, p)
486 } 530 }
487 if rows.Err() != nil { 531 if rows.Err() != nil {
488 return nil, rows.Err() 532 return rows.Err()
489 } 533 }
490 534
491 return resp, nil 535 return nil
492 } 536 }
493 537
494 // getListDetails returns list details for the provided object type. 538 // getListDetails returns list details for the provided object type.
495 func getListDetails(db *sql.DB, objType string) (ListDetails, error) { 539 func (list *ListConfig) SetDetails(db *sql.DB, objType string) error {
496 var resp ListDetails 540 var resp ListDetails
497 rows, err := db.Query(`SELECT 541 rows, err := db.Query(`SELECT
498 OBJECT_TYPE, PARENT_OBJECT_TYPE, PARENT_FILTER_FIELD, SINGLE_DETAIL 542 OBJECT_TYPE,
543 PARENT_OBJECT_TYPE,
544 PARENT_FILTER_FIELD,
545 SINGLE_DETAIL
499 FROM LIST_CONFIG_DETAIL 546 FROM LIST_CONFIG_DETAIL
500 WHERE PARENT_OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 547 WHERE PARENT_OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
501 if err != nil { 548 if err != nil {
502 return resp, err 549 return err
503 } 550 }
504 defer rows.Close() 551 defer rows.Close()
505 if rows.Next() { 552 if rows.Next() {
506 var singleDetail uint32 553 var singleDetail uint32
507 rows.Scan(&resp.ObjectType, &resp.ParentObjectType, &resp.ParentFilterField, &singleDetail) 554 rows.Scan(&resp.ObjectType, &resp.ParentObjectType, &resp.ParentFilterField, &singleDetail)
508 resp.SingleDetail = singleDetail != 0 555 resp.SingleDetail = singleDetail != 0
509 } 556 }
510 if rows.Err() != nil { 557 if rows.Err() != nil {
511 return resp, rows.Err() 558 return rows.Err()
512 } 559 }
513 560
514 return resp, nil 561 list.Details = resp
562
563 return nil
515 } 564 }
516 565
517 // getListLiveGraph returns live graph for the provided object type. 566 // getListLiveGraph returns live graph for the provided object type.
518 func getListLiveGraph(db *sql.DB, objType string) (ListLiveGraph, error) { 567 func (list *ListConfig) SetLiveGraph(db *sql.DB, objType string) error {
519 var resp ListLiveGraph 568 var resp ListLiveGraph
520 rows, err := db.Query(`SELECT 569 rows, err := db.Query(`SELECT
521 OBJECT_TYPE, VALUE_FIELDS, LABEL_FIELDS 570 OBJECT_TYPE,
571 VALUE_FIELDS,
572 LABEL_FIELDS
522 FROM LIST_LIVE_GRAPH 573 FROM LIST_LIVE_GRAPH
523 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType)) 574 WHERE OBJECT_TYPE = ` + fmt.Sprintf("'%s'", objType))
524 if err != nil { 575 if err != nil {
525 return resp, err 576 return err
526 } 577 }
527 defer rows.Close() 578 defer rows.Close()
528 if rows.Next() { 579 if rows.Next() {
529 rows.Scan(&resp.ObjectType, &resp.ValueFields, &resp.LabelFields) 580 rows.Scan(&resp.ObjectType, &resp.ValueFields, &resp.LabelFields)
530 } 581 }
531 if rows.Err() != nil { 582 if rows.Err() != nil {
532 return resp, rows.Err() 583 return rows.Err()
533 } 584 }
534 585
535 return resp, nil 586 list.LiveGraph = resp
587
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "net/http" 4 "net/http"
5 "time" 5 "time"
6 6
7 "git.to-net.rs/marko.tikvic/gologger" 7 "git.to-net.rs/marko.tikvic/gologger"
8 ) 8 )
9 9
10 func SetHeaders(h http.HandlerFunc) http.HandlerFunc { 10 func SetHeaders(h http.HandlerFunc) http.HandlerFunc {
11 return func(w http.ResponseWriter, req *http.Request) { 11 return func(w http.ResponseWriter, req *http.Request) {
12 SetDefaultHeaders(w) 12 SetDefaultHeaders(w)
13 if req.Method == http.MethodOptions { 13 if req.Method == http.MethodOptions {
14 return 14 return
15 } 15 }
16 h(w, req) 16 h(w, req)
17 } 17 }
18 } 18 }
19 19
20 func ParseForm(h http.HandlerFunc) http.HandlerFunc { 20 func ParseForm(h http.HandlerFunc) http.HandlerFunc {
21 return func(w http.ResponseWriter, req *http.Request) { 21 return func(w http.ResponseWriter, req *http.Request) {
22 err := req.ParseForm() 22 err := req.ParseForm()
23 if err != nil { 23 if err != nil {
24 BadRequest(w, req, err.Error()) 24 BadRequest(w, req, err.Error())
25 return 25 return
26 } 26 }
27 h(w, req) 27 h(w, req)
28 } 28 }
29 } 29 }
30 30
31 func ParseMultipartForm(h http.HandlerFunc) http.HandlerFunc {
32 return func(w http.ResponseWriter, req *http.Request) {
33 err := req.ParseMultipartForm(32 << 20)
34 if err != nil {
35 BadRequest(w, req, err.Error())
36 return
37 }
38 h(w, req)
39 }
40 }
41
31 var trafficLogger *gologger.Logger 42 var trafficLogger *gologger.Logger
32 43
33 func EnableLogging(log string) error { 44 func EnableLogging(log string) error {
34 var err error 45 var err error
35 trafficLogger, err = gologger.New(log, gologger.MaxLogSize5MB) 46 trafficLogger, err = gologger.New(log, gologger.MaxLogSize5MB)
36 return err 47 return err
37 } 48 }
38 49
39 func Log(h http.HandlerFunc) http.HandlerFunc { 50 func Log(h http.HandlerFunc) http.HandlerFunc {
40 return func(w http.ResponseWriter, req *http.Request) { 51 return func(w http.ResponseWriter, req *http.Request) {
52 t1 := time.Now()
53
41 in := trafficLogger.RequestLog(req, "") 54 in := trafficLogger.RequestLog(req, "")
42 55
43 w2 := WrapWithStatusRecorder(w) 56 wRec := WrapWithStatusRecorder(w)
44 t1 := time.Now() 57 h(wRec, req)
45 h(w2, req) 58
46 t2 := time.Now() 59 t2 := time.Now()
47 60
48 out := trafficLogger.ResponseLog(w2.Status(), t2.Sub(t1)) 61 out := trafficLogger.ResponseLog(wRec.Status(), t2.Sub(t1), 0)
62
49 trafficLogger.LogHTTPTraffic(in, out) 63 trafficLogger.LogHTTPTraffic(in, out)
50 } 64 }
51 } 65 }
52 66
53 func Auth(roles string, h http.HandlerFunc) http.HandlerFunc { 67 func Auth(roles string, h http.HandlerFunc) http.HandlerFunc {
54 return func(w http.ResponseWriter, req *http.Request) { 68 return func(w http.ResponseWriter, req *http.Request) {
55 if _, ok := AuthCheck(req, roles); !ok { 69 if _, err := AuthCheck(req, roles); err != nil {
56 Unauthorized(w, req, "") 70 Unauthorized(w, req, err.Error())
57 return 71 return
58 } 72 }
59 h(w, req) 73 h(w, req)
60 } 74 }
61 } 75 }
62 76