Add add config validators
This commit is contained in:
8 files changed
+262
-42
No files matched your search
@@ -0,0 +1,62 @@
|
||||
package configloader
|
||||
|
||||
import _ "embed"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"slices"
|
||||
)
|
||||
|
||||
type ParserListItem struct {
|
||||
Title string `json:"title"`
|
||||
Comment string `json:"comment"`
|
||||
Authors []string `json:"authors"`
|
||||
Links []string `json:"links"`
|
||||
}
|
||||
|
||||
// Load parser list from JSON retrieved from musdb's API
|
||||
// See https://<subdomain>.museum-digital.org/musdb/api/meta/list_import_parsers
|
||||
// The embed module requires the variable to not be bound to a function.
|
||||
|
||||
//go:embed parser_list.json
|
||||
var rawParserList []byte
|
||||
|
||||
// Returns a list of the available parsers.
|
||||
func ListParsers() []ParserListItem {
|
||||
|
||||
parserListFromApi := []ParserListItem{}
|
||||
// parserListFromApi := new(ApiParserListFormat)
|
||||
json.Unmarshal(rawParserList, &parserListFromApi)
|
||||
print(parserListFromApi)
|
||||
|
||||
return parserListFromApi
|
||||
|
||||
}
|
||||
|
||||
// Checks if inputParser is in the list of available parsers.
|
||||
// Returns the parser name or an error.
|
||||
func ValidateParser(inputParser string) (string, error) {
|
||||
|
||||
parserList := ListParsers()
|
||||
parserTitles := []string{}
|
||||
|
||||
for _, p := range(parserList) {
|
||||
parserTitles = append(parserTitles, p.Title)
|
||||
}
|
||||
|
||||
if slices.Contains(parserTitles, inputParser) {
|
||||
return inputParser, nil
|
||||
}
|
||||
|
||||
// Accepted invalid modes to clean up:
|
||||
// ParserLido > Lido
|
||||
// lido > Lido
|
||||
cleaned := inputParser[6:]
|
||||
if slices.Contains(parserTitles, cleaned) {
|
||||
return cleaned, nil
|
||||
}
|
||||
|
||||
return "", errors.New("Invalid parser selected")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package configloader
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Tests that the list of parsers is not empty.
|
||||
func TestListParserReturnsNonEmptyResult(t *testing.T) {
|
||||
|
||||
parserList := ListParsers()
|
||||
if len(parserList) == 0 {
|
||||
t.Fatalf("The list of returned parsers is empty")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Ensures that validating a parser will not accept an invalid parser name.
|
||||
func TestInvalidParserIsNotAccepted(t *testing.T) {
|
||||
|
||||
parser, err := ValidateParser("Liddasfasdo")
|
||||
if parser != "" {
|
||||
t.Fatalf("ValidateParser() should return an empty string + error")
|
||||
}
|
||||
if err == nil {
|
||||
t.Fatalf("ValidateParser() did not return an error where it should")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Ensures that a parser is valid at its expected name.
|
||||
func TestValidParserIsAccepted(t *testing.T) {
|
||||
|
||||
parser, err := ValidateParser("Lido")
|
||||
if parser != "Lido" {
|
||||
t.Fatalf("Test expected validated parser for input 'Lido' to be 'Lido'")
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("ValidateParser() returned an error where it should not")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Prepending the prefix "Parser" to a parser name should work as well.
|
||||
// In this case, the prefix should be removed by ValidateParser().
|
||||
func TestValidParserIsAcceptedAndCleaned(t *testing.T) {
|
||||
|
||||
parser, err := ValidateParser("ParserLido")
|
||||
if parser != "Lido" {
|
||||
t.Fatalf("Test expected validated parser for input 'ParserLido' to be 'Lido'")
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("ValidateParser() returned an error where it should not")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package configloader
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Validates a museum-digital instance URL to upload to.
|
||||
// The link must be a valid URL. As it can be expected that people will
|
||||
// enter broken values, the URL should be reduced to its hostname and
|
||||
// rebuilt from there.
|
||||
func ValidateInstanceLink(instanceUrl string) (string, error) {
|
||||
|
||||
parsed, err := url.Parse(instanceUrl)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Check the hostname contains "museum-digital.de" or "museum-digital.org"
|
||||
if !strings.HasSuffix(parsed.Host, "museum-digital.de") && !strings.HasSuffix(parsed.Host, "museum-digital.org") {
|
||||
return "", errors.New("This tool only supports uploading to XYZ.museum-digital.de or XYZ.museum-digital.org")
|
||||
}
|
||||
|
||||
// Check /musdb is available on the md instance
|
||||
musdbUrl := url.URL{
|
||||
Scheme: "https",
|
||||
Host: parsed.Host,
|
||||
Path: "/musdb",
|
||||
}
|
||||
resp, err := http.Get(musdbUrl.String())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if resp.StatusCode > 399 {
|
||||
return "", errors.New("The museum-digital subdomain does not contain a musdb path")
|
||||
}
|
||||
|
||||
// https should be assumed and enforced.
|
||||
url := url.URL{
|
||||
Scheme: "https",
|
||||
Host: parsed.Host,
|
||||
}
|
||||
return url.String(), nil
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package configloader
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test that ValidateInstanceLink() fails on non-URLs.
|
||||
func TestValidateInstanceFailsOnNonUrl(t *testing.T) {
|
||||
|
||||
_, err := ValidateInstanceLink("abcmuseum-digital.org")
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("ValidateInstanceLink() does not return an error on a non-URL")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Test that ValidateInstanceLink() fails on links outside of md.
|
||||
func TestValidateInstanceLinkFailsOutsideOfMd(t *testing.T) {
|
||||
|
||||
_, err := ValidateInstanceLink("test.museum-digital.de")
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("ValidateInstanceLink() accepts URLs outside of the main museum-digital")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Test that ValidateInstanceLink() fails on valid md aggregated instances
|
||||
// (uploads can only happen to regional instances / those that have a dedicated
|
||||
// instance of musdb).
|
||||
func TestValidateInstanceLinkFailsWithAggregatedInstance(t *testing.T) {
|
||||
|
||||
_, err := ValidateInstanceLink("https://nat.museum-digital.de")
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("ValidateInstanceLink() accepts URLs of aggregated instance")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Test that ValidateInstanceLink() works with a valid instance of md.
|
||||
func TestValidateInstanceWorks(t *testing.T) {
|
||||
|
||||
result, err := ValidateInstanceLink("https://hessen.museum-digital.de")
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("ValidateInstanceLink() returns an error where it should work")
|
||||
}
|
||||
if result != "https://hessen.museum-digital.de" {
|
||||
t.Fatalf("Output of ValidateInstanceLink() is not https://hessen.museum-digital.de where it should be")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package configloader
|
||||
|
||||
import "net/mail"
|
||||
|
||||
// Validates an input mail address.
|
||||
// Returns the valid mail address or an eQueries therror.
|
||||
func ValidateMail(email string) (string, error) {
|
||||
|
||||
_, err := mail.ParseAddress(email)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return email, nil
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package configloader
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test that ValidateMail() returns the mail address if it is valid.
|
||||
func TestValidateMailAcceptsValidMailAddress(t *testing.T) {
|
||||
|
||||
_, err := ValidateMail("test@example.com")
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("ValidateMail() returns an error on a valid mail address")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Test that ValidateMail() filters out invalid mail addresses.
|
||||
func TestValidateMailDoesNotAcceptInvalidMailAddress(t *testing.T) {
|
||||
|
||||
_, err := ValidateMail("test")
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("ValidateMail() does not prevent entering an invalid mail address")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,11 +11,6 @@ type MDWebDavUploaderConfig struct {
|
||||
PublishOnImport bool `json:"visible"`
|
||||
}
|
||||
|
||||
type ParserListItem struct {
|
||||
name string
|
||||
|
||||
}
|
||||
|
||||
// Returns a uniform filepath for the configuration of this tool.
|
||||
// To be compatible across operating systems, this will be a JSON
|
||||
// file in the same directory as the current programm.
|
||||
@@ -23,45 +18,8 @@ func getConfigFilepath() string {
|
||||
|
||||
}
|
||||
|
||||
// Returns a uniform filepath for the cache for the list of
|
||||
// available parsers.
|
||||
func getParserCacheFilepath() string {
|
||||
|
||||
}
|
||||
|
||||
// Loads configuration from the configuration file (located using
|
||||
// getConfigFilepath()).
|
||||
func LoadFromFile() MDWebDavUploaderConfig {
|
||||
|
||||
}
|
||||
|
||||
// Stores a parser list to a cache file (located via
|
||||
// getParserCacheFilepath()).
|
||||
func StoreParserList(parserList []ParserListItem) {
|
||||
|
||||
}
|
||||
|
||||
// Returns a list of the available parsers.
|
||||
func ListParsers() []ParserListItem {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Checks if inputParser is in the list of available parsers.
|
||||
// Returns the parser name or an error.
|
||||
func ValidateParser(inputParser string) (string, error) {
|
||||
|
||||
}
|
||||
|
||||
// Validates an input mail address.
|
||||
// Returns the valid mail address or an eQueries therror.
|
||||
func ValidateMail(mail string) (string, error) {
|
||||
|
||||
}
|
||||
|
||||
// Validates an entered instance URL.
|
||||
// Returns the entered URL in a unified form (minus optional
|
||||
// trailing slashes and the /musdb suffix) or an error.
|
||||
func ValidateInstanceLink(instanceUrl string) (string, error) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
[{"title":"AdlibCsv","comment":"Parser for CSV exports from Adlib.\n\nHas the following settings:\n\nstart_at Setting this option to any number other than 0 makes the importer\n\n skip the first X files. This can be useful if an import fails\n\n somewhere in the middle of the import process. Using this setting,\n\n you can skip import files that have already been successfully\n\n imported.\n\nseparator The separator character dividing the columns in the CSV file to be\n\n imported. Defaults to ','.","authors":["Joshua Ramon Enslin <joshua@museum-digital.de>"],"links":["https:\/\/www.axiell.com\/de\/loesungen\/produkt\/adlib\/"]},{"title":"AdlibLiteratureXml","comment":"Parser for XML exports of the literature module of Adlib \/ Axiell Collections.\n\nThis parser imports from the literature module to the literature module.\n\nThe parser has the following settings.\n\nstart_at Setting this option to any number other than\n\n 0 makes the importer skip the first X files.\n\n This can be useful if an import fails somewhere\n\n in the middle of the import process. Using this\n\n setting, you can skip import files that have\n\n already been successfully imported.","authors":["Joshua Ramon Enslin <joshua@museum-digital.de>"],"links":["https:\/\/www.axiell.com\/de\/loesungen\/produkt\/adlib\/"]},{"title":"AdlibLiteratureXmlToObjects","comment":"Parser for XML exports of the literature module of Adlib \/ Axiell Collections.\n\nThis parser imports from the literature module to the object module.\n\nThe parser has the following settings.\n\nstart_at Setting this option to any number other than\n\n 0 makes the importer skip the first X files.\n\n This can be useful if an import fails somewhere\n\n in the middle of the import process. Using this\n\n setting, you can skip import files that have\n\n already been successfully imported.","authors":["Joshua Ramon Enslin <joshua@museum-digital.de>"],"links":["https:\/\/www.axiell.com\/de\/loesungen\/produkt\/adlib\/"]},{"title":"AdlibXml","comment":"Parser for XML exports from Adlib \/ Axiell Collections. Initially optimized and\n\ntested with export data from the Schwules Museum Berlin (https:\/\/www.schwulesmuseum.de\/ \/\n\nhttps:\/\/berlin.museum-digital.de\/institution\/33), the parser has now been extended\n\nto cover exports from a number of museums using different versions of the software.\n\nHas the following settings:\n\nstart_at Setting this option to any number other than\n\n 0 makes the importer skip the first X files.\n\n This can be useful if an import fails somewhere\n\n in the middle of the import process. Using this\n\n setting, you can skip import files that have\n\n already been successfully imported.","authors":["Joshua Ramon Enslin <joshua@museum-digital.de>"],"links":["https:\/\/www.axiell.com\/de\/loesungen\/produkt\/adlib\/"]},{"title":"BeeCollectDtmb","comment":"Parser for XML generated through CSVXML.","authors":["Joshua Ramon Enslin <joshua@museum-digital.de>","Stefan Rohde-Enslin <s.rohde-enslin@museum-digital.de>"],"links":["https:\/\/imports.museum-digital.org\/importer\/parsers\/csvxml.php"]},{"title":"BeeCollectIndustriemuseenSachsen","comment":"Parser for exports from BeeCollect formulated for the industrial heritage\n\nmuseums in Saxony.","authors":["Joshua Ramon Enslin <joshua@museum-digital.de>"],"links":["https:\/\/www.solvatec.com\/"]},{"title":"BeeCollectStadtmuseumDresden","comment":"Parser for exports from BeeCollect formulated for the export settings of the\n\nCity Museum of Dresden.","authors":["Joshua Ramon Enslin <joshua@museum-digital.de>"],"links":["https:\/\/www.solvatec.com\/"]},{"title":"CsvMuseenKoeln","comment":"Parser to import images using very simple CSV files with only two columns:\n\n\"inventory_number\" and \"image_name1\".\n\nstart_at Setting this option to any number other than 0 makes the importer\n\n skip the first X files. This can be useful if an import fails\n\n somewhere in the middle of the import process. Using this setting,\n\n you can skip import files that have already been successfully\n\n imported.\n\nseparator The separator character dividing the columns in the CSV file to be\n\n imported. Defaults to ';'.\n\nsub_separator Separator for tags, etc.","authors":["Joshua Ramon Enslin <joshua@museum-digital.de>"],"links":["https:\/\/csvxml.imports.museum-digital.org\/"]},{"title":"Csvxml","comment":"Parser for XML generated through CLine truncated
|
||||
Reference in new issue
Block a user