diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Company.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Company.java index 978baae..f657a23 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Company.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Company.java @@ -77,6 +77,11 @@ public class Company implements Mappable, Owner { return decimalSeparator; } + @Override + public boolean equals(Object obj) { + return obj instanceof Company c && c.id == id; + } + public String email() { return email; } diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/Item.java b/core/src/main/java/de/srsoftware/umbrella/core/model/Item.java index 7a77d7f..7c3e363 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/Item.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/Item.java @@ -28,6 +28,11 @@ public class Item implements Mappable { this.properties = new HashSet<>(); } + public Item clear() { + dirtyFields.clear(); + return this; + } + public String code(){ return code; } @@ -44,6 +49,12 @@ public class Item implements Mappable { return location; } + public Item location(Location newVal) { + location = newVal; + dirtyFields.add(LOCATION); + return this; + } + public String name(){ return name; } @@ -62,6 +73,24 @@ public class Item implements Mappable { return owner; } + public Item patch(JSONObject json) { + for (var field : json.keySet()){ + var known = true; + switch (field) { + case CODE: + code = json.getString(field); + break; + case NAME: + name = json.getString(field); + break; + default: + known = false; + } + if (known) dirtyFields.add(field); + } + return this; + } + public Collection properties() { return properties; } @@ -82,27 +111,4 @@ public class Item implements Mappable { public String toString() { return name; } - - public Item patch(JSONObject json) { - for (var field : json.keySet()){ - var known = true; - switch (field) { - case CODE: - code = json.getString(field); - break; - case NAME: - name = json.getString(field); - break; - default: - known = false; - } - if (known) dirtyFields.add(field); - } - return this; - } - - public Item clear() { - dirtyFields.clear(); - return this; - } } diff --git a/frontend/src/routes/stock/Index.svelte b/frontend/src/routes/stock/Index.svelte index 43078ec..d2a9e31 100644 --- a/frontend/src/routes/stock/Index.svelte +++ b/frontend/src/routes/stock/Index.svelte @@ -23,7 +23,7 @@ let top_level = $state(null); async function move_dragged_to(new_loc){ - const data = { item : draggedItem, target: new_loc }; + const data = { item : draggedItem.id, target: new_loc.id }; const url = api('stock/move_item'); const res = await fetch(url,{ credentials : 'include', @@ -32,7 +32,10 @@ }); if (res.ok){ yikes(); - } else error(res); + location = new_loc; + } else { + error(res); + } } async function loadLocation(){ diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java b/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java index 3360d90..f464bdd 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/Constants.java @@ -7,13 +7,16 @@ public class Constants { public static final String BELOW = "below"; public static final String CONFIG_DATABASE = "umbrella.modules.stock.database"; + public static final String ITEM = "item"; public static final String ITEM_ID = "item_id"; public static final String ITEMS = "items"; public static final String LOCATIONS = "locations"; + public static final String MOVE_ITEM = "move_item"; public static final String OF_USER = "of_user"; public static final String PROPERTY_ID = "prop_id"; public static final String TABLE_ITEMS = "items"; public static final String TABLE_ITEM_PROPERTIES = "item_props"; public static final String TABLE_LOCATIONS = "locations"; public static final String TABLE_PROPERTIES = "properties"; + public static final String TARGET = "target"; } diff --git a/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java b/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java index 0d52660..62b5016 100644 --- a/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java +++ b/stock/src/main/java/de/srsoftware/umbrella/stock/StockModule.java @@ -19,6 +19,7 @@ import de.srsoftware.tools.Path; import de.srsoftware.tools.SessionToken; import de.srsoftware.umbrella.core.BaseHandler; import de.srsoftware.umbrella.core.ModuleRegistry; +import de.srsoftware.umbrella.core.api.Owner; import de.srsoftware.umbrella.core.api.StockService; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.*; @@ -38,6 +39,14 @@ public class StockModule extends BaseHandler implements StockService { ModuleRegistry.add(this); } + private boolean assigned(Owner owner, UmbrellaUser user){ + owner = owner.resolve(); + if (owner instanceof UmbrellaUser u && user.id() == u.id()) return true; + if (owner instanceof Company comp) return companyService().membership(comp.id(),user.id()); + return false; + + } + @Override public boolean doGet(Path path, HttpExchange ex) throws IOException { addCors(ex); @@ -71,7 +80,11 @@ public class StockModule extends BaseHandler implements StockService { Optional token = SessionToken.from(ex).map(Token::of); var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); - return patchItem(user.get(),ex); + return switch (path.pop()){ + case MOVE_ITEM -> patchMove(user.get(), path,ex); + case null -> patchItem(user.get(),ex); + default -> super.doPatch(path,ex); + }; } catch (UmbrellaException e){ return send(ex,e); } @@ -167,6 +180,25 @@ public class StockModule extends BaseHandler implements StockService { return sendContent(ex,stockDb.save(item)); } + private boolean patchMove(UmbrellaUser user, Path path, HttpExchange ex) throws IOException { + var json = json(ex); + if (!(json.get(ITEM) instanceof Number itemId)) throw missingFieldException(ITEM); + if (!(json.get(TARGET) instanceof Number locationId)) throw missingFieldException(TARGET); + var item = stockDb.loadItem(itemId.longValue()); + + var itemOwner = item.owner().resolve(); + if (!assigned(itemOwner,user)) throw forbidden("You are not allowed to alter the location of \"{0}\"!",item.name()); + + var target = stockDb.loadLocation(locationId.longValue()); + var locOwner = target.resolve().owner().resolve(); + if (!assigned(locOwner,user)) throw forbidden("You are not allowed to modify \"{0}\"!",target.name()); + + if (!locOwner.equals(itemOwner)) throw unprocessable("You may not move items from one owner ({0}) to another ({1})",itemOwner,locOwner); + stockDb.save(item.location(target)); + + return sendContent(ex,item); + } + private boolean postProperty(UmbrellaUser user, HttpExchange ex) throws IOException { var json = json(ex); if (!(json.get(FIELD_ITEM) instanceof JSONObject itemData)) throw missingFieldException(FIELD_ITEM);