changeset 5386:fc3a5345b0fd extented-report

Added enpoint /api/data/stats-updates to list and trigger the stats update scripts. sys_admin only.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 01 Jul 2021 23:07:14 +0200
parents 7f5fc8ece589
children 8e30b926b94d
files pkg/controllers/routes.go pkg/controllers/statsupdates.go
diffstat 2 files changed, 125 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/controllers/routes.go	Thu Jul 01 22:19:38 2021 +0200
+++ b/pkg/controllers/routes.go	Thu Jul 01 23:07:14 2021 +0200
@@ -344,6 +344,17 @@
 	api.Handle("/data/report/{name:"+models.SafePathExp+"}", waterwayAdmin(
 		mw.DBConn(http.HandlerFunc(report)))).Methods(http.MethodGet)
 
+	// Handler for update scripts
+	api.Handle("/data/stats-updates",
+		sysAdmin(&mw.JSONHandler{
+			Handle: listStatsUpdates,
+		})).Methods(http.MethodGet)
+
+	api.Handle("/data/stats-updates/{name:.+}",
+		sysAdmin(&mw.JSONHandler{
+			Handle: statsUpdates,
+		})).Methods(http.MethodGet)
+
 	// Handler to serve data to the client.
 
 	api.Handle("/data/{type:availability|fairway}/{kind:stretch|section|bottleneck}/{name:.+}", any(
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkg/controllers/statsupdates.go	Thu Jul 01 23:07:14 2021 +0200
@@ -0,0 +1,114 @@
+// 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) 2021 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 (
+	"database/sql"
+	"log"
+	"net/http"
+
+	mw "gemma.intevation.de/gemma/pkg/middleware"
+	"github.com/gorilla/mux"
+)
+
+const (
+	listStatsUpdatesSQL   = `SELECT name FROM sys_admin.stats_updates ORDER BY name`
+	statsUpdatesScriptSQL = `SELECT script FROM sys_admin.stats_updates WHERE name = $1`
+)
+
+func listStatsUpdates(req *http.Request) (jr mw.JSONResult, err error) {
+
+	ctx := req.Context()
+	conn := mw.JSONConn(req)
+
+	rows, err2 := conn.QueryContext(ctx, listStatsUpdatesSQL)
+	if err2 != nil {
+		log.Printf("error: %v\n", err2)
+		err = mw.JSONError{
+			Code:    http.StatusInternalServerError,
+			Message: "Listing stats update failed.",
+		}
+		return
+	}
+	defer rows.Close()
+
+	names := []string{}
+
+	for rows.Next() {
+		var name string
+		if err2 := rows.Scan(&name); err2 != nil {
+			log.Printf("error: %v\n", err2)
+			err = mw.JSONError{
+				Code:    http.StatusInternalServerError,
+				Message: "Fetching stats update names failed.",
+			}
+			return
+		}
+		names = append(names, name)
+	}
+
+	if err2 := rows.Err(); err2 != nil {
+		log.Printf("error: %v\n", err2)
+		err = mw.JSONError{
+			Code:    http.StatusInternalServerError,
+			Message: "Fetching stats update names failed.",
+		}
+		return
+	}
+
+	out := struct {
+		StatsUpdates []string `json:"stats-updates"`
+	}{
+		StatsUpdates: names,
+	}
+	jr = mw.JSONResult{Result: out}
+	return
+}
+
+func statsUpdates(req *http.Request) (jr mw.JSONResult, err error) {
+	name := mux.Vars(req)["name"]
+
+	ctx := req.Context()
+	conn := mw.JSONConn(req)
+
+	var script string
+	err2 := conn.QueryRowContext(ctx, statsUpdatesScriptSQL, name).Scan(&script)
+	switch {
+	case err2 == sql.ErrNoRows:
+		err = mw.JSONError{
+			Code:    http.StatusNotFound,
+			Message: "No such update script.",
+		}
+		return
+	case err2 != nil:
+		log.Printf("error: %v\n", err2)
+		err = mw.JSONError{
+			Code:    http.StatusInternalServerError,
+			Message: "Loading update script failed.",
+		}
+		return
+	}
+
+	if _, err2 := conn.ExecContext(ctx, script); err2 != nil {
+		log.Printf("error: %v\n", err2)
+		err = mw.JSONError{
+			Code:    http.StatusInternalServerError,
+			Message: "Loading update script failed.",
+		}
+		return
+	}
+
+	jr = mw.JSONResult{Result: map[string]interface{}{}}
+	return
+}