Mercurial > gemma
diff pkg/controllers/geostyling.go @ 871:f0b6852c14d1 geo-style
More on uploading styles to gemma.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sun, 30 Sep 2018 11:49:23 +0200 |
parents | 29c11f4bf9db |
children | ad9272460ef3 |
line wrap: on
line diff
--- 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 = `<?xml version="1.0"?> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:sld="http://www.opengis.net/sld" + xmlns:se="http://www.opengis.net/se"> + + <xsl:param name="name"/> + + <xsl:template + match="/sld:StyledLayerDescriptor/sld:NamedLayer/sld:Name/text()"> + <xsl:value-of select="$name"/> + </xsl:template> + + <xsl:template + match="/sld:StyledLayerDescriptor/sld:NamedLayer/se:Name/text()"> + <xsl:value-of select="$name"/> + </xsl:template> + + <xsl:template match="@*|node()"> + <xsl:copy> + <xsl:apply-templates select="@*|node()"/> + </xsl:copy> + </xsl:template> +</xsl:stylesheet>` + + 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 }