Mercurial > gemma
view pkg/controllers/printtemplates.go @ 5637:7f9600ab5461
merge
author | Thomas Junk <thomas.junk@intevation.de> |
---|---|
date | Wed, 14 Jun 2023 08:45:11 +0200 |
parents | 4394daeea96a |
children | 6270951dda28 |
line wrap: on
line source
// This is Free Software under GNU Affero General Public License v >= 3.0 // without warranty, see README.md and license for details. // // SPDX-License-Identifier: AGPL-3.0-or-later // License-Filename: LICENSES/AGPL-3.0.txt // // Copyright (C) 2018 by via donau // – Österreichische Wasserstraßen-Gesellschaft mbH // Software engineering by Intevation GmbH // // Author(s): // * Sascha L. Teichmann <sascha.teichmann@intevation.de> package controllers import ( "bytes" "database/sql" "encoding/json" "net/http" "strings" "time" "github.com/gorilla/mux" "github.com/jackc/pgx/pgtype" "gemma.intevation.de/gemma/pkg/models" mw "gemma.intevation.de/gemma/pkg/middleware" ) const maxPrintTemplateSize = 5 * 1024 * 1024 const ( listPrintTemplatesSQL = ` SELECT template_name, template_type::varchar, date_info, country FROM users.templates WHERE ` hasPrintTemplateSQL = ` SELECT true FROM users.templates WHERE template_name = $1 AND template_type = $2::template_types` deletePrintTemplateSQL = ` DELETE FROM users.templates WHERE template_name = $1 AND template_type = $2::template_types` selectPrintTemplateSQL = ` SELECT template_data FROM users.templates WHERE template_name = $1 AND template_type = $2::template_types` insertPrintTemplateSQL = ` INSERT INTO users.templates (template_name, template_type, template_data, country) SELECT $1, $2::template_types, $3, CASE WHEN pg_has_role('sys_admin', 'MEMBER') THEN NULL ELSE (SELECT country FROM users.list_users WHERE username = current_user) END` updatePrintTemplateSQL = ` UPDATE user.templates template_data = $2 WHERE template_name = $1 AND template_type = $2::template_types` ) var templateTypes = []string{"map", "diagram", "report"} func listPrintTemplates(req *http.Request) (jr mw.JSONResult, err error) { ts := mux.Vars(req)["type"] if ts == "" { if ts = req.FormValue("types"); ts == "" { ts = strings.Join(templateTypes, ",") } } types := toTextArray(ts, templateTypes) filter := buildFilterTerm("template_type = ANY($%d) ", types) var stmt strings.Builder var args []interface{} stmt.WriteString(listPrintTemplatesSQL) filter.serialize(&stmt, &args) stmt.WriteString(" ORDER BY date_info DESC") var rows *sql.Rows if rows, err = mw.JSONConn(req).QueryContext(req.Context(), stmt.String(), args...); err != nil { return } defer rows.Close() type template struct { Name string `json:"name"` Type string `json:"type"` Time models.Time `json:"time"` Country *string `json:"country,omitempty"` } templates := []*template{} for rows.Next() { var tmpl template var w time.Time var country sql.NullString if err = rows.Scan( &tmpl.Name, &tmpl.Type, &w, &country, ); err != nil { return } tmpl.Time = models.Time{Time: w} if country.Valid { tmpl.Country = &country.String } templates = append(templates, &tmpl) } jr = mw.JSONResult{Result: templates} return } func fetchPrintTemplate(req *http.Request) (jr mw.JSONResult, err error) { vars := mux.Vars(req) name, typ := vars["name"], vars["type"] ctx := req.Context() var data pgtype.Bytea err = mw.JSONConn(req).QueryRowContext(ctx, selectPrintTemplateSQL, name, typ).Scan(&data) switch { case err == sql.ErrNoRows: err = mw.JSONError{ Code: http.StatusNotFound, Message: "No such template found", } return case err != nil: return case data.Status != pgtype.Present: err = mw.JSONError{ Code: http.StatusInternalServerError, Message: "Unexpected return value from database query", } return } jr = mw.JSONResult{Result: bytes.NewReader(data.Bytes)} return } func createPrintTemplate(req *http.Request) (jr mw.JSONResult, err error) { vars := mux.Vars(req) name, typ := vars["name"], vars["type"] in := mw.JSONInput(req).(*json.RawMessage) if name == "" { err = mw.JSONError{ Code: http.StatusBadRequest, Message: "Template must have a none empty name", } return } if len(*in) == 0 { err = mw.JSONError{ Code: http.StatusBadRequest, Message: "Template must have a none empty template", } return } ctx := req.Context() var tx *sql.Tx if tx, err = mw.JSONConn(req).BeginTx(ctx, nil); err != nil { return } defer tx.Rollback() var dummy bool err = tx.QueryRowContext(ctx, hasPrintTemplateSQL, name, typ).Scan(&dummy) switch { case err == sql.ErrNoRows: // This is fine. case err != nil: return default: err = mw.JSONError{ Code: http.StatusBadRequest, Message: "A template with this name already exists", } return } data := pgtype.Bytea{Bytes: *in, Status: pgtype.Present} if _, err = tx.ExecContext(ctx, insertPrintTemplateSQL, name, typ, &data); err != nil { return } if err = tx.Commit(); err != nil { return } jr = mw.JSONResult{ Code: http.StatusCreated, Result: map[string]string{ "created": name, }, } return } func deletePrintTemplate(req *http.Request) (jr mw.JSONResult, err error) { vars := mux.Vars(req) name, typ := vars["name"], vars["type"] ctx := req.Context() var tx *sql.Tx if tx, err = mw.JSONConn(req).BeginTx(ctx, nil); err != nil { return } defer tx.Rollback() var dummy bool err = tx.QueryRowContext(ctx, hasPrintTemplateSQL, name, typ).Scan(&dummy) switch { case err == sql.ErrNoRows: err = mw.JSONError{ Code: http.StatusNotFound, Message: "No such template found", } return case err != nil: return case !dummy: err = mw.JSONError{ Code: http.StatusInternalServerError, Message: "Unexpected return value from database query", } return } if _, err = tx.ExecContext(ctx, deletePrintTemplateSQL, name, typ); err != nil { return } if err = tx.Commit(); err != nil { return } jr = mw.JSONResult{ Result: map[string]string{ "deleted": name, }, } return } func updatePrintTemplate(req *http.Request) (jr mw.JSONResult, err error) { vars := mux.Vars(req) name, typ := vars["name"], vars["type"] in := mw.JSONInput(req).(*json.RawMessage) if name == "" { err = mw.JSONError{ Code: http.StatusBadRequest, Message: "Template must have a none empty name", } return } if len(*in) == 0 { err = mw.JSONError{ Code: http.StatusBadRequest, Message: "Template must have a none empty template", } return } ctx := req.Context() var tx *sql.Tx if tx, err = mw.JSONConn(req).BeginTx(ctx, nil); err != nil { return } defer tx.Rollback() var dummy bool err = tx.QueryRowContext(ctx, hasPrintTemplateSQL, name, typ).Scan(&dummy) switch { case err == sql.ErrNoRows: err = mw.JSONError{ Code: http.StatusNotFound, Message: "No such template found", } return case err != nil: return case !dummy: err = mw.JSONError{ Code: http.StatusInternalServerError, Message: "Unexpected return value from database query", } return } data := pgtype.Bytea{Bytes: *in, Status: pgtype.Present} if _, err = tx.ExecContext(ctx, updatePrintTemplateSQL, name, typ, &data); err != nil { return } if err = tx.Commit(); err != nil { return } jr = mw.JSONResult{ Code: http.StatusOK, Result: map[string]string{ "updated": name, }, } return }