Commit 6ec91280b2993e3b3731c71a7d2a762f41f189eb

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

working on documentation

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