# HG changeset patch # User Sascha L. Teichmann # Date 1538300963 -7200 # Node ID f0b6852c14d1e839386188afa34a9a48cded65a1 # Parent 29c11f4bf9db22c53ea954cadf67f937e9b972c4 More on uploading styles to gemma. diff -r 29c11f4bf9db -r f0b6852c14d1 pkg/controllers/geostyling.go --- a/pkg/controllers/geostyling.go Sat Sep 29 23:33:14 2018 +0200 +++ b/pkg/controllers/geostyling.go Sun Sep 30 11:49:23 2018 +0200 @@ -2,9 +2,16 @@ import ( "bytes" + "database/sql" + "fmt" "io" "log" "net/http" + "strings" + + "gemma.intevation.de/gemma/pkg/auth" + "gemma.intevation.de/gemma/pkg/models" + "github.com/gorilla/mux" ) const ( @@ -12,6 +19,65 @@ styleName = "style" ) +const ( + replaceNameXSLT = ` + + + + + + + + + + + + + + + + + +` + + xsltSQL = `SELECT xslt_process($1, $2, $3)` +) + +func runXSLT( + req *http.Request, + document, stylesheet string, + params ...string, +) (string, error) { + var result string + + var args strings.Builder + + for len(params) > 1 { + if args.Len() > 0 { + args.WriteByte(',') + } + fmt.Fprintf(&args, "%s='%s'", + strings.Replace(params[0], ",", "", -1), + strings.Replace(params[1], ",", "", -1)) + params = params[2:] + } + + log.Printf("params: %s\n", args.String()) + + err := auth.RunAsSessionUser(req, func(conn *sql.Conn) error { + return conn.QueryRowContext( + req.Context(), xsltSQL, + document, stylesheet, args.String()).Scan(&result) + }) + + return result, err +} + func extractStyle(req *http.Request) ([]byte, error) { f, _, err := req.FormFile(styleName) @@ -28,15 +94,46 @@ return buf.Bytes(), nil } +func supportedWMSFeature(name string) bool { + return len(models.InternalServices.Filter( + models.IntAnd(models.IntWMS, models.IntByName(name)))) > 0 +} + func uploadStyle(rw http.ResponseWriter, req *http.Request) { - data, err := extractStyle(req) + feature := mux.Vars(req)["feature"] + + // only allow internal WMS features + if !supportedWMSFeature(feature) { + http.Error(rw, + fmt.Sprintf("WMS feature %s is not found.", feature), + http.StatusNotFound) + return + } + + style, err := extractStyle(req) if err != nil { log.Printf("error: %v\n", err) http.Error(rw, "error: "+err.Error(), http.StatusBadRequest) return } - log.Printf("uploaded file length: %d\n", len(data)) - // TODO: Implement me! + log.Printf("uploaded file length: %d\n", len(style)) + + result, err := runXSLT( + req, string(style), replaceNameXSLT, "name", feature) + + if err != nil { + log.Printf("error: %v\n", err) + http.Error(rw, "error: "+err.Error(), http.StatusBadRequest) + return + } + + if err := models.UpdateInternalStyle(feature, result); err != nil { + log.Printf("error: %v\n", err) + http.Error(rw, "error: "+err.Error(), http.StatusInternalServerError) + return + } + + // TODO: Configure GeoServer } diff -r 29c11f4bf9db -r f0b6852c14d1 pkg/models/intservices.go --- a/pkg/models/intservices.go Sat Sep 29 23:33:14 2018 +0200 +++ b/pkg/models/intservices.go Sun Sep 30 11:49:23 2018 +0200 @@ -22,11 +22,30 @@ mu sync.Mutex } -const selectPublishedServices = `SELECT relname, style, as_wms, as_wfs +const ( + selectPublishedServices = `SELECT relname, style, as_wms, as_wfs FROM sys_admin.published_services JOIN pg_class ON name = oid ORDER by relname` + updateStyleSQL = ` +UPDATE sys_admin.published_services +SET style = $1 +WHERE name IN (SELECT oid FROM pg_class WHERE relname = $2)` +) + var InternalServices = &IntServices{} +func UpdateInternalStyle(name, style string) error { + return auth.RunAs("sys_admin", context.Background(), + func(conn *sql.Conn) error { + _, err := conn.ExecContext( + context.Background(), updateStyleSQL, style, name) + if err == nil { + InternalServices.Invalidate() + } + return err + }) +} + func (ps *IntServices) Find(name string) (string, bool) { ps.mu.Lock() defer ps.mu.Unlock() @@ -97,6 +116,14 @@ func IntWMS(entry IntEntry) bool { return entry.WMS } func IntWFS(entry IntEntry) bool { return entry.WFS } +func IntByName(name string) func(IntEntry) bool { + return func(entry IntEntry) bool { return entry.Name == name } +} + +func IntAnd(a, b func(IntEntry) bool) func(IntEntry) bool { + return func(entry IntEntry) bool { return a(entry) && b(entry) } +} + func (ps *IntServices) Filter(accept func(IntEntry) bool) []IntEntry { ps.mu.Lock() defer ps.mu.Unlock() diff -r 29c11f4bf9db -r f0b6852c14d1 schema/auth.sql --- a/schema/auth.sql Sat Sep 29 23:33:14 2018 +0200 +++ b/schema/auth.sql Sun Sep 30 11:49:23 2018 +0200 @@ -33,6 +33,7 @@ GRANT SELECT ON ALL TABLES IN SCHEMA sys_admin TO sys_admin; GRANT UPDATE ON sys_admin.system_config TO sys_admin; GRANT UPDATE ON systemconf.feature_colours TO sys_admin; +GRANT UPDATE ON sys_admin.published_services TO sys_admin; GRANT INSERT, DELETE ON sys_admin.password_reset_requests TO sys_admin; GRANT INSERT, DELETE, UPDATE ON waterway.sounding_results_contour_lines TO sys_admin; diff -r 29c11f4bf9db -r f0b6852c14d1 schema/gemma.sql --- a/schema/gemma.sql Sat Sep 29 23:33:14 2018 +0200 +++ b/schema/gemma.sql Sun Sep 30 11:49:23 2018 +0200 @@ -5,6 +5,8 @@ -- CREATE EXTENSION postgis; +CREATE EXTENSION xml2; + -- Needed for 3D processing e.g. for cross section profiles -- FIXME disabled for now, because not available on Ubuntu/Debian --CREATE EXTENSION postgis_sfcgal;