view pkg/controllers/routes.go @ 4894:8eb36d0d5bdf fairway-marks-import

Draft implementation of fairway marks import Currently works (at least) for IENC feature BCNLAT. In order to be able to store different types of fairway marks, more tables and import types are needed. Currently stupidly stores every entry received from the data source. Sorting out duplicates and invalidating entries removed from the data source needs to implemented.
author Tom Gottfried <tom@intevation.de>
date Tue, 14 Jan 2020 15:01:42 +0100
parents 37429e50a74f
children bcb8b69e4358
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", "fm",
		"sec", "dsec", "dst", "dsr",
	}, "|")

	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)
}