-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprocess.go
More file actions
239 lines (224 loc) · 7.37 KB
/
process.go
File metadata and controls
239 lines (224 loc) · 7.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"html/template"
"io"
"log"
"net/http"
"strings"
srvConfig "github.com/CHESSComputing/golib/config"
server "github.com/CHESSComputing/golib/server"
services "github.com/CHESSComputing/golib/services"
"github.com/gin-gonic/gin"
)
// helper function to clean query
func cleanQuery(query string) string {
q := strings.Replace(query, "\r", "", -1)
q = strings.Replace(query, "\n", "", -1)
return q
}
// check if query is valid JSON
func validJSON(query string) error {
if !strings.Contains(query, "{") {
return nil
}
var data map[string]any
err := json.Unmarshal([]byte(query), &data)
if err != nil {
return fmt.Errorf("[Frontend.main.validJSON] json.Unmarshal error: %w", err)
}
return nil
}
// helper function to process service request
func processResults(c *gin.Context, rec services.ServiceRequest, user string, idx, limit int, btrs []string) {
tmpl := server.MakeTmpl(StaticFs, "Search")
tmpl["Base"] = srvConfig.Config.Frontend.WebServer.Base
log.Printf("service request record\n%s", rec.String())
query := cleanQuery(rec.ServiceQuery.Query)
tmpl["Query"] = query
err1 := validJSON(query)
data, err2 := json.Marshal(rec)
if err1 != nil || err2 != nil {
tmpl["FixQuery"] = query
msg := "Given query is not valid JSON, error: "
err := err1
if err1 != nil {
msg += err1.Error()
} else if err2 != nil {
msg += err2.Error()
err = err2
}
tmpl["Content"] = msg
page := server.TmplPage(StaticFs, "query_error.tmpl", tmpl)
msg = string(template.HTML(page))
handleError(c, http.StatusBadRequest, msg, err)
return
}
// search request to DataDiscovery service
_httpReadRequest.GetToken()
rurl := fmt.Sprintf("%s/search", srvConfig.Config.Services.DiscoveryURL)
resp, err := _httpReadRequest.Post(rurl, "application/json", bytes.NewBuffer(data))
if err != nil {
msg := "unable to get meta-data from upstream server"
handleError(c, http.StatusInternalServerError, msg, err)
return
}
// parse data records from meta-data service
var response services.ServiceResponse
defer resp.Body.Close()
data, err = io.ReadAll(resp.Body)
if err != nil {
content := errorTmpl(c, "unable to read response body, error", err)
handleError(c, http.StatusBadRequest, content, err)
return
}
err = json.Unmarshal(data, &response)
if err != nil {
content := errorTmpl(c, "unable to unmarshal response, error", err)
handleError(c, http.StatusBadRequest, content, err)
return
}
if Verbose > 1 {
log.Printf("meta-data response\n%+v", response)
}
// return respose JSON if requested
if c.Request.Header.Get("Accept") == "application/json" {
c.JSON(http.StatusOK, response)
return
}
// otherwise create proper HTML
if response.Results.NRecords == 0 {
tmpl["Content"] = fmt.Sprintf("No records found for your query:\n<pre>%s</pre>", query)
page := server.TmplPage(StaticFs, "noresults.tmpl", tmpl)
c.Data(http.StatusOK, "text/html; charset=utf-8", []byte(header()+page+footerEmpty()))
return
}
records := response.Results.Records
nrecords := response.Results.NRecords
// extract userAttrs cookies which list which attributes to show in a record
var attrs2show []string
if cookie, err := c.Request.Cookie("userAttrs"); err == nil {
for _, v := range strings.Split(cookie.Value, ",") {
attrs2show = append(attrs2show, strings.Trim(v, " "))
}
}
content := records2html(user, records, attrs2show)
tmpl["Records"] = template.HTML(content)
sortKey := "date"
if len(rec.ServiceQuery.SortKeys) > 0 {
sortKey = rec.ServiceQuery.SortKeys[0]
}
sortOrder := "descending"
if rec.ServiceQuery.SortOrder == 1 {
sortOrder = "ascending"
}
pages := pagination(c, query, nrecords, idx, limit, sortKey, sortOrder, btrs)
tmpl["Pagination"] = template.HTML(pages)
page := server.TmplPage(StaticFs, "records.tmpl", tmpl)
// we will not use footer() on handlers since user may expand records
// instead we'll use footerEmpty() function
c.Data(http.StatusOK, "text/html; charset=utf-8", []byte(header()+page+footerEmpty()))
}
func findMetadataRecord(did string) (map[string]any, error) {
var record map[string]any
spec := make(map[string]any)
spec["did"] = did
rec := services.ServiceRequest{
Client: "frontend",
ServiceQuery: services.ServiceQuery{Spec: spec},
}
data, err := json.Marshal(rec)
if err != nil {
msg := "unable to get meta-data from upstream server"
return record, errors.New(msg)
}
// obtain valid token for read request
_httpReadRequest.GetToken()
rurl := fmt.Sprintf("%s/search", srvConfig.Config.Services.MetaDataURL)
resp, err := _httpReadRequest.Post(rurl, "application/json", bytes.NewBuffer(data))
if err != nil {
msg := "unable to get meta-data from upstream server"
return record, errors.New(msg)
}
var records []map[string]any
defer resp.Body.Close()
data, err = io.ReadAll(resp.Body)
if err != nil {
msg := "unable to read response body"
return record, errors.New(msg)
}
err = json.Unmarshal(data, &records)
if err != nil {
msg := "unable to unmarshal response from Metadata service"
return record, errors.New(msg)
}
if len(records) > 1 {
msg := fmt.Sprintf("multiple records found for did=%s, records=%+v", did, records)
return record, errors.New(msg)
} else if len(records) == 0 {
msg := fmt.Sprintf("no metadata record found for did=%s, records=%+v", did, records)
return record, errors.New(msg)
}
return records[0], nil
}
func findMetadataRecordsViaSpec(did string, spec map[string]any) ([]map[string]any, error) {
var records []map[string]any
rec := services.ServiceRequest{
Client: "frontend",
ServiceQuery: services.ServiceQuery{Spec: spec},
}
data, err := json.Marshal(rec)
if err != nil {
msg := "unable to get meta-data from upstream server"
return records, errors.New(msg)
}
// obtain valid token for read request
_httpReadRequest.GetToken()
rurl := fmt.Sprintf("%s/search", srvConfig.Config.Services.MetaDataURL)
resp, err := _httpReadRequest.Post(rurl, "application/json", bytes.NewBuffer(data))
if err != nil {
msg := "unable to get meta-data from upstream server"
return records, errors.New(msg)
}
defer resp.Body.Close()
data, err = io.ReadAll(resp.Body)
if err != nil {
msg := "unable to read response body"
return records, errors.New(msg)
}
err = json.Unmarshal(data, &records)
if err != nil {
msg := "unable to unmarshal response from Metadata service"
return records, errors.New(msg)
}
return records, nil
}
// helper function to update metadata record
func updateMetadataRecord(did string, rec map[string]any) error {
// obtain valid token for write request
_httpWriteRequest.GetToken()
schema := recValue(rec, "schema")
mrec := services.MetaRecord{Schema: schema, Record: rec}
// serialize data record
data, err := json.Marshal(mrec)
if err != nil {
return fmt.Errorf("[Frontend.main.updateMetadataRecord] json.Marshal error: %w", err)
}
// place request to Metadata service
rurl := fmt.Sprintf("%s", srvConfig.Config.Services.MetaDataURL)
resp, err := _httpWriteRequest.Put(rurl, "application/json", bytes.NewBuffer(data))
if err != nil || resp.StatusCode != 200 {
msg := "unable to update metadata record in FOXDEN server"
// read response body and add it to the message
defer resp.Body.Close()
if data, err = io.ReadAll(resp.Body); err == nil {
msg = fmt.Sprintf("%s, %s", msg, string(data))
}
log.Printf("ERROR: %s, response %+v, err %v", msg, resp, err)
return errors.New(msg)
}
return nil
}