diff --git a/core/src/main/java/de/srsoftware/umbrella/core/model/WikiPage.java b/core/src/main/java/de/srsoftware/umbrella/core/model/WikiPage.java index a42d6c0..aca670a 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/model/WikiPage.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/model/WikiPage.java @@ -1,24 +1,24 @@ package de.srsoftware.umbrella.core.model; import de.srsoftware.tools.Mappable; +import de.srsoftware.umbrella.core.exceptions.UmbrellaException; +import org.json.JSONObject; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import static de.srsoftware.umbrella.core.Constants.*; import static de.srsoftware.umbrella.core.Util.markdown; public class WikiPage implements Mappable { - private final String id; - private final int version; + private String id; + private int version; private final List versions = new ArrayList<>(); private final Map members = new HashMap<>(); - private final String content; + private String content; + private Set dirtyFields = new HashSet<>(); public WikiPage(String id, int version, String content) { this.id = id; @@ -38,6 +38,28 @@ public class WikiPage implements Mappable { return new WikiPage(rs.getString(ID),rs.getInt(VERSION),rs.getString(CONTENT)); } + public WikiPage patch(JSONObject json) { + for (var key : json.keySet()){ + var val = json.get(key); + var altered = true; + switch (key){ + case ID: + if (!(val instanceof String s)) throw UmbrellaException.invalidFieldException(ID,"String"); + id = s; break; + case CONTENT: + if (!(val instanceof String s)) throw UmbrellaException.invalidFieldException(CONTENT,"String"); + content = s; break; + default: + altered = false; + } + if (altered) { + dirtyFields.add(key); + version++; + } + } + return this; + } + @Override public Map toMap() { var memberMap = new HashMap>(); diff --git a/frontend/src/routes/wiki/View.svelte b/frontend/src/routes/wiki/View.svelte index 6450ddc..8adc0a4 100644 --- a/frontend/src/routes/wiki/View.svelte +++ b/frontend/src/routes/wiki/View.svelte @@ -20,9 +20,21 @@ } } - async function onSet(newVal){ - console.log('TODO: implement patch',newVal); - return true; + async function patch(data){ + const url = api(`wiki/page/${id}`); + const res = await fetch(url,{ + credentials:'include', + method:'PATCH', + body:JSON.stringify(data) + }); + if (res.ok){ + return true; + error = null; + } else { + error = await res.text(); + return false; + } + } onMount(loadPage); @@ -32,5 +44,5 @@ {error} {/if} {#if page} - + patch({content:s})}> {/if} \ No newline at end of file diff --git a/wiki/src/main/java/de/srsoftware/umbrella/wiki/SqliteDb.java b/wiki/src/main/java/de/srsoftware/umbrella/wiki/SqliteDb.java index 1bae88b..2231ce8 100644 --- a/wiki/src/main/java/de/srsoftware/umbrella/wiki/SqliteDb.java +++ b/wiki/src/main/java/de/srsoftware/umbrella/wiki/SqliteDb.java @@ -2,6 +2,7 @@ package de.srsoftware.umbrella.wiki; import de.srsoftware.tools.jdbc.Condition; import de.srsoftware.umbrella.core.BaseDb; +import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.model.Hash; import de.srsoftware.umbrella.core.model.Permission; import de.srsoftware.umbrella.core.model.WikiPage; @@ -40,10 +41,10 @@ public class SqliteDb extends BaseDb implements WikiDb { return setCurrentVersion(1); } - private void createPagesUsersTable() { - var sql = "CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) NOT NULL, {2} INT NOT NULL, {3} INT NOT NULL, PRIMARY KEY({1}, {2}))"; + private void createPagesTable() { + var sql = "CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) NOT NULL, {2} INT NOT NULL, {3} TEXT NOT NULL, PRIMARY KEY({1},{2}))"; try { - var stmt = db.prepareStatement(format(sql, TABLE_PAGES_USERS, PAGE_ID, USER_ID, PERMISSIONS)); + var stmt = db.prepareStatement(format(sql, TABLE_PAGES, ID, VERSION, CONTENT)); stmt.execute(); stmt.close(); } catch (SQLException e) { @@ -52,10 +53,10 @@ public class SqliteDb extends BaseDb implements WikiDb { } } - private void createPagesTable() { - var sql = "CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) NOT NULL, {2} INT NOT NULL, {3} TEXT NOT NULL, PRIMARY KEY({1},{2}))"; + private void createPagesUsersTable() { + var sql = "CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) NOT NULL, {2} INT NOT NULL, {3} INT NOT NULL, PRIMARY KEY({1}, {2}))"; try { - var stmt = db.prepareStatement(format(sql, TABLE_PAGES, ID, VERSION, CONTENT)); + var stmt = db.prepareStatement(format(sql, TABLE_PAGES_USERS, PAGE_ID, USER_ID, PERMISSIONS)); stmt.execute(); stmt.close(); } catch (SQLException e) { @@ -114,4 +115,9 @@ public class SqliteDb extends BaseDb implements WikiDb { throw databaseException("Failed to load members of \"{0}\" from database!",page.id()); } } + + @Override + public WikiPage save(WikiPage page) { + throw UmbrellaException.unprocessable("save(Wikipage) not implemented"); + } } \ No newline at end of file diff --git a/wiki/src/main/java/de/srsoftware/umbrella/wiki/WikiDb.java b/wiki/src/main/java/de/srsoftware/umbrella/wiki/WikiDb.java index 7ca9ac4..435944c 100644 --- a/wiki/src/main/java/de/srsoftware/umbrella/wiki/WikiDb.java +++ b/wiki/src/main/java/de/srsoftware/umbrella/wiki/WikiDb.java @@ -15,4 +15,6 @@ public interface WikiDb { WikiPage load(String id); Map loadMembers(WikiPage page); + + WikiPage save(WikiPage page); } diff --git a/wiki/src/main/java/de/srsoftware/umbrella/wiki/WikiModule.java b/wiki/src/main/java/de/srsoftware/umbrella/wiki/WikiModule.java index 1735353..b16bdf8 100644 --- a/wiki/src/main/java/de/srsoftware/umbrella/wiki/WikiModule.java +++ b/wiki/src/main/java/de/srsoftware/umbrella/wiki/WikiModule.java @@ -20,7 +20,9 @@ import static de.srsoftware.umbrella.core.ConnectionProvider.connect; import static de.srsoftware.umbrella.core.Paths.PAGE; import static de.srsoftware.umbrella.core.Paths.VIEW; import static de.srsoftware.umbrella.core.Util.mapValues; +import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.forbidden; import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException; +import static de.srsoftware.umbrella.core.model.Permission.EDIT; import static de.srsoftware.umbrella.wiki.Constants.*; public class WikiModule extends BaseHandler implements WikiService { @@ -51,12 +53,36 @@ public class WikiModule extends BaseHandler implements WikiService { } } - private boolean getPage(Path path, UmbrellaUser user, HttpExchange ex) throws IOException { - var id = path.pop(); - if (id == null) throw missingFieldException(PAGE_ID); - return sendContent(ex, loadMembers(wikiDb.load(id))); + @Override + public boolean doPatch(Path path, HttpExchange ex) throws IOException { + addCors(ex); + try { + Optional token = SessionToken.from(ex).map(Token::of); + var user = userService().loadUser(token); + if (user.isEmpty()) return unauthorized(ex); + var head = path.pop(); + return switch (head) { + case null -> getUserPages(user.get(),ex); + case PAGE -> patchPage(path, user.get(), ex); + default -> super.doGet(path,ex); + }; + } catch (UmbrellaException e){ + return send(ex,e); + } } + private boolean getPage(Path path, UmbrellaUser user, HttpExchange ex) throws IOException { + var id = path.pop(); + var page = loadPage(id); + var permission = page.members().get(user.id()); + if (permission == null) throw forbidden("You are not allowed to access \"{0}\"!",id); + return sendContent(ex, page); + } + + private boolean getUserPages(UmbrellaUser user, HttpExchange ex) throws IOException { + var pageList = wikiDb.listUserPages(user.id()); + return sendContent(ex,pageList); + } private WikiPage loadMembers(WikiPage page) { var members = wikiDb.loadMembers(page); @@ -71,9 +97,17 @@ public class WikiModule extends BaseHandler implements WikiService { return page; } - private boolean getUserPages(UmbrellaUser user, HttpExchange ex) throws IOException { - var pageList = wikiDb.listUserPages(user.id()); - return sendContent(ex,pageList); + private WikiPage loadPage(String id){ + if (id == null) throw missingFieldException(PAGE_ID); + return loadMembers(wikiDb.load(id)); } + private boolean patchPage(Path path, UmbrellaUser user, HttpExchange ex) throws IOException { + var id = path.pop(); + var page = loadPage(id); + var member = page.members().get(user.id()); + if (member == null || member.permission() != EDIT) throw forbidden("You are not allowed to edit {0}!",id); + var json = json(ex); + return sendContent(ex,wikiDb.save(page.patch(json))); + } }