Commit 1d0f615536520bf32f1acd061f7acf4a367e9bee
1 parent
f1f300b13c
Exists in
master
and in
1 other branch
can't fetch clob
Showing
4 changed files
with
51 additions
and
56 deletions
Show diff stats
auth_utility.go
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 |
json_utility.go
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 | } |
list_config.go
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 |
select_config.go
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 |