Commit 1d0f615536520bf32f1acd061f7acf4a367e9bee

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

can't fetch clob

1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "errors" 4 "errors"
5 "time" 5 "time"
6 "crypto/sha256" 6 "crypto/sha256"
7 "crypto/rand" 7 "crypto/rand"
8 "encoding/hex" 8 "encoding/hex"
9 "strings" 9 "strings"
10 "net/http" 10 "net/http"
11 11
12 "github.com/dgrijalva/jwt-go" 12 "github.com/dgrijalva/jwt-go"
13 ) 13 )
14 14
15 const OneDay = time.Hour*24 15 const OneDay = time.Hour*24
16 const OneWeek = OneDay*7 16 const OneWeek = OneDay*7
17 const saltSize = 32 17 const saltSize = 32
18 const appName = "korisnicki-centar" 18 const appName = "korisnicki-centar"
19 const secret = "korisnicki-centar-api" 19 const secret = "korisnicki-centar-api"
20 20
21 const RoleAdmin string = "ADMINISTRATOR" 21 const RoleAdmin string = "ADMINISTRATOR"
22 const RoleManager string = "RUKOVODILAC" 22 const RoleManager string = "RUKOVODILAC"
23 const RoleReporter string = "REPORTER" 23 const RoleReporter string = "REPORTER"
24 const RoleOperator string = "OPERATER" 24 const RoleOperator string = "OPERATER"
25 25
26 // TokenClaims are JWT token claims. 26 // TokenClaims are JWT token claims.
27 type TokenClaims struct { 27 type TokenClaims struct {
28 Username string `json:"username"` 28 Username string `json:"username"`
29 Role string `json:"role"` 29 Role string `json:"role"`
30 jwt.StandardClaims 30 jwt.StandardClaims
31 } 31 }
32 32
33 // CredentialsStruct is an instace of username/password values. 33 // CredentialsStruct is an instace of username/password values.
34 type CredentialsStruct struct { 34 type CredentialsStruct struct {
35 Username string `json:"username"` 35 Username string `json:"username"`
36 Password string `json:"password"` 36 Password string `json:"password"`
37 } 37 }
38 38
39 // generateSalt returns a string of random characters of 'saltSize' length. 39 // generateSalt returns a string of random characters of 'saltSize' length.
40 func generateSalt() (salt string, err error) { 40 func generateSalt() (salt string, err error) {
41 rawsalt := make([]byte, saltSize) 41 rawsalt := make([]byte, saltSize)
42 42
43 _, err = rand.Read(rawsalt) 43 _, err = rand.Read(rawsalt)
44 if err != nil { 44 if err != nil {
45 return "", err 45 return "", err
46 } 46 }
47 47
48 salt = hex.EncodeToString(rawsalt) 48 salt = hex.EncodeToString(rawsalt)
49 return salt, nil 49 return salt, nil
50 } 50 }
51 51
52 // HashString hashes input string with SHA256 algorithm. 52 // HashString hashes input string with SHA256 algorithm.
53 // If the presalt parameter is not provided HashString will generate new salt string. 53 // If the presalt parameter is not provided HashString will generate new salt string.
54 // Returns hash and salt string or an error if it fails. 54 // Returns hash and salt string or an error if it fails.
55 func HashString(str string, presalt string) (hash, salt string, err error) { 55 func HashString(str string, 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 = generateSalt() 58 salt, err = generateSalt()
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 // CreateAPIToken returns JWT token with encoded username, role, expiration date and issuer claims. 86 // CreateAPIToken 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 CreateAPIToken(username, role string) (string, error) { 88 func CreateAPIToken(username, role string) (string, error) {
89 var apiToken string 89 var apiToken string
90 var err error 90 var err error
91 91
92 if err != nil { 92 if err != nil {
93 return "", err 93 return "", err
94 } 94 }
95 95
96 claims := TokenClaims{ 96 claims := TokenClaims{
97 username, 97 username,
98 role, 98 role,
99 jwt.StandardClaims{ 99 jwt.StandardClaims{
100 ExpiresAt: (time.Now().Add(OneWeek)).Unix(), 100 ExpiresAt: (time.Now().Add(OneWeek)).Unix(),
101 Issuer: appName, 101 Issuer: appName,
102 }, 102 },
103 } 103 }
104 104
105 jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) 105 jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
106 apiToken, err = jwtToken.SignedString([]byte(secret)) 106 apiToken, err = jwtToken.SignedString([]byte(secret))
107 if err != nil { 107 if err != nil {
108 return "", err 108 return "", err
109 } 109 }
110 return apiToken, nil 110 return apiToken, nil
111 } 111 }
112 112
113 // RefreshAPIToken prolongs JWT token's expiration date for one week. 113 // RefreshAPIToken prolongs JWT token's expiration date for one week.
114 // It returns new JWT token or an error if it fails. 114 // It returns new JWT token or an error if it fails.
115 func RefreshAPIToken(tokenString string) (string, error) { 115 func RefreshAPIToken(tokenString string) (string, error) {
116 var newToken string 116 var newToken string
117 tokenString = strings.TrimPrefix(tokenString, "Bearer ") 117 tokenString = strings.TrimPrefix(tokenString, "Bearer ")
118 token, err := jwt.ParseWithClaims(tokenString, &TokenClaims{}, secretFunc) 118 token, err := jwt.ParseWithClaims(tokenString, &TokenClaims{}, secretFunc)
119 if err != nil { 119 if err != nil {
120 return "", err 120 return "", err
121 } 121 }
122 122
123 // type assertion 123 // type assertion
124 claims, ok := token.Claims.(*TokenClaims) 124 claims, ok := token.Claims.(*TokenClaims)
125 if !ok || !token.Valid { 125 if !ok || !token.Valid {
126 return "", errors.New("token is not valid") 126 return "", errors.New("token is not valid")
127 } 127 }
128 128
129 claims.ExpiresAt = (time.Now().Add(OneWeek)).Unix() 129 claims.ExpiresAt = (time.Now().Add(OneWeek)).Unix()
130 jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) 130 jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
131 131
132 newToken, err = jwtToken.SignedString([]byte(secret)) 132 newToken, err = jwtToken.SignedString([]byte(secret))
133 if err != nil { 133 if err != nil {
134 return "", err 134 return "", err
135 } 135 }
136 136
137 return newToken, nil 137 return newToken, nil
138 } 138 }
139 139
140 // ParseAPIToken parses JWT token claims. 140 // ParseAPIToken parses JWT token claims.
141 // It returns a pointer to TokenClaims struct or an error if it fails. 141 // It returns a pointer to TokenClaims struct or an error if it fails.
142 func ParseAPIToken(tokenString string) (*TokenClaims, error) { 142 func ParseAPIToken(tokenString string) (*TokenClaims, error) {
143 if ok := strings.HasPrefix(tokenString, "Bearer "); ok { 143 if ok := strings.HasPrefix(tokenString, "Bearer "); ok {
144 tokenString = strings.TrimPrefix(tokenString, "Bearer ") 144 tokenString = strings.TrimPrefix(tokenString, "Bearer ")
145 } else { 145 } else {
146 return &TokenClaims{}, errors.New("Authorization header is incomplete") 146 return &TokenClaims{}, errors.New("Authorization header is incomplete")
147 } 147 }
148 148
149 token, err := jwt.ParseWithClaims(tokenString, &TokenClaims{}, secretFunc) 149 token, err := jwt.ParseWithClaims(tokenString, &TokenClaims{}, secretFunc)
150 if err != nil { 150 if err != nil {
151 return &TokenClaims{}, err 151 return &TokenClaims{}, err
152 } 152 }
153 153
154 // type assertion 154 // type assertion
155 claims, ok := token.Claims.(*TokenClaims) 155 claims, ok := token.Claims.(*TokenClaims)
156 if !ok || !token.Valid { 156 if !ok || !token.Valid {
157 return &TokenClaims{}, errors.New("token is not valid") 157 return &TokenClaims{}, errors.New("token is not valid")
158 } 158 }
159 return claims, nil 159 return claims, nil
160 } 160 }
161 161
162 func GetTokenClaims(r *http.Request) (claims *TokenClaims, err error) { 162 func GetTokenClaims(r *http.Request) (claims *TokenClaims, err error) {
163 token := r.Header.Get("Authorization") 163 token := r.Header.Get("Authorization")
164 if ok := strings.HasPrefix(token, "Bearer "); ok { 164 if ok := strings.HasPrefix(token, "Bearer "); ok {
165 token = strings.TrimPrefix(token, "Bearer ") 165 token = strings.TrimPrefix(token, "Bearer ")
166 } else { 166 } else {
167 return &TokenClaims{}, errors.New("Authorization header is incomplete") 167 return &TokenClaims{}, errors.New("Authorization header is incomplete")
168 } 168 }
169 169
170 parsedToken, err := jwt.ParseWithClaims(token, &TokenClaims{}, secretFunc) 170 parsedToken, err := jwt.ParseWithClaims(token, &TokenClaims{}, secretFunc)
171 if err != nil { 171 if err != nil {
172 return &TokenClaims{}, err 172 return &TokenClaims{}, err
173 } 173 }
174 174
175 // type assertion 175 // type assertion
176 claims, ok := parsedToken.Claims.(*TokenClaims) 176 claims, ok := parsedToken.Claims.(*TokenClaims)
177 if !ok || !parsedToken.Valid { 177 if !ok || !parsedToken.Valid {
178 return &TokenClaims{}, errors.New("token is not valid") 178 return &TokenClaims{}, errors.New("token is not valid")
179 } 179 }
180 return claims, err 180 return claims, err
181 } 181 }
182 182
183 // secretFunc returns byte slice of API secret keyword. 183 // secretFunc returns byte slice of API secret keyword.
184 func secretFunc(token *jwt.Token) (interface{}, error) { 184 func secretFunc(token *jwt.Token) (interface{}, error) {
185 return []byte(secret), nil 185 return []byte(secret), nil
186 } 186 }
187 187
188 // roleAuthorized returns true if role from userClaims matches any of the authorizedRoles 188 // roleAuthorized returns true if role from userClaims matches any of the authorizedRoles
189 // or if authorizedRoles contains "*". 189 // or if authorizedRoles contains "*".
190 func roleAuthorized(authorizedRoles []string, userClaims *TokenClaims) bool { 190 func roleAuthorized(authorizedRoles []string, userClaims *TokenClaims) bool {
191 if userClaims == nil { 191 if userClaims == nil {
192 return false 192 return false
193 } 193 }
194 for _, r := range authorizedRoles { 194 for _, r := range authorizedRoles {
195 if userClaims.Role == r || r == "*" { 195 if userClaims.Role == r || r == "*" {
196 return true 196 return true
197 } 197 }
198 } 198 }
199 return false 199 return false
200 } 200 }
201 201
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "fmt"
4 "net/http" 5 "net/http"
5 "encoding/json" 6 "encoding/json"
6 "errors" 7 "errors"
7 "gopkg.in/rana/ora.v3"
8 "io" 8 "io"
9 "io/ioutil" 9 //"io/ioutil"
10 "sync" 10 "sync"
11
12 //"gopkg.in/rana/ora.v3"
13 "gopkg.in/rana/ora.v4"
11 ) 14 )
12 15
13 var mu = &sync.Mutex{} 16 var mu = &sync.Mutex{}
14 var payloads []payloadBuff 17 var payloads []payloadBuff
15 18
16 type LangMap map[string]map[string]string 19 type LangMap map[string]map[string]string
17 20
18 type Field struct { 21 type Field struct {
19 Parameter string `json:"param"` 22 Parameter string `json:"param"`
20 Type string `json:"type"` 23 Type string `json:"type"`
21 Visible bool `json:"visible"` 24 Visible bool `json:"visible"`
22 Editable bool `json:"editable"` 25 Editable bool `json:"editable"`
23 } 26 }
24 27
25 type CorrelationField struct { 28 type CorrelationField struct {
26 Result string `json:"result"` 29 Result string `json:"result"`
27 Elements []string `json:"elements"` 30 Elements []string `json:"elements"`
28 Type string `json:"type"` 31 Type string `json:"type"`
29 } 32 }
30 33
31 type Translation struct { 34 type Translation struct {
32 Language string `json:"language"` 35 Language string `json:"language"`
33 FieldsLabels map[string]string `json:"fieldsLabels"` 36 FieldsLabels map[string]string `json:"fieldsLabels"`
34 } 37 }
35 38
36 type payloadBuff struct { 39 type payloadBuff struct {
37 Type string `json:"tableType"` 40 Type string `json:"tableType"`
38 Method string `json:"method"` 41 Method string `json:"method"`
39 Params map[string]string `json:"params"` 42 Params map[string]string `json:"params"`
40 Lang []Translation `json:"lang"` 43 Lang []Translation `json:"lang"`
41 Fields []Field `json:"fields"` 44 Fields []Field `json:"fields"`
42 Correlations []CorrelationField `json:"correlationFields"` 45 Correlations []CorrelationField `json:"correlationFields"`
43 IdField string `json:"idField"` 46 IdField string `json:"idField"`
44 47
45 // Data can only hold slices of any type. It can't be used for itteration 48 // Data can only hold slices of any type. It can't be used for itteration
46 Data interface{} `json:"data"` 49 Data interface{} `json:"data"`
47 } 50 }
48 51
49 type Payload struct { 52 type Payload struct {
50 Method string `json:"method"` 53 Method string `json:"method"`
51 Params map[string]string `json:"params"` 54 Params map[string]string `json:"params"`
52 Lang []Translation `json:"lang"` 55 Lang []Translation `json:"lang"`
53 Fields []Field `json:"fields"` 56 Fields []Field `json:"fields"`
54 Correlations []CorrelationField `json:"correlationFields"` 57 Correlations []CorrelationField `json:"correlationFields"`
55 IdField string `json:"idField"` 58 IdField string `json:"idField"`
56 59
57 // Data can only hold slices of any type. It can't be used for itteration 60 // Data can only hold slices of any type. It can't be used for itteration
58 Data interface{} `json:"data"` 61 Data interface{} `json:"data"`
59 } 62 }
60 63
61 // NewPayload returs a payload sceleton for provided table. 64 // NewPayload returs a payload sceleton for provided table.
62 func NewPayload(r *http.Request, table string) Payload { 65 func NewPayload(r *http.Request, table string) Payload {
63 var pload Payload 66 var pload Payload
64 67
65 pload.Method = r.Method + " " + r.URL.Path 68 pload.Method = r.Method + " " + r.URL.Path
66 if table != "" { 69 if table != "" {
67 pload.Params = make(map[string]string, 0) 70 pload.Params = make(map[string]string, 0)
68 pload.Lang = translations(table) 71 pload.Lang = translations(table)
69 pload.Fields = fields(table) 72 pload.Fields = fields(table)
70 pload.IdField = id(table) 73 pload.IdField = id(table)
71 pload.Correlations = correlations(table) 74 pload.Correlations = correlations(table)
72 } 75 }
73 return pload 76 return pload
74 } 77 }
75 78
76 // DeliverPayload encodes payload to w. 79 // DeliverPayload encodes payload to w.
77 func DeliverPayload(w http.ResponseWriter, payload Payload) { 80 func DeliverPayload(w http.ResponseWriter, payload Payload) {
78 json.NewEncoder(w).Encode(payload) 81 json.NewEncoder(w).Encode(payload)
79 payload.Data = nil 82 payload.Data = nil
80 } 83 }
81 84
82 // translations returns a slice of translations for a payload/table of ptype type. 85 // translations returns a slice of translations for a payload/table of ptype type.
83 func translations(ptype string) []Translation { 86 func translations(ptype string) []Translation {
84 var translations []Translation 87 var translations []Translation
85 88
86 for _, pload := range payloads { 89 for _, pload := range payloads {
87 if pload.Type == ptype { 90 if pload.Type == ptype {
88 for _, t := range pload.Lang { 91 for _, t := range pload.Lang {
89 translations = append(translations, Translation{ 92 translations = append(translations, Translation{
90 Language: t.Language, 93 Language: t.Language,
91 FieldsLabels: t.FieldsLabels, 94 FieldsLabels: t.FieldsLabels,
92 }) 95 })
93 } 96 }
94 } 97 }
95 } 98 }
96 99
97 return translations 100 return translations
98 } 101 }
99 102
100 // fields returns a slice of fields for a payload/table of ptype type. 103 // fields returns a slice of fields for a payload/table of ptype type.
101 func fields(ptype string) []Field { 104 func fields(ptype string) []Field {
102 var fields []Field 105 var fields []Field
103 106
104 for _, pload := range payloads { 107 for _, pload := range payloads {
105 if pload.Type == ptype { 108 if pload.Type == ptype {
106 for _, f := range pload.Fields { 109 for _, f := range pload.Fields {
107 fields = append(fields, f) 110 fields = append(fields, f)
108 } 111 }
109 } 112 }
110 } 113 }
111 114
112 return fields 115 return fields
113 } 116 }
114 117
115 // id returns the name of ID field of a payload/table of ptype type. 118 // id returns the name of ID field of a payload/table of ptype type.
116 func id(ptype string) string { 119 func id(ptype string) string {
117 for _, pload := range payloads { 120 for _, pload := range payloads {
118 if pload.Type == ptype { 121 if pload.Type == ptype {
119 return pload.IdField 122 return pload.IdField
120 } 123 }
121 } 124 }
122 return "" 125 return ""
123 } 126 }
124 127
125 // correlations returns a slice of correlation fields for a payload/table of ptype type. 128 // correlations returns a slice of correlation fields for a payload/table of ptype type.
126 func correlations(ptype string) []CorrelationField { 129 func correlations(ptype string) []CorrelationField {
127 var corr []CorrelationField 130 var corr []CorrelationField
128 131
129 for _, pload := range payloads { 132 for _, pload := range payloads {
130 if pload.Type == ptype { 133 if pload.Type == ptype {
131 for _, c := range pload.Correlations { 134 for _, c := range pload.Correlations {
132 corr = append(corr, c) 135 corr = append(corr, c)
133 } 136 }
134 } 137 }
135 } 138 }
136 139
137 return corr 140 return corr
138 } 141 }
139 142
140 // InitTables loads all payloads in the payloads variable. 143 // InitTables loads all payloads in the payloads variable.
141 // Returns an error if it fails. 144 // Returns an error if it fails.
142 func InitTables(db *ora.Ses, project string) error { 145 func InitTables(db *ora.Ses, project string) error {
143 jsonbuf, _ := fetchJSON(db, EqualQuotes(project)) 146 jsonbuf, err := fetchJSON(db, project)
147 if err != nil {
148 return err
149 }
150
144 mu.Lock() 151 mu.Lock()
145 defer mu.Unlock() 152 defer mu.Unlock()
146 json.Unmarshal(jsonbuf, &payloads) 153 json.Unmarshal([]byte(jsonbuf), &payloads)
147 if len(payloads) == 0 { 154 if len(payloads) == 0 {
148 return errors.New("tables config is corrupt") 155 return errors.New("tables config is corrupt")
149 } 156 }
150 return nil 157 return nil
151 } 158 }
152 159
153 // fetchJSON returns a byte slice of JSON configuration file from TABLES_CONFIG table. 160 // fetchJSON returns a byte slice of JSON configuration file from TABLES_CONFIG table.
154 // Returns an error if it fails. 161 // Returns an error if it fails.
155 func fetchJSON(db *ora.Ses, project string) ([]byte, error) { 162 func fetchJSON(db *ora.Ses, project string) (string, error) {
156 stmt, err := db.Prep(`SELECT 163 stmt, err := db.Prep(`SELECT JSON_CLOB FROM TABLES_CONFIG WHERE PROJEKAT` + EqualQuotes(project), ora.S)
157 JSON_CLOB
158 FROM TABLES_CONFIG
159 WHERE PROJEKAT` + project, ora.S)
160 defer stmt.Close() 164 defer stmt.Close()
161
162 if err != nil { 165 if err != nil {
163 return nil, err 166 return "", err
164 } 167 }
168 fmt.Println("prep passes")
165 169
166 rset, err := stmt.Qry() 170 rset, err := stmt.Qry()
167 if err != nil { 171 if err != nil {
168 return nil, err 172 fmt.Println(err)
173 return "", err
169 } 174 }
175 fmt.Println("query passes")
170 176
171 bytes := make([]byte, 0) 177 var data string
172 if rset.Next() { 178 if rset.Next() {
173 lob := rset.Row[0].(io.Reader) 179 data = rset.Row[0].(string)
174 if lob != nil {
175 bytes, err = ioutil.ReadAll(lob)
176 if err != nil {
177 // TODO: Find a fix for this.
178 // Some weird streaming read/write LOB error.
179 // Ignore for now.
180 //return nil, err
181 }
182 } else {
183 return nil, errors.New("json config is null")
184 }
1 package webutility 1 package webutility
2 2
3 import "gopkg.in/rana/ora.v3" 3 //import "gopkg.in/rana/ora.v3"
4 import "gopkg.in/rana/ora.v4"
4 5
5 type ListOptions struct { 6 type ListOptions struct {
6 GlobalFilter bool `json:"globalFilter"` 7 GlobalFilter bool `json:"globalFilter"`
7 LocalFilters bool `json:"localFilters"` 8 LocalFilters bool `json:"localFilters"`
8 RemoteFilters bool `json:"remoteFilters"` 9 RemoteFilters bool `json:"remoteFilters"`
9 Pagination bool `json:"pagination"` 10 Pagination bool `json:"pagination"`
10 PageSize uint64 `json:"pageSize"` 11 PageSize uint64 `json:"pageSize"`
11 Pivot bool `json:"pivot"` 12 Pivot bool `json:"pivot"`
12 Detail bool `json:"detail"` 13 Detail bool `json:"detail"`
13 Total bool `json:"total"` 14 Total bool `json:"total"`
14 } 15 }
15 16
16 type ListFilter struct { 17 type ListFilter struct {
17 Position uint32 `json:"-"` 18 Position uint32 `json:"-"`
18 ObjectType string `json:"-"` 19 ObjectType string `json:"-"`
19 FiltersField string `json:"filtersField"` 20 FiltersField string `json:"filtersField"`
20 DefaultValues string `json:"defaultValues"` 21 DefaultValues string `json:"defaultValues"`
21 FiltersType string `json:"filtersType"` 22 FiltersType string `json:"filtersType"`
22 FiltersLabel string `json:"filtersLabel"` 23 FiltersLabel string `json:"filtersLabel"`
23 DropdownConfig Dropdown `json:"dropdownConfig"` 24 DropdownConfig Dropdown `json:"dropdownConfig"`
24 } 25 }
25 26
26 type Dropdown struct { 27 type Dropdown struct {
27 ObjectType string `json:"objectType"` 28 ObjectType string `json:"objectType"`
28 FiltersField string `json:"filtersField"` 29 FiltersField string `json:"filtersField"`
29 IDField string `json:"idField"` 30 IDField string `json:"idField"`
30 LabelField string `json:"labelField"` 31 LabelField string `json:"labelField"`
31 32
32 } 33 }
33 34
34 type ListGraph struct { 35 type ListGraph struct {
35 ObjectType string `json:"objectType"` 36 ObjectType string `json:"objectType"`
36 X string `json:"xField"` 37 X string `json:"xField"`
37 Y string `json:"yField"` 38 Y string `json:"yField"`
38 GroupField string `json:"groupField"` 39 GroupField string `json:"groupField"`
39 Label string `json:"label"` 40 Label string `json:"label"`
40 } 41 }
41 42
42 type ListActions struct { 43 type ListActions struct {
43 Create bool `json:"create"` 44 Create bool `json:"create"`
44 Update bool `json:"update"` 45 Update bool `json:"update"`
45 Delete bool `json:"delete"` 46 Delete bool `json:"delete"`
46 Export bool `json:"export"` 47 Export bool `json:"export"`
47 Print bool `json:"print"` 48 Print bool `json:"print"`
48 Graph bool `json:"graph"` 49 Graph bool `json:"graph"`
49 } 50 }
50 51
51 type ListNavNode struct { 52 type ListNavNode struct {
52 ObjectType string `json:"objectType"` 53 ObjectType string `json:"objectType"`
53 LabelField string `json:"label"` 54 LabelField string `json:"label"`
54 Icon string `json:"icon"` 55 Icon string `json:"icon"`
55 ParentObjectType string `json:"parentObjectType"` 56 ParentObjectType string `json:"parentObjectType"`
56 ParentIDField string `json:"parentIdField"` 57 ParentIDField string `json:"parentIdField"`
57 ParentFilterField string `json:"parentFilterField"` 58 ParentFilterField string `json:"parentFilterField"`
58 } 59 }
59 60
60 type ListParentNode struct { 61 type ListParentNode struct {
61 ObjectType string `json:"objectType"` 62 ObjectType string `json:"objectType"`
62 LabelField string `json:"labelField"` 63 LabelField string `json:"labelField"`
63 FilterField string `json:"filterField"` 64 FilterField string `json:"filterField"`
64 } 65 }
65 66
66 type ListPivot struct { 67 type ListPivot struct {
67 ObjectType string `json:"objectType"` 68 ObjectType string `json:"objectType"`
68 GroupField string `json:"groupField"` 69 GroupField string `json:"groupField"`
69 DistinctField string `json:"distinctField"` 70 DistinctField string `json:"distinctField"`
70 Value string `json:"valueField"` 71 Value string `json:"valueField"`
71 } 72 }
72 73
73 type ListDetails struct { 74 type ListDetails struct {
74 ObjectType string `json:"objectType"` 75 ObjectType string `json:"objectType"`
75 ParentObjectType string `json:"parentObjectType"` 76 ParentObjectType string `json:"parentObjectType"`
76 ParentFilterField string `json:"parentFilterField"` 77 ParentFilterField string `json:"parentFilterField"`
77 SingleDetail bool `json:"singleDetail"` 78 SingleDetail bool `json:"singleDetail"`
78 } 79 }
79 80
80 type ListConfig struct { 81 type ListConfig struct {
81 ObjectType string `json:"objectType"` 82 ObjectType string `json:"objectType"`
82 Title string `json:"title"` 83 Title string `json:"title"`
83 LazyLoad bool `json:"lazyLoad"` 84 LazyLoad bool `json:"lazyLoad"`
84 InlineEdit bool `json:"inlineEdit"` 85 InlineEdit bool `json:"inlineEdit"`
85 Options ListOptions `json:"options"` 86 Options ListOptions `json:"options"`
86 Filters []ListFilter `json:"defaultFilters"` 87 Filters []ListFilter `json:"defaultFilters"`
87 Graphs []ListGraph `json:"graphs"` 88 Graphs []ListGraph `json:"graphs"`
88 Actions ListActions `json:"actions"` 89 Actions ListActions `json:"actions"`
89 Parent []ListParentNode `json:"parent"` 90 Parent []ListParentNode `json:"parent"`
90 Navigation []ListNavNode `json:"navigation"` 91 Navigation []ListNavNode `json:"navigation"`
91 Pivots []ListPivot `json:"pivots"` 92 Pivots []ListPivot `json:"pivots"`
92 Details ListDetails `json:"details"` 93 Details ListDetails `json:"details"`
93 } 94 }
94 95
95 // GetListConfig returns list configuration for the provided object type for the front-end application 96 // GetListConfig returns list configuration for the provided object type for the front-end application
96 // or an error if it fails. 97 // or an error if it fails.
97 func GetListConfig(db *ora.Ses, objType string) (ListConfig, error) { 98 func GetListConfig(db *ora.Ses, objType string) (ListConfig, error) {
98 resp := newDefaultList(objType) 99 resp := newDefaultList(objType)
99 var err error 100 var err error
100 101
101 err = setListParams(db, &resp, objType) 102 err = setListParams(db, &resp, objType)
102 resp.Navigation, err = getListNavigation(db, objType) 103 resp.Navigation, err = getListNavigation(db, objType)
103 resp.Actions, err = getListActions(db, objType) 104 resp.Actions, err = getListActions(db, objType)
104 resp.Filters, err = getListFilters(db, objType) 105 resp.Filters, err = getListFilters(db, objType)
105 resp.Options, err = getListOptions(db, objType) 106 resp.Options, err = getListOptions(db, objType)
106 resp.Parent, err = getListParent(db, objType) 107 resp.Parent, err = getListParent(db, objType)
107 resp.Graphs, err = getListGraph(db, objType) 108 resp.Graphs, err = getListGraph(db, objType)
108 resp.Pivots, err = getListPivot(db, objType) 109 resp.Pivots, err = getListPivot(db, objType)
109 resp.Details, err = getListDetails(db, objType) 110 resp.Details, err = getListDetails(db, objType)
110 111
111 if err != nil { 112 if err != nil {
112 return ListConfig{}, err 113 return ListConfig{}, err
113 } 114 }
114 115
115 return resp, nil 116 return resp, nil
116 } 117 }
117 118
118 // GetListConfigObjectIDField takes in database connection and an object type and it returns the 119 // GetListConfigObjectIDField takes in database connection and an object type and it returns the
119 // ID field name for the provided object type. 120 // ID field name for the provided object type.
120 func GetListConfigObjectIDField(db *ora.Ses, otype string) string { 121 func GetListConfigObjectIDField(db *ora.Ses, otype string) string {
121 var resp string 122 var resp string
122 var err error 123 var err error
123 var stmt *ora.Stmt 124 var stmt *ora.Stmt
124 125
125 stmt, err = db.Prep(`SELECT 126 stmt, err = db.Prep(`SELECT
126 ID_FIELD 127 ID_FIELD
127 FROM LIST_CONFIG_ID_FIELD 128 FROM LIST_CONFIG_ID_FIELD
128 WHERE OBJECT_TYPE = '` + otype + `'`, 129 WHERE OBJECT_TYPE = '` + otype + `'`,
129 ora.S) 130 ora.S)
130 131
131 defer stmt.Close() 132 defer stmt.Close()
132 133
133 if err != nil { 134 if err != nil {
134 return "" 135 return ""
135 } 136 }
136 137
137 rset, err := stmt.Qry() 138 rset, err := stmt.Qry()
138 if rset.Next() { 139 if rset.Next() {
139 resp = rset.Row[0].(string) 140 resp = rset.Row[0].(string)
140 } 141 }
141 142
142 if rset.Err != nil { 143 if rset.Err() != nil {
143 return "" 144 return ""
144 } 145 }
145 146
146 return resp 147 return resp
147 } 148 }
148 149
149 // newDefaultList returns default configuration for the provided object type. 150 // newDefaultList returns default configuration for the provided object type.
150 func newDefaultList(objType string) ListConfig { 151 func newDefaultList(objType string) ListConfig {
151 list := ListConfig{ 152 list := ListConfig{
152 ObjectType: objType, 153 ObjectType: objType,
153 Title: objType, 154 Title: objType,
154 LazyLoad: false, 155 LazyLoad: false,
155 Options: ListOptions{ 156 Options: ListOptions{
156 GlobalFilter: true, 157 GlobalFilter: true,
157 LocalFilters: true, 158 LocalFilters: true,
158 RemoteFilters: false, 159 RemoteFilters: false,
159 Pagination: true, 160 Pagination: true,
160 PageSize: 20, 161 PageSize: 20,
161 }, 162 },
162 Filters: nil, 163 Filters: nil,
163 Actions: ListActions{ 164 Actions: ListActions{
164 Create: false, 165 Create: false,
165 Update: false, 166 Update: false,
166 Delete: false, 167 Delete: false,
167 Export: false, 168 Export: false,
168 Print: false, 169 Print: false,
169 Graph: false, 170 Graph: false,
170 }, 171 },
171 Parent: nil, 172 Parent: nil,
172 Navigation: nil, 173 Navigation: nil,
173 } 174 }
174 175
175 return list 176 return list
176 } 177 }
177 178
178 // setListParams sets the default parameters of the provided configuration list for the provided object type. 179 // setListParams sets the default parameters of the provided configuration list for the provided object type.
179 func setListParams(db *ora.Ses, list *ListConfig, objType string) error { 180 func setListParams(db *ora.Ses, list *ListConfig, objType string) error {
180 var err error 181 var err error
181 var stmt *ora.Stmt 182 var stmt *ora.Stmt
182 query := `SELECT 183 query := `SELECT
183 OBJECT_TYPE, TITLE, LAZY_LOAD, INLINE_EDIT 184 OBJECT_TYPE, TITLE, LAZY_LOAD, INLINE_EDIT
184 FROM LIST_CONFIG 185 FROM LIST_CONFIG
185 WHERE OBJECT_TYPE = '` + objType + `'` 186 WHERE OBJECT_TYPE = '` + objType + `'`
186 187
187 stmt, err = db.Prep(query, ora.S, ora.S, ora.U32, ora.U32) 188 stmt, err = db.Prep(query, ora.S, ora.S, ora.U32, ora.U32)
188 if err != nil { 189 if err != nil {
189 return err 190 return err
190 } 191 }
191 defer stmt.Close() 192 defer stmt.Close()
192 193
193 rset, err := stmt.Qry() 194 rset, err := stmt.Qry()
194 if err != nil { 195 if err != nil {
195 return err 196 return err
196 } 197 }
197 if rset.Next() { 198 if rset.Next() {
198 otype := rset.Row[0].(string) 199 otype := rset.Row[0].(string)
199 if otype != "" { 200 if otype != "" {
200 list.ObjectType = otype 201 list.ObjectType = otype
201 } 202 }
202 203
203 title := rset.Row[1].(string) 204 title := rset.Row[1].(string)
204 if title != "" { 205 if title != "" {
205 list.Title = title 206 list.Title = title
206 } 207 }
207 list.LazyLoad = rset.Row[2].(uint32) != 0 208 list.LazyLoad = rset.Row[2].(uint32) != 0
208 list.InlineEdit = rset.Row[3].(uint32) != 0 209 list.InlineEdit = rset.Row[3].(uint32) != 0
209 } 210 }
210 if rset.Err != nil { 211 if rset.Err() != nil {
211 return rset.Err 212 return rset.Err()
212 } 213 }
213 return nil 214 return nil
214 } 215 }
215 216
216 // getListNavigation returns list navigation node slice for the provided objectType. 217 // getListNavigation returns list navigation node slice for the provided objectType.
217 func getListNavigation(db *ora.Ses, listObjType string) ([]ListNavNode, error) { 218 func getListNavigation(db *ora.Ses, listObjType string) ([]ListNavNode, error) {
218 resp := make([]ListNavNode, 0) 219 resp := make([]ListNavNode, 0)
219 var err error 220 var err error
220 var stmt *ora.Stmt 221 var stmt *ora.Stmt
221 query := `SELECT 222 query := `SELECT
222 a.OBJECT_TYPE, a.PARENT_OBJECT_TYPE, a.LABEL, a.ICON, a.PARENT_FILTER_FIELD, b.PARENT_ID_FIELD, b.RB 223 a.OBJECT_TYPE, a.PARENT_OBJECT_TYPE, a.LABEL, a.ICON, a.PARENT_FILTER_FIELD, b.PARENT_ID_FIELD, b.RB
223 FROM LIST_CONFIG_NAVIGATION b 224 FROM LIST_CONFIG_NAVIGATION b
224 JOIN LIST_CONFIG_CHILD a ON b.PARENT_CHILD_ID = a.PARENT_CHILD_ID 225 JOIN LIST_CONFIG_CHILD a ON b.PARENT_CHILD_ID = a.PARENT_CHILD_ID
225 WHERE b.LIST_OBJECT_TYPE = '`+listObjType+`' 226 WHERE b.LIST_OBJECT_TYPE = '`+listObjType+`'
226 ORDER BY b.RB ASC` 227 ORDER BY b.RB ASC`
227 228
228 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S, ora.S) 229 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S, ora.S)
229 if err != nil { 230 if err != nil {
230 return resp, err 231 return resp, err
231 } 232 }
232 defer stmt.Close() 233 defer stmt.Close()
233 234
234 rset, err := stmt.Qry() 235 rset, err := stmt.Qry()
235 if err != nil { 236 if err != nil {
236 return resp, err 237 return resp, err
237 } 238 }
238 for rset.Next() { 239 for rset.Next() {
239 resp = append(resp, ListNavNode{ 240 resp = append(resp, ListNavNode{
240 ObjectType: rset.Row[0].(string), 241 ObjectType: rset.Row[0].(string),
241 ParentObjectType: rset.Row[1].(string), 242 ParentObjectType: rset.Row[1].(string),
242 LabelField: rset.Row[2].(string), 243 LabelField: rset.Row[2].(string),
243 Icon: rset.Row[3].(string), 244 Icon: rset.Row[3].(string),
244 ParentFilterField: rset.Row[4].(string), 245 ParentFilterField: rset.Row[4].(string),
245 ParentIDField: rset.Row[5].(string), 246 ParentIDField: rset.Row[5].(string),
246 // RB is ignored 247 // RB is ignored
247 }) 248 })
248 } 249 }
249 if rset.Err != nil { 250 if rset.Err() != nil {
250 return nil, rset.Err 251 return nil, rset.Err()
251 } 252 }
252 253
253 return resp, nil 254 return resp, nil
254 } 255 }
255 256
256 // getListActions returns list actions for the provided object type. 257 // getListActions returns list actions for the provided object type.
257 func getListActions(db *ora.Ses, objType string) (ListActions, error) { 258 func getListActions(db *ora.Ses, objType string) (ListActions, error) {
258 var resp ListActions 259 var resp ListActions
259 var err error 260 var err error
260 var stmt *ora.Stmt 261 var stmt *ora.Stmt
261 query := `SELECT 262 query := `SELECT
262 ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE, ACTION_EXPORT, 263 ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE, ACTION_EXPORT,
263 ACTION_PRINT, ACTION_GRAPH 264 ACTION_PRINT, ACTION_GRAPH
264 FROM LIST_CONFIG 265 FROM LIST_CONFIG
265 WHERE OBJECT_TYPE = '` + objType + `'` 266 WHERE OBJECT_TYPE = '` + objType + `'`
266 267
267 stmt, err = db.Prep(query, ora.U32, ora.U32, ora.U32, ora.U32, 268 stmt, err = db.Prep(query, ora.U32, ora.U32, ora.U32, ora.U32,
268 ora.U32, ora.U32) 269 ora.U32, ora.U32)
269 if err != nil { 270 if err != nil {
270 return ListActions{}, err 271 return ListActions{}, err
271 } 272 }
272 defer stmt.Close() 273 defer stmt.Close()
273 274
274 rset, err := stmt.Qry() 275 rset, err := stmt.Qry()
275 if err != nil { 276 if err != nil {
276 return ListActions{}, err 277 return ListActions{}, err
277 } 278 }
278 if rset.Next() { 279 if rset.Next() {
279 resp.Create = rset.Row[0].(uint32) != 0 280 resp.Create = rset.Row[0].(uint32) != 0
280 resp.Update = rset.Row[1].(uint32) != 0 281 resp.Update = rset.Row[1].(uint32) != 0
281 resp.Delete = rset.Row[2].(uint32) != 0 282 resp.Delete = rset.Row[2].(uint32) != 0
282 resp.Export = rset.Row[3].(uint32) != 0 283 resp.Export = rset.Row[3].(uint32) != 0
283 resp.Print = rset.Row[4].(uint32) != 0 284 resp.Print = rset.Row[4].(uint32) != 0
284 resp.Graph = rset.Row[5].(uint32) != 0 285 resp.Graph = rset.Row[5].(uint32) != 0
285 } 286 }
286 if rset.Err != nil { 287 if rset.Err() != nil {
287 return ListActions{}, rset.Err 288 return ListActions{}, rset.Err()
288 } 289 }
289 return resp, nil 290 return resp, nil
290 } 291 }
291 292
292 // getListFiters returns list filter slice for the provided object type. 293 // getListFiters returns list filter slice for the provided object type.
293 func getListFilters(db *ora.Ses, objType string) ([]ListFilter, error) { 294 func getListFilters(db *ora.Ses, objType string) ([]ListFilter, error) {
294 resp := make([]ListFilter, 0) 295 resp := make([]ListFilter, 0)
295 filtersFields, err := getFilterFieldsAndPosition(db, objType) 296 filtersFields, err := getFilterFieldsAndPosition(db, objType)
296 if err != nil { 297 if err != nil {
297 return nil, err 298 return nil, err
298 } 299 }
299 for field, pos := range filtersFields { 300 for field, pos := range filtersFields {
300 filters, _ := getFiltersByFilterField(db, field) 301 filters, _ := getFiltersByFilterField(db, field)
301 for _, filter := range filters { 302 for _, filter := range filters {
302 var f ListFilter 303 var f ListFilter
303 f.Position = pos 304 f.Position = pos
304 f.ObjectType = objType 305 f.ObjectType = objType
305 f.FiltersField = field 306 f.FiltersField = field
306 f.DefaultValues = filter.DefaultValues 307 f.DefaultValues = filter.DefaultValues
307 f.FiltersLabel = filter.Label 308 f.FiltersLabel = filter.Label
308 f.FiltersType = filter.Type 309 f.FiltersType = filter.Type
309 if filter.Type == "dropdown" { 310 if filter.Type == "dropdown" {
310 f.DropdownConfig, err = getFilterDropdownConfig(db, field) 311 f.DropdownConfig, err = getFilterDropdownConfig(db, field)
311 if err != nil { 312 if err != nil {
312 return nil, err 313 return nil, err
313 } 314 }
314 } 315 }
315 resp = append(resp, f) 316 resp = append(resp, f)
316 } 317 }
317 } 318 }
318 319
319 sortFilters(resp) 320 sortFilters(resp)
320 321
321 return resp, nil 322 return resp, nil
322 } 323 }
323 324
324 // getFilterFieldsAndPosition returns a map of filter fields and their respective position in the menu. 325 // getFilterFieldsAndPosition returns a map of filter fields and their respective position in the menu.
325 func getFilterFieldsAndPosition(db *ora.Ses, objType string) (map[string]uint32, error) { 326 func getFilterFieldsAndPosition(db *ora.Ses, objType string) (map[string]uint32, error) {
326 filtersField := make(map[string]uint32, 0) 327 filtersField := make(map[string]uint32, 0)
327 var err error 328 var err error
328 var stmt *ora.Stmt 329 var stmt *ora.Stmt
329 query := `SELECT 330 query := `SELECT
330 FILTERS_FIELD, RB 331 FILTERS_FIELD, RB
331 FROM LIST_CONFIG_FILTERS 332 FROM LIST_CONFIG_FILTERS
332 WHERE OBJECT_TYPE = '` + objType + `'` 333 WHERE OBJECT_TYPE = '` + objType + `'`
333 334
334 stmt, err = db.Prep(query, ora.S, ora.U32) 335 stmt, err = db.Prep(query, ora.S, ora.U32)
335 if err != nil { 336 if err != nil {
336 return nil, err 337 return nil, err
337 } 338 }
338 defer stmt.Close() 339 defer stmt.Close()
339 340
340 rset, err := stmt.Qry() 341 rset, err := stmt.Qry()
341 if err != nil { 342 if err != nil {
342 return nil, err 343 return nil, err
343 } 344 }
344 for rset.Next() { 345 for rset.Next() {
345 filtersField[rset.Row[0].(string)] = rset.Row[1].(uint32) 346 filtersField[rset.Row[0].(string)] = rset.Row[1].(uint32)
346 } 347 }
347 if rset.Err != nil { 348 if rset.Err() != nil {
348 return nil, rset.Err 349 return nil, rset.Err()
349 } 350 }
350 return filtersField, nil 351 return filtersField, nil
351 } 352 }
352 353
353 type _filter struct { 354 type _filter struct {
354 DefaultValues string 355 DefaultValues string
355 Label string 356 Label string
356 Type string 357 Type string
357 } 358 }
358 359
359 // getFiltersByFilterField returns filter slice for the provided filter field. 360 // getFiltersByFilterField returns filter slice for the provided filter field.
360 func getFiltersByFilterField(db *ora.Ses, filtersField string) ([]_filter, error) { 361 func getFiltersByFilterField(db *ora.Ses, filtersField string) ([]_filter, error) {
361 resp := make([]_filter, 0) 362 resp := make([]_filter, 0)
362 var err error 363 var err error
363 var stmt *ora.Stmt 364 var stmt *ora.Stmt
364 query := `SELECT 365 query := `SELECT
365 FILTERS_TYPE, FILTERS_LABEL, DEFAULT_VALUES 366 FILTERS_TYPE, FILTERS_LABEL, DEFAULT_VALUES
366 FROM LIST_FILTERS_FIELD 367 FROM LIST_FILTERS_FIELD
367 WHERE FILTERS_FIELD = '` + filtersField + `'` 368 WHERE FILTERS_FIELD = '` + filtersField + `'`
368 369
369 stmt, err = db.Prep(query, ora.S, ora.S, ora.S) 370 stmt, err = db.Prep(query, ora.S, ora.S, ora.S)
370 if err != nil { 371 if err != nil {
371 return resp, err 372 return resp, err
372 } 373 }
373 defer stmt.Close() 374 defer stmt.Close()
374 375
375 rset, err := stmt.Qry() 376 rset, err := stmt.Qry()
376 if err != nil { 377 if err != nil {
377 return resp, err 378 return resp, err
378 } 379 }
379 for rset.Next() { 380 for rset.Next() {
380 resp = append(resp, _filter{ 381 resp = append(resp, _filter{
381 Type: rset.Row[0].(string), 382 Type: rset.Row[0].(string),
382 Label: rset.Row[1].(string), 383 Label: rset.Row[1].(string),
383 DefaultValues: rset.Row[2].(string), 384 DefaultValues: rset.Row[2].(string),
384 }) 385 })
385 } 386 }
386 if rset.Err != nil { 387 if rset.Err() != nil {
387 return resp, rset.Err 388 return resp, rset.Err()
388 } 389 }
389 return resp, nil 390 return resp, nil
390 } 391 }
391 392
392 // getFilterDropdownConfig returns dropdown menu for the provided filter field. 393 // getFilterDropdownConfig returns dropdown menu for the provided filter field.
393 func getFilterDropdownConfig(db *ora.Ses, filtersField string) (Dropdown, error) { 394 func getFilterDropdownConfig(db *ora.Ses, filtersField string) (Dropdown, error) {
394 var resp Dropdown 395 var resp Dropdown
395 var err error 396 var err error
396 var stmt *ora.Stmt 397 var stmt *ora.Stmt
397 query := `SELECT 398 query := `SELECT
398 FILTERS_FIELD, OBJECT_TYPE, ID_FIELD, LABEL_FIELD 399 FILTERS_FIELD, OBJECT_TYPE, ID_FIELD, LABEL_FIELD
399 FROM LIST_DROPDOWN_FILTER 400 FROM LIST_DROPDOWN_FILTER
400 WHERE FILTERS_FIELD = '` + filtersField + `'` 401 WHERE FILTERS_FIELD = '` + filtersField + `'`
401 402
402 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S) 403 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S)
403 if err != nil { 404 if err != nil {
404 return resp, err 405 return resp, err
405 } 406 }
406 defer stmt.Close() 407 defer stmt.Close()
407 408
408 rset, err := stmt.Qry() 409 rset, err := stmt.Qry()
409 if err != nil { 410 if err != nil {
410 return resp, err 411 return resp, err
411 } 412 }
412 if rset.Next() { 413 if rset.Next() {
413 resp.FiltersField = rset.Row[0].(string) 414 resp.FiltersField = rset.Row[0].(string)
414 resp.ObjectType = rset.Row[1].(string) 415 resp.ObjectType = rset.Row[1].(string)
415 resp.IDField = rset.Row[2].(string) 416 resp.IDField = rset.Row[2].(string)
416 resp.LabelField = rset.Row[3].(string) 417 resp.LabelField = rset.Row[3].(string)
417 } 418 }
418 if rset.Err != nil { 419 if rset.Err() != nil {
419 return resp, rset.Err 420 return resp, rset.Err()
420 } 421 }
421 return resp, nil 422 return resp, nil
422 } 423 }
423 424
424 // sortFilters bubble sorts provided filters slice by position field. 425 // sortFilters bubble sorts provided filters slice by position field.
425 func sortFilters(filters []ListFilter) { 426 func sortFilters(filters []ListFilter) {
426 done := false 427 done := false
427 var temp ListFilter 428 var temp ListFilter
428 for !done { 429 for !done {
429 done = true 430 done = true
430 for i := 0; i < len(filters) - 1; i++ { 431 for i := 0; i < len(filters) - 1; i++ {
431 if filters[i].Position > filters[i+1].Position { 432 if filters[i].Position > filters[i+1].Position {
432 done = false 433 done = false
433 temp = filters[i] 434 temp = filters[i]
434 filters[i] = filters[i+1] 435 filters[i] = filters[i+1]
435 filters[i+1] = temp 436 filters[i+1] = temp
436 } 437 }
437 } 438 }
438 } 439 }
439 } 440 }
440 441
441 // getListGraph return list graph slice for the provided object type. 442 // getListGraph return list graph slice for the provided object type.
442 func getListGraph(db *ora.Ses, objType string) ([]ListGraph, error) { 443 func getListGraph(db *ora.Ses, objType string) ([]ListGraph, error) {
443 resp := make([]ListGraph, 0) 444 resp := make([]ListGraph, 0)
444 var err error 445 var err error
445 var stmt *ora.Stmt 446 var stmt *ora.Stmt
446 query := `SELECT 447 query := `SELECT
447 OBJECT_TYPE, X_FIELD, Y_FIELD, GROUP_FIELD, LABEL 448 OBJECT_TYPE, X_FIELD, Y_FIELD, GROUP_FIELD, LABEL
448 FROM LIST_GRAPHS 449 FROM LIST_GRAPHS
449 WHERE OBJECT_TYPE = '` + objType + `'` 450 WHERE OBJECT_TYPE = '` + objType + `'`
450 451
451 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S) 452 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S)
452 if err != nil { 453 if err != nil {
453 return resp, err 454 return resp, err
454 } 455 }
455 defer stmt.Close() 456 defer stmt.Close()
456 457
457 rset, err := stmt.Qry() 458 rset, err := stmt.Qry()
458 if err != nil { 459 if err != nil {
459 return resp, err 460 return resp, err
460 } 461 }
461 for rset.Next() { 462 for rset.Next() {
462 resp = append(resp, ListGraph{ 463 resp = append(resp, ListGraph{
463 ObjectType: rset.Row[0].(string), 464 ObjectType: rset.Row[0].(string),
464 X: rset.Row[1].(string), 465 X: rset.Row[1].(string),
465 Y: rset.Row[2].(string), 466 Y: rset.Row[2].(string),
466 GroupField: rset.Row[3].(string), 467 GroupField: rset.Row[3].(string),
467 Label: rset.Row[4].(string), 468 Label: rset.Row[4].(string),
468 }) 469 })
469 } 470 }
470 if rset.Err != nil { 471 if rset.Err() != nil {
471 return resp, rset.Err 472 return resp, rset.Err()
472 } 473 }
473 return resp, nil 474 return resp, nil
474 } 475 }
475 476
476 // getListOptions returns list options for the provided object type. 477 // getListOptions returns list options for the provided object type.
477 func getListOptions(db *ora.Ses, objType string) (ListOptions, error) { 478 func getListOptions(db *ora.Ses, objType string) (ListOptions, error) {
478 var resp ListOptions 479 var resp ListOptions
479 var err error 480 var err error
480 var stmt *ora.Stmt 481 var stmt *ora.Stmt
481 query := `SELECT 482 query := `SELECT
482 GLOBAL_FILTER, LOCAL_FILTER, REMOTE_FILTER, PAGINATION, 483 GLOBAL_FILTER, LOCAL_FILTER, REMOTE_FILTER, PAGINATION,
483 PAGE_SIZE, PIVOT, DETAIL, TOTAL 484 PAGE_SIZE, PIVOT, DETAIL, TOTAL
484 FROM LIST_CONFIG 485 FROM LIST_CONFIG
485 WHERE OBJECT_TYPE = '` + objType + `'` 486 WHERE OBJECT_TYPE = '` + objType + `'`
486 487
487 stmt, err = db.Prep(query, ora.U32, ora.U32, ora.U32, ora.U32, 488 stmt, err = db.Prep(query, ora.U32, ora.U32, ora.U32, ora.U32,
488 ora.U64, ora.U64, ora.U32, ora.U32) 489 ora.U64, ora.U64, ora.U32, ora.U32)
489 if err != nil { 490 if err != nil {
490 return ListOptions{}, err 491 return ListOptions{}, err
491 } 492 }
492 defer stmt.Close() 493 defer stmt.Close()
493 494
494 rset, err := stmt.Qry() 495 rset, err := stmt.Qry()
495 if err != nil { 496 if err != nil {
496 return ListOptions{}, err 497 return ListOptions{}, err
497 } 498 }
498 if rset.Next() { 499 if rset.Next() {
499 resp.GlobalFilter = rset.Row[0].(uint32) != 0 500 resp.GlobalFilter = rset.Row[0].(uint32) != 0
500 resp.LocalFilters = rset.Row[1].(uint32) != 0 501 resp.LocalFilters = rset.Row[1].(uint32) != 0
501 resp.RemoteFilters = rset.Row[2].(uint32) != 0 502 resp.RemoteFilters = rset.Row[2].(uint32) != 0
502 resp.Pagination = rset.Row[3].(uint32) != 0 503 resp.Pagination = rset.Row[3].(uint32) != 0
503 resp.PageSize = rset.Row[4].(uint64) 504 resp.PageSize = rset.Row[4].(uint64)
504 resp.Pivot = rset.Row[5].(uint64) != 0 505 resp.Pivot = rset.Row[5].(uint64) != 0
505 resp.Detail = rset.Row[6].(uint32) != 0 506 resp.Detail = rset.Row[6].(uint32) != 0
506 resp.Total = rset.Row[7].(uint32) != 0 507 resp.Total = rset.Row[7].(uint32) != 0
507 } 508 }
508 if rset.Err != nil { 509 if rset.Err() != nil {
509 return ListOptions{}, rset.Err 510 return ListOptions{}, rset.Err()
510 } 511 }
511 return resp, nil 512 return resp, nil
512 } 513 }
513 514
514 // getListParent returns list parent node slice for the provided object type. 515 // getListParent returns list parent node slice for the provided object type.
515 func getListParent(db *ora.Ses, objType string) ([]ListParentNode, error) { 516 func getListParent(db *ora.Ses, objType string) ([]ListParentNode, error) {
516 resp := make([]ListParentNode, 0) 517 resp := make([]ListParentNode, 0)
517 var err error 518 var err error
518 var stmt *ora.Stmt 519 var stmt *ora.Stmt
519 query := `SELECT 520 query := `SELECT
520 PARENT_OBJECT_TYPE, PARENT_LABEL_FIELD, PARENT_FILTER_FIELD 521 PARENT_OBJECT_TYPE, PARENT_LABEL_FIELD, PARENT_FILTER_FIELD
521 FROM LIST_CONFIG_CHILD 522 FROM LIST_CONFIG_CHILD
522 WHERE OBJECT_TYPE = '` + objType + `'` 523 WHERE OBJECT_TYPE = '` + objType + `'`
523 524
524 stmt, err = db.Prep(query, ora.S, ora.S, ora.S) 525 stmt, err = db.Prep(query, ora.S, ora.S, ora.S)
525 if err != nil { 526 if err != nil {
526 return resp, err 527 return resp, err
527 } 528 }
528 defer stmt.Close() 529 defer stmt.Close()
529 530
530 rset, err := stmt.Qry() 531 rset, err := stmt.Qry()
531 if err != nil { 532 if err != nil {
532 return resp, err 533 return resp, err
533 } 534 }
534 for rset.Next() { 535 for rset.Next() {
535 resp = append(resp, ListParentNode{ 536 resp = append(resp, ListParentNode{
536 ObjectType: rset.Row[0].(string), 537 ObjectType: rset.Row[0].(string),
537 LabelField: rset.Row[1].(string), 538 LabelField: rset.Row[1].(string),
538 FilterField: rset.Row[2].(string), 539 FilterField: rset.Row[2].(string),
539 }) 540 })
540 } 541 }
541 if rset.Err != nil { 542 if rset.Err() != nil {
542 return nil, rset.Err 543 return nil, rset.Err()
543 } 544 }
544 545
545 return resp, nil 546 return resp, nil
546 } 547 }
547 548
548 // getListPivot list pivot slice for the provided object type. 549 // getListPivot list pivot slice for the provided object type.
549 func getListPivot(db *ora.Ses, objType string) ([]ListPivot, error) { 550 func getListPivot(db *ora.Ses, objType string) ([]ListPivot, error) {
550 resp := make([]ListPivot, 0) 551 resp := make([]ListPivot, 0)
551 var err error 552 var err error
552 var stmt *ora.Stmt 553 var stmt *ora.Stmt
553 query := `SELECT 554 query := `SELECT
554 OBJECT_TYPE, GROUP_FIELD, DISTINCT_FIELD, VALUE_FIELD 555 OBJECT_TYPE, GROUP_FIELD, DISTINCT_FIELD, VALUE_FIELD
555 FROM LIST_PIVOTS 556 FROM LIST_PIVOTS
556 WHERE OBJECT_TYPE = '` + objType + `'` 557 WHERE OBJECT_TYPE = '` + objType + `'`
557 558
558 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S) 559 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S)
559 if err != nil { 560 if err != nil {
560 return resp, err 561 return resp, err
561 } 562 }
562 defer stmt.Close() 563 defer stmt.Close()
563 564
564 rset, err := stmt.Qry() 565 rset, err := stmt.Qry()
565 if err != nil { 566 if err != nil {
566 return resp, err 567 return resp, err
567 } 568 }
568 for rset.Next() { 569 for rset.Next() {
569 resp = append(resp, ListPivot{ 570 resp = append(resp, ListPivot{
570 ObjectType: rset.Row[0].(string), 571 ObjectType: rset.Row[0].(string),
571 GroupField: rset.Row[1].(string), 572 GroupField: rset.Row[1].(string),
572 DistinctField: rset.Row[2].(string), 573 DistinctField: rset.Row[2].(string),
573 Value: rset.Row[3].(string), 574 Value: rset.Row[3].(string),
574 }) 575 })
575 } 576 }
576 if rset.Err != nil { 577 if rset.Err() != nil {
577 return nil, rset.Err 578 return nil, rset.Err()
578 } 579 }
579 580
580 return resp, nil 581 return resp, nil
581 } 582 }
582 583
583 // getListDetails returns list details for the provided object type. 584 // getListDetails returns list details for the provided object type.
584 func getListDetails(db *ora.Ses, objType string) (ListDetails, error) { 585 func getListDetails(db *ora.Ses, objType string) (ListDetails, error) {
585 var resp ListDetails 586 var resp ListDetails
586 var err error 587 var err error
587 var stmt *ora.Stmt 588 var stmt *ora.Stmt
588 query := `SELECT 589 query := `SELECT
589 OBJECT_TYPE, PARENT_OBJECT_TYPE, PARENT_FILTER_FIELD, SINGLE_DETAIL 590 OBJECT_TYPE, PARENT_OBJECT_TYPE, PARENT_FILTER_FIELD, SINGLE_DETAIL
590 FROM LIST_CONFIG_DETAIL 591 FROM LIST_CONFIG_DETAIL
591 WHERE PARENT_OBJECT_TYPE = '` + objType + `'` 592 WHERE PARENT_OBJECT_TYPE = '` + objType + `'`
592 593
593 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.U32) 594 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.U32)
594 if err != nil { 595 if err != nil {
595 return resp, err 596 return resp, err
596 } 597 }
597 defer stmt.Close() 598 defer stmt.Close()
598 599
599 rset, err := stmt.Qry() 600 rset, err := stmt.Qry()
600 if err != nil { 601 if err != nil {
601 return resp, err 602 return resp, err
602 } 603 }
603 if rset.Next() { 604 if rset.Next() {
604 resp.ObjectType = rset.Row[0].(string) 605 resp.ObjectType = rset.Row[0].(string)
605 resp.ParentObjectType = rset.Row[1].(string) 606 resp.ParentObjectType = rset.Row[1].(string)
606 resp.ParentFilterField = rset.Row[2].(string) 607 resp.ParentFilterField = rset.Row[2].(string)
607 resp.SingleDetail = rset.Row[3].(uint32) != 0 608 resp.SingleDetail = rset.Row[3].(uint32) != 0
608 } 609 }
609 if rset.Err != nil { 610 if rset.Err() != nil {
610 return resp, rset.Err 611 return resp, rset.Err()
611 } 612 }
612 613
613 return resp, nil 614 return resp, nil
614 } 615 }
615 616
1 package webutility 1 package webutility
2 2
3 import ( 3 //import "gopkg.in/rana/ora.v3"
4 "gopkg.in/rana/ora.v3" 4 import "gopkg.in/rana/ora.v4"
5 )
6 5
7 type SelectConfig struct { 6 type SelectConfig struct {
8 ListObjType string `json:"listObjectType"` 7 ListObjType string `json:"listObjectType"`
9 ObjType string `json:"objectType"` 8 ObjType string `json:"objectType"`
10 Type string `json:"type"` 9 Type string `json:"type"`
11 IdField string `json:"idField"` 10 IdField string `json:"idField"`
12 LabelField string `json:"labelField"` 11 LabelField string `json:"labelField"`
13 ValueField string `json:"valueField"` 12 ValueField string `json:"valueField"`
14 } 13 }
15 14
16 // GetSelectConfig returns select configuration slice for the given object type. 15 // GetSelectConfig returns select configuration slice for the given object type.
17 func GetSelectConfig(db *ora.Ses, otype string) ([]SelectConfig, error) { 16 func GetSelectConfig(db *ora.Ses, otype string) ([]SelectConfig, error) {
18 resp := make([]SelectConfig, 0) 17 resp := make([]SelectConfig, 0)
19 var err error 18 var err error
20 var stmt *ora.Stmt 19 var stmt *ora.Stmt
21 query := `SELECT a.LIST_OBJECT_TYPE, a.OBJECT_TYPE, a.ID_FIELD, 20 query := `SELECT a.LIST_OBJECT_TYPE, a.OBJECT_TYPE, a.ID_FIELD,
22 a.LABEL_FIELD, a.TYPE, b.FIELD 21 a.LABEL_FIELD, a.TYPE, b.FIELD
23 FROM LIST_SELECT_CONFIG a, LIST_VALUE_FIELD b 22 FROM LIST_SELECT_CONFIG a, LIST_VALUE_FIELD b
24 WHERE a.LIST_OBJECT_TYPE` + otype + ` 23 WHERE a.LIST_OBJECT_TYPE` + otype + `
25 AND b.LIST_TYPE = a.LIST_OBJECT_TYPE 24 AND b.LIST_TYPE = a.LIST_OBJECT_TYPE
26 AND b.OBJECT_TYPE = a.OBJECT_TYPE` 25 AND b.OBJECT_TYPE = a.OBJECT_TYPE`
27 26
28 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S, ora.S, ora.S) 27 stmt, err = db.Prep(query, ora.S, ora.S, ora.S, ora.S, ora.S, ora.S)
29 defer stmt.Close() 28 defer stmt.Close()
30 if err != nil { 29 if err != nil {
31 return nil, err 30 return nil, err
32 } 31 }
33 32
34 rset, err := stmt.Qry() 33 rset, err := stmt.Qry()
35 if err != nil { 34 if err != nil {
36 return nil, err 35 return nil, err
37 } 36 }
38 for rset.Next() { 37 for rset.Next() {
39 resp = append(resp, SelectConfig{ 38 resp = append(resp, SelectConfig{
40 ListObjType: rset.Row[0].(string), 39 ListObjType: rset.Row[0].(string),
41 ObjType: rset.Row[1].(string), 40 ObjType: rset.Row[1].(string),
42 IdField: rset.Row[2].(string), 41 IdField: rset.Row[2].(string),
43 LabelField: rset.Row[3].(string), 42 LabelField: rset.Row[3].(string),
44 Type: rset.Row[4].(string), 43 Type: rset.Row[4].(string),
45 ValueField: rset.Row[5].(string), 44 ValueField: rset.Row[5].(string),
46 }) 45 })
47 } 46 }
48 if rset.Err != nil { 47 if rset.Err() != nil {
49 return nil, rset.Err 48 return nil, rset.Err()
50 } 49 }
51 50
52 return resp, nil 51 return resp, nil
53 } 52 }
54 53