changeset 2058:09f9ae3d0526 unify_imports

Imports: Handle manual imports with a single route using the shortnames of the imports to distiquish between them.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 28 Jan 2019 20:35:14 +0100
parents 84d88fbd6007
children ae0021feaac8
files pkg/controllers/json.go pkg/controllers/manualimports.go pkg/controllers/routes.go pkg/imports/modelconvert.go
diffstat 4 files changed, 103 insertions(+), 144 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/controllers/json.go	Mon Jan 28 19:30:03 2019 +0100
+++ b/pkg/controllers/json.go	Mon Jan 28 20:35:14 2019 +0100
@@ -44,7 +44,7 @@
 type JSONHandler struct {
 	// Input (if not nil) is called to fill a data structure
 	// returned by this function.
-	Input func() interface{}
+	Input func(*http.Request) interface{}
 	// Handle is called to handle the incoming HTTP request.
 	// in is the data structure returned by Input. Its nil if Input is nil.
 	// req is the incoming HTTP request.
@@ -79,7 +79,7 @@
 
 	var input interface{}
 	if j.Input != nil {
-		input = j.Input()
+		input = j.Input(req)
 		defer req.Body.Close()
 		var r io.Reader
 		switch {
--- a/pkg/controllers/manualimports.go	Mon Jan 28 19:30:03 2019 +0100
+++ b/pkg/controllers/manualimports.go	Mon Jan 28 20:35:14 2019 +0100
@@ -24,78 +24,88 @@
 	"gemma.intevation.de/gemma/pkg/common"
 	"gemma.intevation.de/gemma/pkg/imports"
 	"gemma.intevation.de/gemma/pkg/models"
+	"github.com/gorilla/mux"
 )
 
+func importModel(req *http.Request) interface{} {
+	kind := mux.Vars(req)["kind"]
+	ctor := imports.ImportModelForJobKind(imports.JobKind(kind))
+	if ctor == nil {
+		log.Printf("error: Unknown job kind '%s'.\n", kind)
+		panic(http.ErrAbortHandler)
+	}
+	return ctor()
+}
+
 func manualImport(
-	kind imports.JobKind,
-) func(interface{}, *http.Request, *sql.Conn) (JSONResult, error) {
-
-	return func(input interface{}, req *http.Request, _ *sql.Conn) (
-		jr JSONResult, err error) {
-
-		what := imports.ConvertToInternal(kind, input)
-		if what == nil {
-			err = JSONError{
-				Code:    http.StatusInternalServerError,
-				Message: "Unable to convert import models",
-			}
-			return
-		}
-
-		var serialized string
-		if serialized, err = common.ToJSONString(what); err != nil {
-			return
-		}
-
-		var (
-			due       time.Time
-			trys      *int
-			waitRetry *time.Duration
-			email     bool
-		)
+	input interface{},
+	req *http.Request,
+	_ *sql.Conn,
+) (jr JSONResult, err error) {
 
-		if qctg, ok := input.(models.QueueConfigurationGetter); ok {
-			qct := qctg.GetQueueConfiguration()
-			if qct.Due != nil {
-				due = qct.Due.Time
-			}
-			trys = qct.Trys
-			if qct.WaitRetry != nil {
-				waitRetry = &qct.WaitRetry.Duration
-			}
-		}
-
-		if etg, ok := input.(models.EmailTypeGetter); ok {
-			email = etg.GetEmailType().Email
-		}
-
-		session, _ := auth.GetSession(req)
-
-		var jobID int64
-		if jobID, err = imports.AddJob(
-			kind,
-			due,
-			trys,
-			waitRetry,
-			session.User,
-			email,
-			serialized,
-		); err != nil {
-			return
-		}
-
-		log.Printf("info: added import #%d to queue\n", jobID)
-
-		result := struct {
-			ID int64 `json:"id"`
-		}{
-			ID: jobID,
-		}
-
-		jr = JSONResult{
-			Code:   http.StatusCreated,
-			Result: &result,
+	kind := imports.JobKind(mux.Vars(req)["kind"])
+	what := imports.ConvertToInternal(kind, input)
+	if what == nil {
+		err = JSONError{
+			Code:    http.StatusInternalServerError,
+			Message: "Unable to convert import models",
 		}
 		return
 	}
+
+	var serialized string
+	if serialized, err = common.ToJSONString(what); err != nil {
+		return
+	}
+
+	var (
+		due       time.Time
+		trys      *int
+		waitRetry *time.Duration
+		email     bool
+	)
+
+	if qctg, ok := input.(models.QueueConfigurationGetter); ok {
+		qct := qctg.GetQueueConfiguration()
+		if qct.Due != nil {
+			due = qct.Due.Time
+		}
+		trys = qct.Trys
+		if qct.WaitRetry != nil {
+			waitRetry = &qct.WaitRetry.Duration
+		}
+	}
+
+	if etg, ok := input.(models.EmailTypeGetter); ok {
+		email = etg.GetEmailType().Email
+	}
+
+	session, _ := auth.GetSession(req)
+
+	var jobID int64
+	if jobID, err = imports.AddJob(
+		kind,
+		due,
+		trys,
+		waitRetry,
+		session.User,
+		email,
+		serialized,
+	); err != nil {
+		return
+	}
+
+	log.Printf("info: added import #%d to queue\n", jobID)
+
+	result := struct {
+		ID int64 `json:"id"`
+	}{
+		ID: jobID,
+	}
+
+	jr = JSONResult{
+		Code:   http.StatusCreated,
+		Result: &result,
+	}
+	return
 }
--- a/pkg/controllers/routes.go	Mon Jan 28 19:30:03 2019 +0100
+++ b/pkg/controllers/routes.go	Mon Jan 28 20:35:14 2019 +0100
@@ -18,6 +18,7 @@
 	"encoding/json"
 	"net/http"
 	"net/http/httputil"
+	"strings"
 
 	"github.com/gorilla/mux"
 
@@ -44,7 +45,7 @@
 	})).Methods(http.MethodGet)
 
 	api.Handle("/users", sysAdmin(&JSONHandler{
-		Input:  func() interface{} { return new(models.User) },
+		Input:  func(*http.Request) interface{} { return new(models.User) },
 		Handle: createUser,
 	})).Methods(http.MethodPost)
 
@@ -53,7 +54,7 @@
 	})).Methods(http.MethodGet)
 
 	api.Handle("/users/{user}", any(&JSONHandler{
-		Input:  func() interface{} { return new(models.User) },
+		Input:  func(*http.Request) interface{} { return new(models.User) },
 		Handle: updateUser,
 	})).Methods(http.MethodPut)
 
@@ -78,13 +79,13 @@
 	})).Methods(http.MethodGet)
 
 	api.Handle("/system/style/{feature}/{attr}", any(&JSONHandler{
-		Input:  func() interface{} { return new(models.Colour) },
+		Input:  func(*http.Request) interface{} { return new(models.Colour) },
 		Handle: setFeatureStyle,
 	})).Methods(http.MethodPut)
 
 	// Password resets.
 	api.Handle("/users/passwordreset", &JSONHandler{
-		Input:  func() interface{} { return new(models.PWResetUser) },
+		Input:  func(*http.Request) interface{} { return new(models.PWResetUser) },
 		Handle: passwordResetRequest,
 		NoConn: true,
 	}).Methods(http.MethodPost)
@@ -148,13 +149,13 @@
 
 	// Cross sections
 	api.Handle("/cross", any(&JSONHandler{
-		Input:  func() interface{} { return new(models.CrossSectionInput) },
+		Input:  func(*http.Request) interface{} { return new(models.CrossSectionInput) },
 		Handle: crossSection,
 	})).Methods(http.MethodPost)
 
 	// Feature search
 	api.Handle("/search", any(&JSONHandler{
-		Input:  func() interface{} { return new(models.SearchRequest) },
+		Input:  func(*http.Request) interface{} { return new(models.SearchRequest) },
 		Handle: searchFeature,
 	})).Methods(http.MethodPost)
 
@@ -163,76 +164,33 @@
 		sysAdmin(http.HandlerFunc(uploadStyle))).Methods(http.MethodPost)
 
 	// Imports
-	api.Handle("/imports/soundingresult-upload/{token}",
+	api.Handle("/imports/sr-upload/{token}",
 		waterwayAdmin(http.HandlerFunc(deleteSoundingUpload))).Methods(http.MethodDelete)
 
-	api.Handle("/imports/soundingresult-upload", waterwayAdmin(&JSONHandler{
+	api.Handle("/imports/sr-upload", waterwayAdmin(&JSONHandler{
 		Handle: uploadSoundingResult,
 	})).Methods(http.MethodPost)
 
-	api.Handle("/imports/soundingresult", waterwayAdmin(
+	api.Handle("/imports/sr", waterwayAdmin(
 		http.HandlerFunc(importSoundingResult))).Methods(http.MethodPost)
 
-	api.Handle("/imports/approvedgm", waterwayAdmin(
+	api.Handle("/imports/agm", waterwayAdmin(
 		http.HandlerFunc(importApprovedGaugeMeasurements))).Methods(http.MethodPost)
 
-	api.Handle("/imports/bottleneck", waterwayAdmin(&JSONHandler{
-		Input:  imports.MustImportModel(imports.BNJobKind),
-		Handle: manualImport(imports.BNJobKind),
-		NoConn: true,
-	})).Methods(http.MethodPost)
-
-	api.Handle("/imports/gaugemeasurement", waterwayAdmin(&JSONHandler{
-		Input:  imports.MustImportModel(imports.GMJobKind),
-		Handle: manualImport(imports.GMJobKind),
-		NoConn: true,
-	})).Methods(http.MethodPost)
-
-	api.Handle("/imports/fairwayavailability", waterwayAdmin(&JSONHandler{
-		Input:  imports.MustImportModel(imports.FAJobKind),
-		Handle: manualImport(imports.FAJobKind),
+	api.Handle("/imports/{kind:st}", sysAdmin(&JSONHandler{
+		Input:  importModel,
+		Handle: manualImport,
 		NoConn: true,
 	})).Methods(http.MethodPost)
 
-	api.Handle("/imports/waterwayaxis", waterwayAdmin(&JSONHandler{
-		Input:  imports.MustImportModel(imports.WXJobKind),
-		Handle: manualImport(imports.WXJobKind),
-		NoConn: true,
-	})).Methods(http.MethodPost)
-
-	api.Handle("/imports/waterwayarea", waterwayAdmin(&JSONHandler{
-		Input:  imports.MustImportModel(imports.WAJobKind),
-		Handle: manualImport(imports.WAJobKind),
-		NoConn: true,
-	})).Methods(http.MethodPost)
-
-	api.Handle("/imports/waterwaygauge", waterwayAdmin(&JSONHandler{
-		Input:  imports.MustImportModel(imports.WGJobKind),
-		Handle: manualImport(imports.WGJobKind),
-		NoConn: true,
-	})).Methods(http.MethodPost)
+	kinds := strings.Join([]string{
+		"bn", "gm", "fa", "wx", "wa",
+		"wg", "dmv", "fd", "dm",
+	}, "|")
 
-	api.Handle("/imports/distancemarksvirtual", waterwayAdmin(&JSONHandler{
-		Input:  imports.MustImportModel(imports.DMVJobKind),
-		Handle: manualImport(imports.DMVJobKind),
-		NoConn: true,
-	})).Methods(http.MethodPost)
-
-	api.Handle("/imports/fairwaydimension", waterwayAdmin(&JSONHandler{
-		Input:  imports.MustImportModel(imports.FDJobKind),
-		Handle: manualImport(imports.FDJobKind),
-		NoConn: true,
-	})).Methods(http.MethodPost)
-
-	api.Handle("/imports/distancemarks", waterwayAdmin(&JSONHandler{
-		Input:  imports.MustImportModel(imports.DMAJobKind),
-		Handle: manualImport(imports.DMAJobKind),
-		NoConn: true,
-	})).Methods(http.MethodPost)
-
-	api.Handle("/imports/stretch", sysAdmin(&JSONHandler{
-		Input:  imports.MustImportModel(imports.STJobKind),
-		Handle: manualImport(imports.STJobKind),
+	api.Handle("/imports/{kind:"+kinds+"}", waterwayAdmin(&JSONHandler{
+		Input:  importModel,
+		Handle: manualImport,
 		NoConn: true,
 	})).Methods(http.MethodPost)
 
@@ -244,7 +202,7 @@
 
 	api.Handle("/imports/config/{id:[0-9]+}",
 		waterwayAdmin(&JSONHandler{
-			Input:  func() interface{} { return &json.RawMessage{} },
+			Input:  func(*http.Request) interface{} { return &json.RawMessage{} },
 			Handle: modifyImportConfig,
 		})).Methods(http.MethodPatch)
 
@@ -260,7 +218,7 @@
 
 	api.Handle("/imports/config",
 		waterwayAdmin(&JSONHandler{
-			Input:  func() interface{} { return new(imports.ImportConfigIn) },
+			Input:  func(*http.Request) interface{} { return new(imports.ImportConfigIn) },
 			Handle: addImportConfig,
 		})).Methods(http.MethodPost)
 
@@ -282,7 +240,7 @@
 	})).Methods(http.MethodGet)
 
 	api.Handle("/imports", waterwayAdmin(&JSONHandler{
-		Input:  func() interface{} { return &[]models.Review{} },
+		Input:  func(*http.Request) interface{} { return &[]models.Review{} },
 		Handle: reviewImports,
 	})).Methods(http.MethodPatch)
 
--- a/pkg/imports/modelconvert.go	Mon Jan 28 19:30:03 2019 +0100
+++ b/pkg/imports/modelconvert.go	Mon Jan 28 20:35:14 2019 +0100
@@ -14,8 +14,6 @@
 package imports
 
 import (
-	"fmt"
-
 	"gemma.intevation.de/gemma/pkg/models"
 )
 
@@ -36,13 +34,6 @@
 	return kindToImportModel[kind]
 }
 
-func MustImportModel(kind JobKind) func() interface{} {
-	if ctor := kindToImportModel[kind]; ctor != nil {
-		return ctor
-	}
-	panic(fmt.Sprintf("Cannot find import model for kind '%s'.", kind))
-}
-
 var convertModel = map[JobKind]func(interface{}) interface{}{
 
 	BNJobKind: func(input interface{}) interface{} {