diff options
author | Přemysl Janouch <p@janouch.name> | 2019-04-16 00:07:00 +0200 |
---|---|---|
committer | Přemysl Janouch <p@janouch.name> | 2019-04-16 00:07:00 +0200 |
commit | a4a399b8127b8930b7e725af55ed6d129b4c654e (patch) | |
tree | d5cbdeb1755c2b9a3fcdeae22f089e997dd0ea45 | |
parent | 2bd4f5921cb91bef2f39b231ac57a5fba5b782d2 (diff) | |
download | sklad-a4a399b8127b8930b7e725af55ed6d129b4c654e.tar.gz sklad-a4a399b8127b8930b7e725af55ed6d129b4c654e.tar.xz sklad-a4a399b8127b8930b7e725af55ed6d129b4c654e.zip |
sklad: prevent creating container cycles
-rw-r--r-- | cmd/sklad/container.tmpl | 2 | ||||
-rw-r--r-- | cmd/sklad/db.go | 15 | ||||
-rw-r--r-- | cmd/sklad/main.go | 2 |
3 files changed, 16 insertions, 3 deletions
diff --git a/cmd/sklad/container.tmpl b/cmd/sklad/container.tmpl index b3ce98f..200bb19 100644 --- a/cmd/sklad/container.tmpl +++ b/cmd/sklad/container.tmpl @@ -12,6 +12,8 @@ <p>Chyba: Řadu u neprázdných obalů nelze měnit. {{ else if .ErrorCannotChangeNumber }} <p>Chyba: Číslo obalu v řadě nelze měnit. +{{ else if .ErrorWouldContainItself }} +<p>Chyba: Obal by obsahoval sám sebe. {{ else if .ErrorContainerInUse }} <p>Chyba: Obal se používá. {{ else if .Error }} diff --git a/cmd/sklad/db.go b/cmd/sklad/db.go index a6cdda8..262a164 100644 --- a/cmd/sklad/db.go +++ b/cmd/sklad/db.go @@ -163,6 +163,7 @@ var errNoSuchContainer = errors.New("no such container") var errCannotChangeSeriesNotEmpty = errors.New( "cannot change the series of a non-empty container") var errCannotChangeNumber = errors.New("cannot change the number") +var errWouldContainItself = errors.New("container would contain itself") var errContainerInUse = errors.New("container is in use") // Find and filter out the container in O(n). @@ -204,19 +205,27 @@ func dbContainerCreate(c *Container) error { } func dbContainerUpdate(c *Container, updated Container) error { - newId := updated.Id() + newID := updated.Id() if updated.Series != c.Series && len(c.Children()) > 0 { return errCannotChangeSeriesNotEmpty } if updated.Number != c.Number { return errCannotChangeNumber } - if _, ok := indexContainer[newId]; ok && newId != c.Id() { + if _, ok := indexContainer[newID]; ok && newID != c.Id() { return errContainerAlreadyExists } if updated.Parent != c.Parent { + // Relying on the invariant that we can't change the ID + // of a non-empty container. + for pv := &updated; pv.Parent != ""; pv = indexContainer[pv.Parent] { + if pv.Parent == updated.Id() { + return errWouldContainItself + } + } + indexChildren[c.Parent] = filterContainer(indexChildren[c.Parent], c) - indexChildren[newId] = append(indexChildren[newId], c) + indexChildren[newID] = append(indexChildren[newID], c) } *c = updated return dbCommit() diff --git a/cmd/sklad/main.go b/cmd/sklad/main.go index 22d25b7..decd894 100644 --- a/cmd/sklad/main.go +++ b/cmd/sklad/main.go @@ -130,6 +130,7 @@ func handleContainer(w http.ResponseWriter, r *http.Request) { ErrorNoSuchContainer bool ErrorCannotChangeSeriesNotEmpty bool ErrorCannotChangeNumber bool + ErrorWouldContainItself bool ErrorContainerInUse bool Container *Container Children []*Container @@ -141,6 +142,7 @@ func handleContainer(w http.ResponseWriter, r *http.Request) { ErrorNoSuchContainer: err == errNoSuchContainer, ErrorCannotChangeSeriesNotEmpty: err == errCannotChangeSeriesNotEmpty, ErrorCannotChangeNumber: err == errCannotChangeNumber, + ErrorWouldContainItself: err == errWouldContainItself, ErrorContainerInUse: err == errContainerInUse, Container: container, Children: children, |