view pkg/controllers/routes.go @ 4962:1b309a8e7673 fairway-marks-import

Distinguish more clearly between BCNLAT HYDRO and IENC features This allows importing them from different sources while keeping the history of data intact. Additionally, storing them in different tables also allows to have different attributes (here only dirimp via an m:n-table) and different constraints (currently not implemented) according to the IENC feature catalogue. Since both new tables inherit from a table with the same name as the old table, all entries still can be accessed via a table of the same name. Thus, no changes to GeoServer layers are necessary. ToDo: solve layout problems in the client SPA.
author Tom Gottfried <tom@intevation.de>
date Thu, 27 Feb 2020 21:05:09 +0100
parents b3b2ba09a450
children 58dc06e91c39
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, 2020 by via donau
//   – Österreichische Wasserstraßen-Gesellschaft mbH
// Software engineering by Intevation GmbH
//
// Author(s):
//  * Sascha L. Teichmann <sascha.teichmann@intevation.de>
//  * Sascha Wilde <sascha.wilde@intevation.de>

package controllers

import (
	"encoding/json"
	"net/http"
	"net/http/httputil"
	"strings"

	"github.com/gorilla/mux"

	"gemma.intevation.de/gemma/pkg/auth"
	"gemma.intevation.de/gemma/pkg/imports"
	mw "gemma.intevation.de/gemma/pkg/middleware"
	"gemma.intevation.de/gemma/pkg/models"
)

// BindRoutes binds all the API endpoints to the exposed router.
func BindRoutes(m *mux.Router) {

	api := m.PathPrefix("/api").Subrouter()

	var (
		sysAdmin      = auth.EnsureRole("sys_admin")
		waterwayAdmin = auth.EnsureRole("waterway_admin")
		any           = auth.EnsureRole("sys_admin", "waterway_admin", "waterway_user")
	)

	// Password resets.
	api.Handle("/users/passwordreset", &mw.JSONHandler{
		Input:  func(*http.Request) interface{} { return new(models.PWResetUser) },
		Handle: passwordResetRequest,
		NoConn: true,
	}).Methods(http.MethodPost)

	api.HandleFunc("/users/passwordreset/{hash}", passwordReset).
		Methods(http.MethodGet)

	// User management.
	api.Handle("/users", any(&mw.JSONHandler{
		Handle: listUsers,
	})).Methods(http.MethodGet)

	api.Handle("/users", sysAdmin(&mw.JSONHandler{
		Input:  func(*http.Request) interface{} { return new(models.User) },
		Handle: createUser,
	})).Methods(http.MethodPost)

	api.Handle("/users/{user:.+}", any(&mw.JSONHandler{
		Handle: listUser,
	})).Methods(http.MethodGet)

	api.Handle("/users/{user:.+}", any(&mw.JSONHandler{
		Input:  func(*http.Request) interface{} { return new(models.User) },
		Handle: updateUser,
	})).Methods(http.MethodPut)

	api.Handle("/users/{user:.+}", sysAdmin(&mw.JSONHandler{
		Handle: deleteUser,
	})).Methods(http.MethodDelete)

	// System notifications
	api.Handle("/testmail/{user:.+}", sysAdmin(&mw.JSONHandler{
		Handle: sendTestMail,
	})).Methods(http.MethodGet)

	// System Management
	api.Handle("/system/log/{service}/{file}", sysAdmin(&mw.JSONHandler{
		Handle: showSystemLog,
		NoConn: true,
	})).Methods(http.MethodGet)

	// System Settings
	api.Handle("/system/config", any(&mw.JSONHandler{
		Handle: getSystemConfig,
		NoConn: true,
	})).Methods(http.MethodGet)

	api.Handle("/system/settings", any(&mw.JSONHandler{
		Handle: getSystemSettings,
	})).Methods(http.MethodGet)

	api.Handle("/system/settings", sysAdmin(&mw.JSONHandler{
		Input:  func(*http.Request) interface{} { return &map[string]string{} },
		Handle: setSystemSettings,
	})).Methods(http.MethodPut)

	// Print templates
	api.Handle("/templates", any(&mw.JSONHandler{
		Handle: listPrintTemplates,
	})).Methods(http.MethodGet)

	tTypes := "{type:" + strings.Join(templateTypes, "|") + "}"

	api.Handle("/templates/"+tTypes, any(&mw.JSONHandler{
		Handle: listPrintTemplates,
	})).Methods(http.MethodGet)

	api.Handle("/templates/"+tTypes+"/{name}", any(&mw.JSONHandler{
		Handle: fetchPrintTemplate,
	})).Methods(http.MethodGet)

	api.Handle("/templates/"+tTypes+"/{name}", waterwayAdmin(&mw.JSONHandler{
		Input:  func(*http.Request) interface{} { return &json.RawMessage{} },
		Handle: createPrintTemplate,
		Limit:  maxPrintTemplateSize,
	})).Methods(http.MethodPost)

	api.Handle("/templates/"+tTypes+"/{name}", waterwayAdmin(&mw.JSONHandler{
		Handle: deletePrintTemplate,
	})).Methods(http.MethodDelete)

	api.Handle("/templates/"+tTypes+"/{name}", waterwayAdmin(&mw.JSONHandler{
		Input:  func(*http.Request) interface{} { return &json.RawMessage{} },
		Handle: updatePrintTemplate,
		Limit:  maxPrintTemplateSize,
	})).Methods(http.MethodPatch)

	// External proxies.
	external := mw.NotFound(&httputil.ReverseProxy{
		Director:       proxyDirector(models.ExternalServices.Find),
		ModifyResponse: proxyModifyResponse("/api/external/"),
	})

	externalAuth := any(external)

	api.Handle("/external/{hash}/{url}", externalAuth).
		Methods(
			http.MethodGet, http.MethodPost,
			http.MethodPut, http.MethodDelete)

	api.Handle("/external/{entry}", externalAuth).
		Methods(
			http.MethodGet, http.MethodPost,
			http.MethodPut, http.MethodDelete)

	// Internal proxies.
	internal := mw.NotFound(&httputil.ReverseProxy{
		Director:       proxyDirector(models.InternalServices.Find),
		ModifyResponse: proxyModifyResponse("/api/internal/"),
	})

	internalAuth := any(
		mw.ModifyQuery(internal, mw.InjectUser))

	api.Handle("/internal/{hash}/{url}", internalAuth).
		Methods(
			http.MethodGet, http.MethodPost,
			http.MethodPut, http.MethodDelete)

	api.Handle("/internal/{entry}", internalAuth).
		Methods(
			http.MethodGet, http.MethodPost,
			http.MethodPut, http.MethodDelete)

	api.Handle("/published", any(&mw.JSONHandler{
		Handle: published,
		NoConn: true,
	})).Methods(http.MethodGet)

	// Survey selection
	api.Handle("/surveys/{bottleneck:.+}", any(&mw.JSONHandler{
		Handle: listSurveys,
	})).Methods(http.MethodGet)

	// Bottlenecks
	api.Handle("/bottlenecks", any(&mw.JSONHandler{
		Handle: listBottlenecks,
	})).Methods(http.MethodGet)

	// difference calculation
	api.Handle("/diff", any(&mw.JSONHandler{
		Input:  func(*http.Request) interface{} { return new(models.DiffCalculationInput) },
		Handle: diffCalculation,
		NoConn: true,
	})).Methods(http.MethodPost)

	// Cross sections
	api.Handle("/cross", any(&mw.JSONHandler{
		Input:  func(*http.Request) interface{} { return new(models.CrossSectionInput) },
		Handle: crossSection,
	})).Methods(http.MethodPost)

	// Feature search
	api.Handle("/search", any(&mw.JSONHandler{
		Input:  func(*http.Request) interface{} { return new(models.SearchRequest) },
		Handle: searchFeature,
	})).Methods(http.MethodPost)

	// Geo styling
	api.Handle("/geo/style/{feature}",
		sysAdmin(http.HandlerFunc(uploadStyle))).Methods(http.MethodPost)

	// Imports
	api.Handle("/imports/sr-upload/{token}",
		waterwayAdmin(http.HandlerFunc(deleteSoundingUpload))).Methods(http.MethodDelete)

	api.Handle("/imports/sr-upload", waterwayAdmin(&mw.JSONHandler{
		Handle: uploadSoundingResult,
	})).Methods(http.MethodPost)

	api.Handle("/imports/sr", waterwayAdmin(
		http.HandlerFunc(importSoundingResult))).Methods(http.MethodPost)

	api.Handle("/imports/wp", waterwayAdmin(
		importWaterwayProfiles())).Methods(http.MethodPost)

	api.Handle("/imports/agm", waterwayAdmin(
		importApprovedGaugeMeasurements())).Methods(http.MethodPost)

	api.Handle("/imports/ubn", waterwayAdmin(
		importUploadedBottleneck())).Methods(http.MethodPost)

	api.Handle("/imports/ufa", waterwayAdmin(
		importUploadedFairwayAvailability())).Methods(http.MethodPost)

	api.Handle("/imports/ugm", waterwayAdmin(
		importUploadedGaugeMeasurement())).Methods(http.MethodPost)

	api.Handle("/imports/stsh", sysAdmin(
		importUploadedStretchShape())).Methods(http.MethodPost)

	api.Handle("/imports/{kind:st}", sysAdmin(&mw.JSONHandler{
		Input:  importModel,
		Handle: manualImport,
		NoConn: true,
	})).Methods(http.MethodPost)

	kinds := strings.Join([]string{
		"bn", "gm", "fa", "wx", "wa",
		"wg", "dmv", "fd", "dma",
		"sec", "dsec", "dst", "dsr",
		"fm_bcnlat_hydro",
		"fm_bcnlat_ienc",
		"fm_boycar",
		"fm_boylat",
		"fm_boysaw",
		"fm_boyspp",
		"fm_daymar",
		"fm_lights",
		"fm_rtpbcn",
		"fm_topmar",
		"fm_notmrk",
	}, "|")

	api.Handle("/imports/{kind:"+kinds+"}", waterwayAdmin(&mw.JSONHandler{
		Input:  importModel,
		Handle: manualImport,
		NoConn: true,
	})).Methods(http.MethodPost)

	// Import scheduler configuration
	api.Handle("/imports/config/{id:[0-9]+}/run",
		waterwayAdmin(&mw.JSONHandler{
			Handle: runImportConfig,
		})).Methods(http.MethodGet)

	api.Handle("/imports/config/{id:[0-9]+}",
		waterwayAdmin(&mw.JSONHandler{
			Input:  func(*http.Request) interface{} { return &json.RawMessage{} },
			Handle: modifyImportConfig,
		})).Methods(http.MethodPatch)

	api.Handle("/imports/config/{id:[0-9]+}",
		waterwayAdmin(&mw.JSONHandler{
			Handle: deleteImportConfig,
		})).Methods(http.MethodDelete)

	api.Handle("/imports/config/{id:[0-9]+}",
		waterwayAdmin(&mw.JSONHandler{
			Handle: infoImportConfig,
		})).Methods(http.MethodGet)

	api.Handle("/imports/config",
		waterwayAdmin(&mw.JSONHandler{
			Input:  func(*http.Request) interface{} { return new(imports.ImportConfigIn) },
			Handle: addImportConfig,
		})).Methods(http.MethodPost)

	api.Handle("/imports/config",
		waterwayAdmin(&mw.JSONHandler{
			Handle: listImportConfigs,
		})).Methods(http.MethodGet)

	// Import queue

	api.Handle("/imports", waterwayAdmin(&mw.JSONHandler{
		Handle: listImports,
	})).Methods(http.MethodGet)

	api.Handle("/imports/export", waterwayAdmin(
		mw.DBConn(http.HandlerFunc(exportImports)))).Methods(http.MethodGet)

	api.Handle("/imports/{id:[0-9]+}", waterwayAdmin(&mw.JSONHandler{
		Handle: importLogs,
	})).Methods(http.MethodGet)

	api.Handle("/imports", waterwayAdmin(&mw.JSONHandler{
		Input:  func(*http.Request) interface{} { return &[]models.Review{} },
		Handle: reviewImports,
	})).Methods(http.MethodPatch)

	api.Handle("/imports/{id:[0-9]+}", waterwayAdmin(&mw.JSONHandler{
		Handle: deleteImport,
	})).Methods(http.MethodDelete)

	// Handler to review an import which is pending.
	api.Handle("/imports/{id:[0-9]+}/{state:(?:accepted|declined)}",
		waterwayAdmin(&mw.JSONHandler{
			Handle: reviewImport,
		})).Methods(http.MethodPut)

	// Handler to serve data to the client.

	api.Handle("/data/stretch/shape/{name:.+}", any(
		mw.DBConn(http.HandlerFunc(stretchShapeDownload)))).Methods(http.MethodGet)

	api.Handle("/data/{kind:stretch|section}/availability/{name:.+}", any(
		mw.DBConn(http.HandlerFunc(stretchAvailabilty)))).Methods(http.MethodGet)

	api.Handle("/data/{kind:stretch|section}/fairway-depth/{name:.+}", any(
		mw.DBConn(http.HandlerFunc(stretchAvailableFairwayDepth)))).Methods(http.MethodGet)

	api.Handle("/data/bottleneck/fairway-depth/{objnam:.+}", any(
		mw.DBConn(http.HandlerFunc(bottleneckAvailableFairwayDepth)))).Methods(http.MethodGet)

	api.Handle("/data/bottleneck/availability/{objnam:.+}", any(
		mw.DBConn(http.HandlerFunc(bottleneckAvailabilty)))).Methods(http.MethodGet)

	api.Handle("/data/waterlevels/{gauge:.+}", any(
		mw.DBConn(http.HandlerFunc(waterlevels)))).Methods(http.MethodGet)

	api.Handle("/data/longterm-waterlevels/{gauge:.+}", any(
		mw.DBConn(http.HandlerFunc(longtermWaterlevels)))).Methods(http.MethodGet)

	// TODO: gauge should not contain '/'s.
	api.Handle("/data/year-waterlevels/{gauge}/{year:[0-9]+}", any(
		mw.DBConn(http.HandlerFunc(yearWaterlevels)))).Methods(http.MethodGet)

	api.Handle("/data/nash-sutcliffe/{gauge:.+}", any(&mw.JSONHandler{
		Handle: nashSutcliffe,
	})).Methods(http.MethodGet)

	// Token handling: Login/Logout.
	api.HandleFunc("/login", login).
		Methods(http.MethodPost)
	api.Handle("/logout", auth.SessionMiddleware(http.HandlerFunc(logout))).
		Methods(http.MethodGet, http.MethodPost)
	api.Handle("/renew", auth.SessionMiddleware(http.HandlerFunc(renew))).
		Methods(http.MethodGet, http.MethodPost)
}