started implementing poll backend
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -23,6 +23,7 @@ dependencies{
|
|||||||
implementation(project(":markdown"))
|
implementation(project(":markdown"))
|
||||||
implementation(project(":messages"))
|
implementation(project(":messages"))
|
||||||
implementation(project(":notes"))
|
implementation(project(":notes"))
|
||||||
|
implementation(project(":poll"))
|
||||||
implementation(project(":project"))
|
implementation(project(":project"))
|
||||||
implementation(project(":stock"))
|
implementation(project(":stock"))
|
||||||
implementation(project(":tags"))
|
implementation(project(":tags"))
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import de.srsoftware.umbrella.markdown.MarkdownApi;
|
|||||||
import de.srsoftware.umbrella.message.MessageSystem;
|
import de.srsoftware.umbrella.message.MessageSystem;
|
||||||
import de.srsoftware.umbrella.messagebus.MessageApi;
|
import de.srsoftware.umbrella.messagebus.MessageApi;
|
||||||
import de.srsoftware.umbrella.notes.NoteModule;
|
import de.srsoftware.umbrella.notes.NoteModule;
|
||||||
|
import de.srsoftware.umbrella.poll.PollModule;
|
||||||
import de.srsoftware.umbrella.project.ProjectModule;
|
import de.srsoftware.umbrella.project.ProjectModule;
|
||||||
import de.srsoftware.umbrella.stock.StockModule;
|
import de.srsoftware.umbrella.stock.StockModule;
|
||||||
import de.srsoftware.umbrella.tags.TagModule;
|
import de.srsoftware.umbrella.tags.TagModule;
|
||||||
@@ -81,6 +82,7 @@ public class Application {
|
|||||||
new MarkdownApi().bindPath("/api/markdown").on(server);
|
new MarkdownApi().bindPath("/api/markdown").on(server);
|
||||||
new NoteModule(config).bindPath("/api/notes").on(server);
|
new NoteModule(config).bindPath("/api/notes").on(server);
|
||||||
new StockModule(config).bindPath("/api/stock").on(server);
|
new StockModule(config).bindPath("/api/stock").on(server);
|
||||||
|
new PollModule(config).bindPath("/api/poll").on(server);
|
||||||
new ProjectModule(config).bindPath("/api/project").on(server);
|
new ProjectModule(config).bindPath("/api/project").on(server);
|
||||||
new ProjectLegacy(config).bindPath("/legacy/project").on(server);
|
new ProjectLegacy(config).bindPath("/legacy/project").on(server);
|
||||||
new TaskModule(config).bindPath("/api/task").on(server);
|
new TaskModule(config).bindPath("/api/task").on(server);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ public class ModuleRegistry {
|
|||||||
private FileService fileService;
|
private FileService fileService;
|
||||||
private MarkdownService markdownService;
|
private MarkdownService markdownService;
|
||||||
private NoteService noteService;
|
private NoteService noteService;
|
||||||
|
private PollService pollService;
|
||||||
private PostBox postBox;
|
private PostBox postBox;
|
||||||
private ProjectService projectService;
|
private ProjectService projectService;
|
||||||
private StockService stockService;
|
private StockService stockService;
|
||||||
@@ -33,9 +34,10 @@ public class ModuleRegistry {
|
|||||||
case ContactService cs: singleton.contactService = cs; break;
|
case ContactService cs: singleton.contactService = cs; break;
|
||||||
case DocumentService ds: singleton.documentService = ds; break;
|
case DocumentService ds: singleton.documentService = ds; break;
|
||||||
case FileService fs: singleton.fileService = fs; break;
|
case FileService fs: singleton.fileService = fs; break;
|
||||||
case StockService is: singleton.stockService = is; break;
|
case StockService is: singleton.stockService = is; break;
|
||||||
case MarkdownService ms: singleton.markdownService = ms; break;
|
case MarkdownService ms: singleton.markdownService = ms; break;
|
||||||
case NoteService ns: singleton.noteService = ns; break;
|
case NoteService ns: singleton.noteService = ns; break;
|
||||||
|
case PollService ps: singleton.pollService = ps; break;
|
||||||
case PostBox pb: singleton.postBox = pb; break;
|
case PostBox pb: singleton.postBox = pb; break;
|
||||||
case ProjectService ps: singleton.projectService = ps; break;
|
case ProjectService ps: singleton.projectService = ps; break;
|
||||||
case TagService ts: singleton.tagService = ts; break;
|
case TagService ts: singleton.tagService = ts; break;
|
||||||
@@ -81,6 +83,10 @@ public class ModuleRegistry {
|
|||||||
return singleton.noteService;
|
return singleton.noteService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PollService pollService() {
|
||||||
|
return singleton.pollService;
|
||||||
|
}
|
||||||
|
|
||||||
public static PostBox postBox() {
|
public static PostBox postBox() {
|
||||||
return singleton.postBox;
|
return singleton.postBox;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.core.api;
|
package de.srsoftware.umbrella.core.api;
|
||||||
|
|
||||||
public interface PollService {
|
public interface PollService {
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package de.srsoftware.umbrella.core.model;
|
||||||
|
|
||||||
|
import de.srsoftware.tools.Mappable;
|
||||||
|
import de.srsoftware.umbrella.core.ModuleRegistry;
|
||||||
|
import de.srsoftware.umbrella.core.Util;
|
||||||
|
import de.srsoftware.umbrella.core.api.Owner;
|
||||||
|
import de.srsoftware.umbrella.core.constants.Field;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public record Poll(String id, Owner owner, String name, String description, boolean isPrivate) implements Mappable {
|
||||||
|
public static Poll of(ResultSet rs) throws SQLException {
|
||||||
|
var id = rs.getString(Field.ID);
|
||||||
|
var userId = rs.getLong(Field.USER_ID);
|
||||||
|
var name = rs.getString(Field.NAME);
|
||||||
|
var description = rs.getString(Field.DESCRIPTION);
|
||||||
|
var isPrivate = rs.getBoolean(Field.PRIVATE);
|
||||||
|
var owner = ModuleRegistry.userService().loadUser(userId);
|
||||||
|
return new Poll(id,owner,name,description,isPrivate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> toMap() {
|
||||||
|
return Map.of(
|
||||||
|
Field.ID, id,
|
||||||
|
Field.OWNER, owner.toMap(),
|
||||||
|
Field.NAME,name,
|
||||||
|
Field.DESCRIPTION, Map.of(
|
||||||
|
Field.SOURCE,description,
|
||||||
|
Field.RENDERED,Util.markdown(description)
|
||||||
|
),
|
||||||
|
Field.PRIVATE, isPrivate
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.poll;
|
package de.srsoftware.umbrella.poll;
|
||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
public static final String CONFIG_DATABASE = "de.umbrella.module.polls";
|
public static final String CONFIG_DATABASE = "umbrella.modules.poll.database";
|
||||||
public static final String TABLE_OPTIONS = "options";
|
public static final String TABLE_OPTIONS = "options";
|
||||||
public static final String TABLE_POLLS = "polls";
|
public static final String TABLE_POLLS = "polls";
|
||||||
public static final String TABLE_SELECTIONS = "selections";
|
public static final String TABLE_SELECTIONS = "selections";
|
||||||
|
public static final String TABLE_SHARES = "shares";
|
||||||
public static final String TABLE_WEIGHTS = "weights";
|
public static final String TABLE_WEIGHTS = "weights";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.poll;
|
package de.srsoftware.umbrella.poll;
|
||||||
|
|
||||||
|
import de.srsoftware.umbrella.core.model.Poll;
|
||||||
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
public interface PollDb {
|
public interface PollDb {
|
||||||
|
Collection<Poll> listPolls(UmbrellaUser user);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,56 @@
|
|||||||
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.poll;
|
package de.srsoftware.umbrella.poll;
|
||||||
|
|
||||||
|
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
||||||
|
import static de.srsoftware.umbrella.core.ModuleRegistry.userService;
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Path.LIST;
|
||||||
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingField;
|
||||||
|
import static de.srsoftware.umbrella.poll.Constants.CONFIG_DATABASE;
|
||||||
|
|
||||||
|
import com.sun.net.httpserver.HttpExchange;
|
||||||
import de.srsoftware.configuration.Configuration;
|
import de.srsoftware.configuration.Configuration;
|
||||||
|
import de.srsoftware.tools.Path;
|
||||||
|
import de.srsoftware.tools.SessionToken;
|
||||||
import de.srsoftware.umbrella.core.BaseHandler;
|
import de.srsoftware.umbrella.core.BaseHandler;
|
||||||
import de.srsoftware.umbrella.core.ModuleRegistry;
|
import de.srsoftware.umbrella.core.ModuleRegistry;
|
||||||
import de.srsoftware.umbrella.core.api.PollService;
|
import de.srsoftware.umbrella.core.api.PollService;
|
||||||
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
|
import de.srsoftware.umbrella.core.model.Token;
|
||||||
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
|
|
||||||
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
import java.io.IOException;
|
||||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingField;
|
import java.util.Optional;
|
||||||
import static de.srsoftware.umbrella.poll.Constants.CONFIG_DATABASE;
|
|
||||||
|
|
||||||
public class PollModule extends BaseHandler implements PollService {
|
public class PollModule extends BaseHandler implements PollService {
|
||||||
|
|
||||||
private PollDb pollDb;
|
private PollDb pollDb;
|
||||||
|
|
||||||
PollModule(Configuration config){
|
public PollModule(Configuration config){
|
||||||
super();
|
super();
|
||||||
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingField(CONFIG_DATABASE));
|
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingField(CONFIG_DATABASE));
|
||||||
pollDb = new SqliteDb(connect(dbFile));
|
pollDb = new SqliteDb(connect(dbFile));
|
||||||
ModuleRegistry.add(this);
|
ModuleRegistry.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doGet(Path path, HttpExchange ex) throws IOException {
|
||||||
|
addCors(ex);
|
||||||
|
try {
|
||||||
|
Optional<Token> 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 LIST -> getPollList(ex,user.get());
|
||||||
|
case null, default -> super.doGet(path,ex);
|
||||||
|
};
|
||||||
|
} catch (UmbrellaException e){
|
||||||
|
return send(ex,e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean getPollList(HttpExchange ex, UmbrellaUser user) throws IOException {
|
||||||
|
var list = pollDb.listPolls(user);
|
||||||
|
return sendContent(ex,list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,25 @@
|
|||||||
|
/* © SRSoftware 2025 */
|
||||||
package de.srsoftware.umbrella.poll;
|
package de.srsoftware.umbrella.poll;
|
||||||
|
|
||||||
|
import static de.srsoftware.tools.jdbc.Condition.equal;
|
||||||
|
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
|
||||||
|
import static de.srsoftware.tools.jdbc.Query.select;
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Field.*;
|
||||||
|
import static de.srsoftware.umbrella.core.constants.Field.DESCRIPTION;
|
||||||
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
||||||
|
import static de.srsoftware.umbrella.poll.Constants.*;
|
||||||
|
import static java.text.MessageFormat.format;
|
||||||
|
|
||||||
import de.srsoftware.umbrella.core.BaseDb;
|
import de.srsoftware.umbrella.core.BaseDb;
|
||||||
import de.srsoftware.umbrella.core.constants.Field;
|
import de.srsoftware.umbrella.core.constants.Field;
|
||||||
|
import de.srsoftware.umbrella.core.model.Poll;
|
||||||
|
import de.srsoftware.umbrella.core.model.UmbrellaUser;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.*;
|
import java.util.Collection;
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.DESCRIPTION;
|
import java.util.List;
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.SHOW_CLOSED;
|
|
||||||
import static de.srsoftware.umbrella.core.constants.Field.STATUS;
|
|
||||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.failedToCreateTable;
|
|
||||||
import static de.srsoftware.umbrella.core.model.Status.OPEN;
|
|
||||||
import static de.srsoftware.umbrella.poll.Constants.*;
|
|
||||||
import static java.text.MessageFormat.format;
|
|
||||||
|
|
||||||
public class SqliteDb extends BaseDb implements PollDb {
|
public class SqliteDb extends BaseDb implements PollDb {
|
||||||
|
|
||||||
@@ -48,7 +54,7 @@ public class SqliteDb extends BaseDb implements PollDb {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createPollsTable() {
|
private void createPollsTable() {
|
||||||
var sql = "CREATE TABLE IF NOT EXISTS {0} ({1} VARCHAR(255) NOT NULL PRIMARY_KEY, {2} INT NOT NULL, {3} VARCHAR(255) NOT NULL, {4} TEXT, {5} BOOLEAN)";
|
var sql = "CREATE TABLE IF NOT EXISTS {0} ({1} VARCHAR(255) NOT NULL PRIMARY KEY, {2} INT NOT NULL, {3} VARCHAR(255) NOT NULL, {4} TEXT, {5} BOOLEAN)";
|
||||||
try {
|
try {
|
||||||
var stmt = db.prepareStatement(format(sql,TABLE_POLLS, Field.ID,Field.USER_ID,Field.NAME,Field.DESCRIPTION, Field.PRIVATE));
|
var stmt = db.prepareStatement(format(sql,TABLE_POLLS, Field.ID,Field.USER_ID,Field.NAME,Field.DESCRIPTION, Field.PRIVATE));
|
||||||
stmt.execute();
|
stmt.execute();
|
||||||
@@ -69,8 +75,19 @@ public class SqliteDb extends BaseDb implements PollDb {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createSharesTable() {
|
||||||
|
var sql = "CREATE TABLE IF NOT EXISTS {0} ({1} VARCHAR(255) NOT NULL REFERENCES {2}({3}), {4} INT NOT NULL, {5} INT, PRIMARY KEY ({1}, {4}))";
|
||||||
|
try {
|
||||||
|
var stmt = db.prepareStatement(format(sql,TABLE_SHARES,POLL_ID,TABLE_POLLS,ID,USER_ID, PERMISSION));
|
||||||
|
stmt.execute();
|
||||||
|
stmt.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw failedToCreateTable(TABLE_SHARES).causedBy(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void createWeightsTable(){
|
private void createWeightsTable(){
|
||||||
var sql = "CREATE TABLE {0} ( {1} INT NOT NULL, {2} VARCHAR(255) NOT NULL REFERENCES {3}({4}), {5} TEXT, PRIMARY KEY ({2}, {1}))"
|
var sql = "CREATE TABLE {0} ( {1} INT NOT NULL, {2} VARCHAR(255) NOT NULL REFERENCES {3}({4}), {5} TEXT, PRIMARY KEY ({2}, {1}))";
|
||||||
try {
|
try {
|
||||||
var stmt = db.prepareStatement(format(sql,TABLE_WEIGHTS, WEIGHT,POLL_ID,TABLE_POLLS, ID, DESCRIPTION));
|
var stmt = db.prepareStatement(format(sql,TABLE_WEIGHTS, WEIGHT,POLL_ID,TABLE_POLLS, ID, DESCRIPTION));
|
||||||
stmt.execute();
|
stmt.execute();
|
||||||
@@ -79,5 +96,18 @@ public class SqliteDb extends BaseDb implements PollDb {
|
|||||||
throw failedToCreateTable(TABLE_WEIGHTS).causedBy(e);
|
throw failedToCreateTable(TABLE_WEIGHTS).causedBy(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Poll> listPolls(UmbrellaUser user) {
|
||||||
|
// TODO
|
||||||
|
try {
|
||||||
|
var rs = select(ALL).from(TABLE_POLLS).where(USER_ID,equal(user.id())).exec(db);
|
||||||
|
var list = new ArrayList<Poll>();
|
||||||
|
while (rs.next()) list.add(Poll.of(rs));
|
||||||
|
return list;
|
||||||
|
} catch (SQLException sqle){
|
||||||
|
throw failedToLoadObject(TABLE_POLLS);
|
||||||
|
}
|
||||||
|
return List.of();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,12 +33,10 @@ import de.srsoftware.umbrella.core.constants.Text;
|
|||||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||||
import de.srsoftware.umbrella.core.model.*;
|
import de.srsoftware.umbrella.core.model.*;
|
||||||
import de.srsoftware.umbrella.core.model.Location;
|
import de.srsoftware.umbrella.core.model.Location;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import de.srsoftware.umbrella.messagebus.events.Event;
|
import de.srsoftware.umbrella.messagebus.events.Event;
|
||||||
import de.srsoftware.umbrella.messagebus.events.ItemEvent;
|
import de.srsoftware.umbrella.messagebus.events.ItemEvent;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.*;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class StockModule extends BaseHandler implements StockService {
|
public class StockModule extends BaseHandler implements StockService {
|
||||||
|
|||||||
Reference in New Issue
Block a user