From a50a451b95dc9517e13ad6d0b0f89fa72d9e97e0 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Sun, 17 Aug 2025 23:31:06 +0200 Subject: [PATCH] conveniance modification: added registry and getters for modules to BaseHandler Signed-off-by: Stephan Richter --- .../umbrella/backend/Application.java | 2 +- .../umbrella/bookmarks/BookmarkApi.java | 11 +-- .../umbrella/company/CompanyModule.java | 21 ++-- .../srsoftware/umbrella/core/BaseHandler.java | 47 ++++++++- .../umbrella/core/ModuleRegistry.java | 97 +++++++------------ .../umbrella/documents/DocumentApi.java | 35 ++++--- .../de/srsoftware/umbrella/items/ItemApi.java | 9 +- .../umbrella/legacy/CompanyLegacy.java | 7 +- .../umbrella/legacy/NotesLegacy.java | 9 +- .../umbrella/legacy/ProjectLegacy.java | 7 +- .../umbrella/legacy/TaskLegacy.java | 72 ++++++++++++++ .../umbrella/legacy/UserLegacy.java | 17 ++-- .../umbrella/markdown/MarkdownApi.java | 5 +- .../umbrella/message/MessageApi.java | 14 --- .../srsoftware/umbrella/notes/NoteModule.java | 13 ++- .../umbrella/project/ProjectModule.java | 25 +++-- .../srsoftware/umbrella/tags/TagModule.java | 9 +- .../srsoftware/umbrella/task/TaskModule.java | 37 ++++--- .../srsoftware/umbrella/time/TimeModule.java | 11 +-- .../srsoftware/umbrella/user/UserModule.java | 5 +- .../srsoftware/umbrella/web/WebHandler.java | 5 + 21 files changed, 260 insertions(+), 198 deletions(-) create mode 100644 legacy/src/main/java/de/srsoftware/umbrella/legacy/TaskLegacy.java delete mode 100644 messages/src/main/java/de/srsoftware/umbrella/message/MessageApi.java diff --git a/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java b/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java index 1bbe406..1d6e586 100644 --- a/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java +++ b/backend/src/main/java/de/srsoftware/umbrella/backend/Application.java @@ -80,7 +80,7 @@ public class Application { new ProjectLegacy(registry,config).bindPath("/legacy/project").on(server); new TaskModule(registry, config).bindPath("/api/task").on(server); new TimeModule(registry, config).bindPath("/api/times").on(server); - new WebHandler().bindPath("/").on(server); + new WebHandler(registry).bindPath("/").on(server); server.setExecutor(Executors.newFixedThreadPool(threads)); server.start(); diff --git a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkApi.java b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkApi.java index 47b2444..f31033e 100644 --- a/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkApi.java +++ b/bookmark/src/main/java/de/srsoftware/umbrella/bookmarks/BookmarkApi.java @@ -26,12 +26,11 @@ import org.json.JSONArray; public class BookmarkApi extends BaseHandler implements BookmarkService { private final BookmarkDb db; - private final ModuleRegistry registry; public BookmarkApi(ModuleRegistry registry, Configuration config) { + super(registry); var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); db = new SqliteDb(connect(dbFile)); - this.registry = registry.add(this); } @Override @@ -39,7 +38,7 @@ public class BookmarkApi extends BaseHandler implements BookmarkService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -59,7 +58,7 @@ public class BookmarkApi extends BaseHandler implements BookmarkService { private boolean getBookmark(UmbrellaUser user, long id, HttpExchange ex) throws IOException { var bookmark = db.load(id,user.id()); - registry.tagService().getTags(BOOKMARK, id, user).forEach(bookmark.tags()::add); + tagService().getTags(BOOKMARK, id, user).forEach(bookmark.tags()::add); return sendContent(ex,bookmark); } @@ -68,7 +67,7 @@ public class BookmarkApi extends BaseHandler implements BookmarkService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -115,7 +114,7 @@ public class BookmarkApi extends BaseHandler implements BookmarkService { if (json.has(TAGS) && json.get(TAGS) instanceof JSONArray tagList){ var list = tagList.toList().stream().map(Object::toString).toList(); - registry.tagService().save(BOOKMARK,bookmark.urlId(), userList, list); + tagService().save(BOOKMARK,bookmark.urlId(), userList, list); } return sendContent(ex,bookmark); } diff --git a/company/src/main/java/de/srsoftware/umbrella/company/CompanyModule.java b/company/src/main/java/de/srsoftware/umbrella/company/CompanyModule.java index 9d54888..726b198 100644 --- a/company/src/main/java/de/srsoftware/umbrella/company/CompanyModule.java +++ b/company/src/main/java/de/srsoftware/umbrella/company/CompanyModule.java @@ -24,20 +24,19 @@ import java.util.*; public class CompanyModule extends BaseHandler implements CompanyService { private final CompanyDb companyDb; - private final ModuleRegistry registry; public CompanyModule(ModuleRegistry registry, Configuration config) throws UmbrellaException { + super(registry); var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); companyDb = new SqliteDb(connect(dbFile)); - this.registry = registry.add(this); } private boolean deleteCompany(long companyId, UmbrellaUser user, HttpExchange ex) throws IOException { var company = get(companyId); if (!membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); - if (!registry.documentService().list(companyId).isEmpty()) throw forbidden("There are documents owned by {0}",company.name()); - if (!registry.itemService().list(companyId).isEmpty()) throw forbidden("There are items owned by {0}",company.name()); - if (!registry.projectService().listCompanyProjects(companyId,true).isEmpty()) throw forbidden("There are projects owned by {0}",company.name()); + if (!documentService().list(companyId).isEmpty()) throw forbidden("There are documents owned by {0}",company.name()); + if (!itemService().list(companyId).isEmpty()) throw forbidden("There are items owned by {0}",company.name()); + if (!projectService().listCompanyProjects(companyId,true).isEmpty()) throw forbidden("There are projects owned by {0}",company.name()); return sendContent(ex, companyDb.drop(companyId)); } @@ -46,7 +45,7 @@ public class CompanyModule extends BaseHandler implements CompanyService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -65,7 +64,7 @@ public class CompanyModule extends BaseHandler implements CompanyService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head){ @@ -83,7 +82,7 @@ public class CompanyModule extends BaseHandler implements CompanyService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -102,7 +101,7 @@ public class CompanyModule extends BaseHandler implements CompanyService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -130,7 +129,7 @@ public class CompanyModule extends BaseHandler implements CompanyService { @Override public Collection getMembers(long companyId) throws UmbrellaException { var members = new HashSet(); - for (var userId : companyDb.getMembers(companyId)) members.add(registry.userService().loadUser(userId)); + for (var userId : companyDb.getMembers(companyId)) members.add(userService().loadUser(userId)); return members; } @@ -148,7 +147,7 @@ public class CompanyModule extends BaseHandler implements CompanyService { var userMap = new HashMap(); for (var company : companyList){ for (var userId : companyDb.getMembers(company.id())){ - var user = userMap.computeIfAbsent(userId,k -> registry.userService().loadUser(userId)); + var user = userMap.computeIfAbsent(userId,k -> userService().loadUser(userId)); company.members().put(userId,user); } } diff --git a/core/src/main/java/de/srsoftware/umbrella/core/BaseHandler.java b/core/src/main/java/de/srsoftware/umbrella/core/BaseHandler.java index 03af3d2..10124a8 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/BaseHandler.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/BaseHandler.java @@ -9,6 +9,7 @@ import static java.net.HttpURLConnection.*; import com.sun.net.httpserver.HttpExchange; import de.srsoftware.tools.Path; import de.srsoftware.tools.PathHandler; +import de.srsoftware.umbrella.core.api.*; import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -16,8 +17,14 @@ import java.util.List; public abstract class BaseHandler extends PathHandler { + private final ModuleRegistry registry; + public record Page(String mime, byte[] bytes){} + public BaseHandler(ModuleRegistry registry){ + this.registry = registry.add(this); + } + public HttpExchange addCors(HttpExchange ex){ var headers = ex.getRequestHeaders(); var origin = nullable(headers.get("Origin")).orElse(List.of()).stream().filter(url -> url.contains("://localhost")||url.contains("://127.0.0.1")).findAny(); @@ -34,11 +41,23 @@ public abstract class BaseHandler extends PathHandler { return ex; } + public CompanyService companyService(){ + return registry.companyService(); + } + + public DocumentService documentService(){ + return registry.documentService(); + } + @Override public boolean doOptions(Path path, HttpExchange ex) throws IOException { return ok(addCors(ex)); } + public ItemService itemService(){ + return registry.itemService(); + } + public boolean load(Path path, HttpExchange ex) throws IOException { try { var doc = load(path.toString()); @@ -65,17 +84,43 @@ public abstract class BaseHandler extends PathHandler { } } + public NoteService noteService(){ + return registry.noteService(); + } + public boolean ok(HttpExchange ex) throws IOException { return sendEmptyResponse(HTTP_OK,ex); } + public PostBox postBox() { + return registry.postBox(); + } + + public ProjectService projectService(){ + return registry.projectService(); + } + public boolean send(HttpExchange ex, UmbrellaException e) throws IOException { return sendContent(ex,e.statusCode(),e.getMessage()); } + public TagService tagService(){ + return registry.tagService(); + } + + public TaskService taskService(){ + return registry.taskService(); + } + + public Translator translator(){ + return registry.translator(); + } + public boolean unauthorized(HttpExchange ex) throws IOException { return sendEmptyResponse(HTTP_UNAUTHORIZED,ex); } - + public UserService userService(){ + return registry.userService(); + } } diff --git a/core/src/main/java/de/srsoftware/umbrella/core/ModuleRegistry.java b/core/src/main/java/de/srsoftware/umbrella/core/ModuleRegistry.java index d052247..a2d5dfb 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/ModuleRegistry.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/ModuleRegistry.java @@ -1,86 +1,47 @@ /* © SRSoftware 2025 */ package de.srsoftware.umbrella.core; +import static java.text.MessageFormat.format; + import de.srsoftware.umbrella.core.api.*; public class ModuleRegistry { - private Translator translator; - private PostBox postBox; - private UserService userService; - private TagService tagService; private BookmarkService bookmarkService; private CompanyService companyService; private DocumentService documentService; private ItemService itemService; private MarkdownService markdownService; private NoteService noteService; + private PostBox postBox; private ProjectService projectService; + private TagService tagService; private TaskService taskService; private TimeService timeService; + private Translator translator; + private UserService userService; - public ModuleRegistry add(BookmarkService bookmarkService) { - this.bookmarkService = bookmarkService; - return this; - } - - public ModuleRegistry add(CompanyService companyService) { - this.companyService = companyService; - return this; - } - - public ModuleRegistry add(DocumentService documentService) { - this.documentService = documentService; - return this; - } - - public ModuleRegistry add(ItemService itemService) { - this.itemService = itemService; - return this; - } - - public ModuleRegistry add(MarkdownService markdownService) { - this.markdownService = markdownService; - return this; - } - - public ModuleRegistry add(NoteService noteService) { - this.noteService = noteService; - return this; - } - - public ModuleRegistry add(PostBox postBox) { - this.postBox = postBox; - return this; - } - - public ModuleRegistry add(ProjectService projectService) { - this.projectService = projectService; - return this; - } - - public ModuleRegistry add(TagService tagService) { - this.tagService = tagService; - return this; - } - - public ModuleRegistry add(TaskService taskService) { - this.taskService = taskService; - return this; - } - - public ModuleRegistry add(TimeService timeService) { - this.timeService = timeService; + public ModuleRegistry add(Object service) { + switch (service) { + case BookmarkService bs: bookmarkService = bs; break; + case CompanyService cs: companyService = cs; break; + case DocumentService ds: documentService = ds; break; + case ItemService is: itemService = is; break; + case MarkdownService ms: markdownService = ms; break; + case NoteService ns: noteService = ns; break; + case PostBox pb: postBox = pb; break; + case ProjectService ps: projectService = ps; break; + case TagService ts: tagService = ts; break; + case TaskService ts: taskService = ts; break; + case TimeService ts: timeService = ts; break; + case Translator tr: translator = tr; break; + case UserService us: userService = us; break; + default: throw new RuntimeException(format("Trying to add unknown service ({0}) to {1}",service.getClass().getSimpleName(),getClass().getSimpleName())); + } return this; } - public ModuleRegistry add(Translator translator) { - this.translator = translator; - return this; - } - - public ModuleRegistry add(UserService userService) { - this.userService = userService; - return this; + public BookmarkService bookmarkService(){ + return bookmarkService; } public CompanyService companyService(){ @@ -95,6 +56,10 @@ public class ModuleRegistry { return itemService; } + public MarkdownService markdownService(){ + return markdownService; + } + public NoteService noteService(){ return noteService; } @@ -115,6 +80,10 @@ public class ModuleRegistry { return taskService; } + public TimeService timeService(){ + return timeService; + } + public Translator translator(){ return translator; } diff --git a/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java b/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java index 1913af0..6f24e94 100644 --- a/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java +++ b/documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java @@ -74,13 +74,12 @@ public class DocumentApi extends BaseHandler implements DocumentService { private final Configuration config; private final DocumentDb db; - private final ModuleRegistry modules; public DocumentApi(ModuleRegistry registry, Configuration config) throws UmbrellaException { + super(registry); this.config = config; var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); db = new SqliteDb(connect(dbFile)); - modules = registry.add(this); Optional templates = config.get(CONFIG_TEMPLATES); if (templates.isEmpty()) throw missingFieldException(CONFIG_TEMPLATES); @@ -95,7 +94,7 @@ public class DocumentApi extends BaseHandler implements DocumentService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = modules.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); long docId = Long.parseLong(head); @@ -114,7 +113,7 @@ public class DocumentApi extends BaseHandler implements DocumentService { private boolean deleteDocument(HttpExchange ex, long docId, UmbrellaUser user) throws IOException, UmbrellaException { var doc = db.loadDoc(docId); var companyId = doc.companyId(); - if (!modules.companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",doc.companyId()); + if (!companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",doc.companyId()); if (doc.state() != NEW) throw new UmbrellaException(HTTP_BAD_REQUEST,"This document has already been sent"); return sendContent(ex,db.deleteDoc(docId)); } @@ -122,7 +121,7 @@ public class DocumentApi extends BaseHandler implements DocumentService { private boolean deletePosition(HttpExchange ex, long docId, UmbrellaUser user) throws UmbrellaException, IOException { var doc = db.loadDoc(docId); var companyId = doc.companyId(); - if (!modules.companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",doc.companyId()); + if (!companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",doc.companyId()); if (doc.state() != NEW) throw new UmbrellaException(HTTP_BAD_REQUEST,"This document has already been sent"); var json = json(ex); if (!(json.has(POSITION) && json.get(POSITION) instanceof Number number)) throw missingFieldException(POSITION); @@ -135,7 +134,7 @@ public class DocumentApi extends BaseHandler implements DocumentService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = modules.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head){ @@ -166,7 +165,7 @@ public class DocumentApi extends BaseHandler implements DocumentService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = modules.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); var docId = Long.parseLong(head); @@ -188,7 +187,7 @@ public class DocumentApi extends BaseHandler implements DocumentService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = modules.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head){ @@ -220,7 +219,7 @@ public class DocumentApi extends BaseHandler implements DocumentService { var attachment = new Attachment(doc.number()+".pdf",rendered.mimeType(),rendered.bytes()); var message = new Message(user,subject,content,null,List.of(attachment)); var envelope = new Envelope(message,new User(doc.customer().shortName(),new EmailAddress(email),doc.customer().language())); - modules.postBox().send(envelope); + postBox().send(envelope); db.save(doc.set(SENT)); return ok(ex); } @@ -245,8 +244,8 @@ public class DocumentApi extends BaseHandler implements DocumentService { private Tuple getDocument(long docId, UmbrellaUser user) throws UmbrellaException { var doc = db.loadDoc(docId); var companyId = doc.companyId(); - var company = modules.companyService().get(companyId); - if (!modules.companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); + var company = companyService().get(companyId); + if (!companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); return Tuple.of(doc,company); } @@ -365,7 +364,7 @@ public class DocumentApi extends BaseHandler implements DocumentService { .filter(filter) .findAny(); if (optDoc.isEmpty()) throw UmbrellaException.notFound("Cannot render {0} {1}: Missing template \"{2}\"",type,document.number(),template); - Function translate = text -> modules.translator().translate(user.language(),text); + Function translate = text -> translator().translate(user.language(),text); var pdfData = new HashMap(); pdfData.put(FIELD_DOCUMENT,document.renderToMap()); pdfData.put("translate",translate); @@ -419,8 +418,8 @@ public class DocumentApi extends BaseHandler implements DocumentService { var json = json(ex); if (!json.has(COMPANY)) throw missingFieldException(COMPANY); long companyId = json.getLong(COMPANY); - var company = modules.companyService().get(companyId); - if (!modules.companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company); + var company = companyService().get(companyId); + if (!companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company); var docs = list(companyId); var map = new HashMap(); for (var entry : docs.entrySet()) map.put(entry.getKey(),entry.getValue().summary()); @@ -466,8 +465,8 @@ public class DocumentApi extends BaseHandler implements DocumentService { if (!(json.has(SENDER) && json.get(SENDER) instanceof JSONObject senderData)) throw missingFieldException(SENDER); if (!senderData.has(FIELD_COMPANY) || !(senderData.get(FIELD_COMPANY) instanceof Number companyId)) throw missingFieldException(FIELD_COMPANY); - var company = modules.companyService().get(companyId.longValue()); - if (!modules.companyService().membership(companyId.longValue(),user.id())) throw forbidden("You are mot a member of company {0}",company); + var company = companyService().get(companyId.longValue()); + if (!companyService().membership(companyId.longValue(),user.id())) throw forbidden("You are mot a member of company {0}",company); if (!json.has(FIELD_CUSTOMER) || !(json.get(FIELD_CUSTOMER) instanceof JSONObject customerData)) throw missingFieldException(FIELD_CUSTOMER); if (!json.has(FIELD_TYPE) || !(json.get(FIELD_TYPE) instanceof Number docTypeId)) throw missingFieldException(FIELD_TYPE); @@ -513,8 +512,8 @@ public class DocumentApi extends BaseHandler implements DocumentService { private boolean postTemplateList(HttpExchange ex, UmbrellaUser user) throws UmbrellaException, IOException { var json = json(ex); if (!(json.has(COMPANY) && json.get(COMPANY) instanceof Number companyId)) throw missingFieldException(COMPANY); - var company = modules.companyService().get(companyId.longValue()); - if (!modules.companyService().membership(companyId.longValue(),user.id())) throw forbidden("You are not a member of {0}",company.name()); + var company = companyService().get(companyId.longValue()); + if (!companyService().membership(companyId.longValue(),user.id())) throw forbidden("You are not a member of {0}",company.name()); var templates = db.getCompanyTemplates(companyId.longValue()); return sendContent(ex,templates.stream().map(Template::toMap)); } diff --git a/items/src/main/java/de/srsoftware/umbrella/items/ItemApi.java b/items/src/main/java/de/srsoftware/umbrella/items/ItemApi.java index 36c48e9..a6e585c 100644 --- a/items/src/main/java/de/srsoftware/umbrella/items/ItemApi.java +++ b/items/src/main/java/de/srsoftware/umbrella/items/ItemApi.java @@ -27,12 +27,11 @@ import java.util.Optional; public class ItemApi extends BaseHandler implements ItemService { private final ItemDb itemDb; - private final ModuleRegistry registry; public ItemApi(ModuleRegistry registry, Configuration config) throws UmbrellaException { + super(registry); var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); itemDb = new SqliteDb(connect(dbFile)); - this.registry = registry.add(this); } @Override @@ -40,7 +39,7 @@ public class ItemApi extends BaseHandler implements ItemService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -61,8 +60,8 @@ public class ItemApi extends BaseHandler implements ItemService { var json = json(ex); if (!(json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number cid)) throw missingFieldException(COMPANY_ID); var companyId = cid.longValue(); - var company = registry.companyService().get(companyId); - if (!registry.companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); + var company = companyService().get(companyId); + if (!companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); var items = list(companyId) .stream() .map(Item::toMap) diff --git a/legacy/src/main/java/de/srsoftware/umbrella/legacy/CompanyLegacy.java b/legacy/src/main/java/de/srsoftware/umbrella/legacy/CompanyLegacy.java index 6ebc4a6..ee24026 100644 --- a/legacy/src/main/java/de/srsoftware/umbrella/legacy/CompanyLegacy.java +++ b/legacy/src/main/java/de/srsoftware/umbrella/legacy/CompanyLegacy.java @@ -20,11 +20,10 @@ import java.util.Map; import java.util.Optional; public class CompanyLegacy extends BaseHandler { - private final ModuleRegistry registry; private final Configuration config; public CompanyLegacy(ModuleRegistry registry, Configuration config) { - this.registry = registry; + super(registry); this.config = config.subset("umbrella.modules").orElseThrow(() -> new RuntimeException("Missing configuration: umbrella.modules")); } @@ -55,7 +54,7 @@ public class CompanyLegacy extends BaseHandler { Optional token = SessionToken.from(ex).map(Token::of); if (token.isEmpty()) token = nullable(params.get(TOKEN)).map(Object::toString).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); return switch (path.pop()){ @@ -65,7 +64,7 @@ public class CompanyLegacy extends BaseHandler { } private boolean postCompanyJson(HttpExchange ex, Map params, UmbrellaUser user) throws IOException { - var companies = registry.companyService().listCompaniesOf(user); + var companies = companyService().listCompaniesOf(user); return sendContent(ex, mapValues(companies)); } diff --git a/legacy/src/main/java/de/srsoftware/umbrella/legacy/NotesLegacy.java b/legacy/src/main/java/de/srsoftware/umbrella/legacy/NotesLegacy.java index 9ce044c..1ce0399 100644 --- a/legacy/src/main/java/de/srsoftware/umbrella/legacy/NotesLegacy.java +++ b/legacy/src/main/java/de/srsoftware/umbrella/legacy/NotesLegacy.java @@ -24,11 +24,10 @@ import java.util.Map; import java.util.Optional; public class NotesLegacy extends BaseHandler { - private final ModuleRegistry registry; private final Configuration config; public NotesLegacy(ModuleRegistry registry, Configuration config) { - this.registry = registry; + super(registry); this.config = config.subset("umbrella.modules").orElseThrow(() -> new RuntimeException("Missing configuration: umbrella.modules")); } @@ -59,7 +58,7 @@ public class NotesLegacy extends BaseHandler { Optional token = SessionToken.from(ex).map(Token::of); if (token.isEmpty()) token = nullable(params.get(TOKEN)).map(Object::toString).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); return switch (path.pop()){ @@ -74,9 +73,9 @@ public class NotesLegacy extends BaseHandler { if (parts.length<2) throw invalidFieldException(URI,"URI of the form \"module:entry-id\""); var module = parts[0]; var entryId = parts[1]; - var notes = registry.noteService().getNotes(module,entryId); + var notes = noteService().getNotes(module,entryId); var authors = new HashMap (); - var users = registry.userService(); + var users = userService(); for (var note : notes.values()) { var userId = note.authorId(); authors.computeIfAbsent(userId,k -> users.loadUser(userId)); diff --git a/legacy/src/main/java/de/srsoftware/umbrella/legacy/ProjectLegacy.java b/legacy/src/main/java/de/srsoftware/umbrella/legacy/ProjectLegacy.java index 5d1e14d..5990f43 100644 --- a/legacy/src/main/java/de/srsoftware/umbrella/legacy/ProjectLegacy.java +++ b/legacy/src/main/java/de/srsoftware/umbrella/legacy/ProjectLegacy.java @@ -20,11 +20,10 @@ import java.util.Map; import java.util.Optional; public class ProjectLegacy extends BaseHandler { - private final ModuleRegistry registry; private final Configuration config; public ProjectLegacy(ModuleRegistry registry, Configuration config) { - this.registry = registry; + super(registry); this.config = config.subset("umbrella.modules").orElseThrow(() -> new RuntimeException("Missing configuration: umbrella.modules")); } @@ -55,7 +54,7 @@ public class ProjectLegacy extends BaseHandler { Optional token = SessionToken.from(ex).map(Token::of); if (token.isEmpty()) token = nullable(params.get(TOKEN)).map(Object::toString).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); return switch (path.pop()){ @@ -66,7 +65,7 @@ public class ProjectLegacy extends BaseHandler { private boolean postProjectJson(HttpExchange ex, Map params, UmbrellaUser user) throws IOException { var includeUsers = "1".equals(params.get(USERS)); - var projects = registry.projectService().listUserProjects(user.id(), false); + var projects = projectService().listUserProjects(user.id(), false); return sendContent(ex, mapValues(projects)); } } diff --git a/legacy/src/main/java/de/srsoftware/umbrella/legacy/TaskLegacy.java b/legacy/src/main/java/de/srsoftware/umbrella/legacy/TaskLegacy.java new file mode 100644 index 0000000..3304cd2 --- /dev/null +++ b/legacy/src/main/java/de/srsoftware/umbrella/legacy/TaskLegacy.java @@ -0,0 +1,72 @@ +/* © SRSoftware 2025 */ +package de.srsoftware.umbrella.legacy; + + +import static de.srsoftware.tools.Optionals.nullable; +import static de.srsoftware.umbrella.core.Constants.TOKEN; +import static de.srsoftware.umbrella.core.Constants.USERS; +import static de.srsoftware.umbrella.core.Paths.JSON; +import static de.srsoftware.umbrella.core.Util.mapValues; + +import com.sun.net.httpserver.HttpExchange; +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.ModuleRegistry; +import de.srsoftware.umbrella.core.model.Token; +import de.srsoftware.umbrella.core.model.UmbrellaUser; +import java.io.IOException; +import java.util.Map; +import java.util.Optional; + +public class TaskLegacy extends BaseHandler { + private final Configuration config; + + public TaskLegacy(ModuleRegistry registry, Configuration config) { + super(registry); + this.config = config.subset("umbrella.modules").orElseThrow(() -> new RuntimeException("Missing configuration: umbrella.modules")); + } + + @Override + public boolean doDelete(Path path, HttpExchange ex) throws IOException { + return super.doDelete(path, ex); + } + + @Override + public boolean doGet(Path path, HttpExchange ex) throws IOException { + if (path.empty()) return sendRedirect(ex, url(ex).replaceAll("/legacy/","/")); + return super.doGet(path, ex); + } + + @Override + public boolean doOptions(Path path, HttpExchange ex) throws IOException { + return super.doOptions(path, ex); + } + + @Override + public boolean doPatch(Path path, HttpExchange ex) throws IOException { + return super.doPatch(path, ex); + } + + @Override + public boolean doPost(Path path, HttpExchange ex) throws IOException{ + var params = formData(ex); + + Optional token = SessionToken.from(ex).map(Token::of); + if (token.isEmpty()) token = nullable(params.get(TOKEN)).map(Object::toString).map(Token::of); + var user = userService().loadUser(token); + if (user.isEmpty()) return unauthorized(ex); + + return switch (path.pop()){ + case JSON -> postProjectJson(ex,params,user.get()); + default -> super.doPost(path, ex); + }; + } + + private boolean postProjectJson(HttpExchange ex, Map params, UmbrellaUser user) throws IOException { + var includeUsers = "1".equals(params.get(USERS)); + var projects = projectService().listUserProjects(user.id(), false); + return sendContent(ex, mapValues(projects)); + } +} diff --git a/legacy/src/main/java/de/srsoftware/umbrella/legacy/UserLegacy.java b/legacy/src/main/java/de/srsoftware/umbrella/legacy/UserLegacy.java index 025727c..734bb8b 100644 --- a/legacy/src/main/java/de/srsoftware/umbrella/legacy/UserLegacy.java +++ b/legacy/src/main/java/de/srsoftware/umbrella/legacy/UserLegacy.java @@ -33,10 +33,9 @@ public class UserLegacy extends BaseHandler { private final Configuration config; private final String messageUrl; - private final ModuleRegistry registry; public UserLegacy(ModuleRegistry registry, Configuration config) { - this.registry = registry; + super(registry); this.config = config.subset("umbrella.modules").orElseThrow(() -> new RuntimeException("Missing configuration: umbrella.modules")); this.messageUrl = null; } @@ -128,7 +127,7 @@ public class UserLegacy extends BaseHandler { throw new UmbrellaException(400,"Fetching related users not implemented, yet!"); } - Map userMap = registry.userService().list(0, null, ids); + Map userMap = userService().list(0, null, ids); if (arrayPassed || userMap.size() != 1) { var userData = new HashMap>(); for (var entry : userMap.entrySet()) userData.put(entry.getKey(),entry.getValue().toMap()); @@ -180,7 +179,7 @@ public class UserLegacy extends BaseHandler { } } if (!recipients.isEmpty()){ // replace legacy user ids by user objects in receivers field - Map resp = registry.userService().list(0, null, recipients); + Map resp = userService().list(0, null, recipients); data.put("receivers",resp.values().stream().map(UmbrellaUser::toMap).toList()); } @@ -203,7 +202,7 @@ public class UserLegacy extends BaseHandler { var optToken = SessionToken.from(ex).map(Token::of); if (optToken.isPresent()) try{ var token = optToken.get(); - registry.userService().dropSession(token); + userService().dropSession(token); var expiredToken = new SessionToken(token.toString(),"/", Instant.now().minus(1, DAYS),true); expiredToken.addTo(ex); if (returnTo instanceof String location) return sendRedirect(ex,location); @@ -245,8 +244,8 @@ public class UserLegacy extends BaseHandler { }; protected Session requestSession(Token token) throws UmbrellaException { - var session = registry.userService().load(token); - session = registry.userService().extend(session); + var session = userService().load(token); + session = userService().extend(session); return session; } @@ -280,8 +279,8 @@ public class UserLegacy extends BaseHandler { var o = map.get(TOKEN); if (!(o instanceof String token)) throw new UmbrellaException(500,"Request did not contain token!"); - var session = registry.userService().load(Token.of(token)); - var user = registry.userService().load(session); + var session = userService().load(Token.of(token)); + var user = userService().load(session); var userMap = user.toMap(); userMap.put(TOKEN,Map.of(TOKEN,token,EXPIRATION,session.expiration().getEpochSecond())); return sendContent(ex,userMap); diff --git a/markdown/src/main/java/de/srsoftware/umbrella/markdown/MarkdownApi.java b/markdown/src/main/java/de/srsoftware/umbrella/markdown/MarkdownApi.java index 6d3475c..9dbea31 100644 --- a/markdown/src/main/java/de/srsoftware/umbrella/markdown/MarkdownApi.java +++ b/markdown/src/main/java/de/srsoftware/umbrella/markdown/MarkdownApi.java @@ -17,10 +17,9 @@ import java.util.Optional; public class MarkdownApi extends BaseHandler implements MarkdownService { - private final ModuleRegistry registry; public MarkdownApi(ModuleRegistry registry) { - this.registry = registry.add(this); + super(registry); } @Override @@ -28,7 +27,7 @@ public class MarkdownApi extends BaseHandler implements MarkdownService { try { addCors(ex); Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) throw UmbrellaException.forbidden("You must be logged in to use the markdown renderer!"); var rendered = Util.markdown(body(ex)); diff --git a/messages/src/main/java/de/srsoftware/umbrella/message/MessageApi.java b/messages/src/main/java/de/srsoftware/umbrella/message/MessageApi.java deleted file mode 100644 index 194d16f..0000000 --- a/messages/src/main/java/de/srsoftware/umbrella/message/MessageApi.java +++ /dev/null @@ -1,14 +0,0 @@ -/* © SRSoftware 2025 */ -package de.srsoftware.umbrella.message; - -import de.srsoftware.umbrella.core.BaseHandler; -import de.srsoftware.umbrella.core.ModuleRegistry; - -public class MessageApi extends BaseHandler { - private final ModuleRegistry registry; - - public MessageApi(ModuleRegistry moduleRegistry) { - super(); - this.registry = moduleRegistry; - } -} diff --git a/notes/src/main/java/de/srsoftware/umbrella/notes/NoteModule.java b/notes/src/main/java/de/srsoftware/umbrella/notes/NoteModule.java index 1cd1008..0e81c1a 100644 --- a/notes/src/main/java/de/srsoftware/umbrella/notes/NoteModule.java +++ b/notes/src/main/java/de/srsoftware/umbrella/notes/NoteModule.java @@ -28,12 +28,11 @@ import java.util.stream.Collectors; public class NoteModule extends BaseHandler implements NoteService { private final NotesDb notesDb; - private final ModuleRegistry registry; public NoteModule(ModuleRegistry registry, Configuration config) { + super(registry); var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); notesDb = new SqliteDb(connect(dbFile)); - this.registry = registry.add(this); } @Override @@ -46,7 +45,7 @@ public class NoteModule extends BaseHandler implements NoteService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); if (head == null) throw unprocessable("Module missing in path."); @@ -73,7 +72,7 @@ public class NoteModule extends BaseHandler implements NoteService { public boolean doGet(Path path, HttpExchange ex) throws IOException { addCors(ex); try { - var user = registry.userService().refreshSession(ex); + var user = userService().refreshSession(ex); if (user.isEmpty()) return unauthorized(ex); var module = path.pop(); return switch (module){ @@ -105,7 +104,7 @@ public class NoteModule extends BaseHandler implements NoteService { } private Map addUsers(Map notes) { - var authors = notes.values().stream().map(Note::authorId).distinct().map(registry.userService()::loadUser).collect(Collectors.toMap(UmbrellaUser::id,UmbrellaUser::toMap)); + var authors = notes.values().stream().map(Note::authorId).distinct().map(userService()::loadUser).collect(Collectors.toMap(UmbrellaUser::id,UmbrellaUser::toMap)); return Map.of("notes",mapValues(notes),"authors",authors); } @@ -114,7 +113,7 @@ public class NoteModule extends BaseHandler implements NoteService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); long noteId = Long.parseLong(head); @@ -137,7 +136,7 @@ public class NoteModule extends BaseHandler implements NoteService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var module = path.pop(); if (module == null) throw unprocessable("Module missing in path."); diff --git a/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java b/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java index 45f08ac..2a7ecda 100644 --- a/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java +++ b/project/src/main/java/de/srsoftware/umbrella/project/ProjectModule.java @@ -30,16 +30,15 @@ import org.json.JSONObject; public class ProjectModule extends BaseHandler implements ProjectService { private final ProjectDb projects; - private final ModuleRegistry registy; public ProjectModule(ModuleRegistry registry, Configuration config) throws UmbrellaException { + super(registry); var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); projects = new SqliteDb(connect(dbFile)); - this.registy = registry.add(this); } private void addMember(Project project, long userId) { - var user = registy.userService().loadUser(userId); + var user = userService().loadUser(userId); var member = new Member(user,READ_ONLY); project.members().put(userId,member); project.dirty(MEMBERS); @@ -50,7 +49,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registy.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -74,7 +73,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registy.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -97,7 +96,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registy.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -129,7 +128,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { var project = loadMembers(projects.load(projectId)); if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name()); var map = project.toMap(); - project.companyId().map(registy.companyService()::get).map(Company::toMap).ifPresent(data -> map.put(COMPANY,data)); + project.companyId().map(companyService()::get).map(Company::toMap).ifPresent(data -> map.put(COMPANY,data)); return sendContent(ex,map); } @@ -140,8 +139,8 @@ public class ProjectModule extends BaseHandler implements ProjectService { } private boolean listCompanyProjects(HttpExchange ex, UmbrellaUser user, long companyId) throws IOException, UmbrellaException { - var company = registy.companyService().get(companyId); - if (!registy.companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); + var company = companyService().get(companyId); + if (!companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); var projects = listCompanyProjects(companyId,false); return sendContent(ex,mapValues(projects)); } @@ -170,7 +169,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { for (var entry : projects.getMembers(project).entrySet()){ var userId = entry.getKey(); var permission = entry.getValue(); - var user = userMap.computeIfAbsent(userId,k -> registy.userService().loadUser(userId)); + var user = userMap.computeIfAbsent(userId,k -> userService().loadUser(userId)); project.members().put(userId,new Member(user,permission)); } } @@ -194,7 +193,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { if (member.permission() == OWNER) members.put(member.user().id(),new Member(member.user(),EDIT)); } } - members.put(userId,new Member(registy.userService().loadUser(userId),permission)); + members.put(userId,new Member(userService().loadUser(userId),permission)); project.dirty(MEMBERS); } } @@ -233,7 +232,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { } Long companyId = null; if (json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number number){ - if (!registy.companyService().membership(number.longValue(), user.id())) throw forbidden("You are not a member of company {0}!",number); + if (!companyService().membership(number.longValue(), user.id())) throw forbidden("You are not a member of company {0}!",number); companyId = number.longValue(); } var showClosed = false; @@ -246,7 +245,7 @@ public class ProjectModule extends BaseHandler implements ProjectService { if (json.has(TAGS) && json.get(TAGS) instanceof JSONArray arr){ var tagList = arr.toList().stream().filter(elem -> elem instanceof String).map(String.class::cast).toList(); - registy.tagService().save(PROJECT,prj.id(),null,tagList); + tagService().save(PROJECT,prj.id(),null,tagList); } return sendContent(ex,prj); diff --git a/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java b/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java index 161eec6..6f047f6 100644 --- a/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java +++ b/tags/src/main/java/de/srsoftware/umbrella/tags/TagModule.java @@ -25,13 +25,12 @@ import org.json.JSONArray; public class TagModule extends BaseHandler implements TagService { private final SqliteDb tagDb; - private final ModuleRegistry registry; public TagModule(ModuleRegistry registry, Configuration config) { + super(registry); var tagDbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); var bmDbFile = config.get(de.srsoftware.umbrella.bookmarks.Constants.CONFIG_DATABASE).orElseThrow(() -> missingFieldException(de.srsoftware.umbrella.bookmarks.Constants.CONFIG_DATABASE)); tagDb = new SqliteDb(connect(tagDbFile),connect(bmDbFile)); - this.registry = registry.add(this); } @Override @@ -44,7 +43,7 @@ public class TagModule extends BaseHandler implements TagService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var module = path.pop(); if (module == null) throw unprocessable("Module missing in path."); @@ -63,7 +62,7 @@ public class TagModule extends BaseHandler implements TagService { public boolean doGet(Path path, HttpExchange ex) throws IOException { addCors(ex); try { - var user = registry.userService().refreshSession(ex); + var user = userService().refreshSession(ex); if (user.isEmpty()) return unauthorized(ex); var module = path.pop(); if (module == null) throw unprocessable("Module missing in path."); @@ -87,7 +86,7 @@ public class TagModule extends BaseHandler implements TagService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var module = path.pop(); if (module == null) throw unprocessable("Module missing in path."); diff --git a/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java b/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java index c09bf76..b7ce539 100644 --- a/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java +++ b/task/src/main/java/de/srsoftware/umbrella/task/TaskModule.java @@ -35,16 +35,15 @@ import org.json.JSONObject; public class TaskModule extends BaseHandler implements TaskService { private final TaskDb taskDb; - private final ModuleRegistry registry; public TaskModule(ModuleRegistry registry, Configuration config) throws UmbrellaException { + super(registry); var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); taskDb = new SqliteDb(connect(dbFile)); - this.registry = registry.add(this); } private void addMember(Task task, long userId) { - var user = registry.userService().loadUser(userId); + var user = userService().loadUser(userId); var member = new Member(user,READ_ONLY); task.members().put(userId,member); task.dirty(MEMBERS); @@ -55,8 +54,8 @@ public class TaskModule extends BaseHandler implements TaskService { var member = task.members().get(user.id()); if (member == null || !member.mayWrite()) throw forbidden("You are not allowed to delete {0}",task.name()); taskDb.delete(task); - registry.noteService().deleteEntity(TASK,""+taskId); - registry.tagService().deleteEntity(TASK,taskId); + noteService().deleteEntity(TASK,""+taskId); + tagService().deleteEntity(TASK,taskId); return sendContent(ex,Map.of(DELETED,taskId)); } @@ -65,7 +64,7 @@ public class TaskModule extends BaseHandler implements TaskService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -85,7 +84,7 @@ public class TaskModule extends BaseHandler implements TaskService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -107,7 +106,7 @@ public class TaskModule extends BaseHandler implements TaskService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -128,7 +127,7 @@ public class TaskModule extends BaseHandler implements TaskService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -152,9 +151,9 @@ public class TaskModule extends BaseHandler implements TaskService { var json = json(ex); if (!(json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number cid)) throw missingFieldException(COMPANY_ID); var companyId = cid.longValue(); - var company = registry.companyService().get(companyId); - if (!registry.companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); - var projectMap = registry.projectService().listCompanyProjects(companyId,false); + var company = companyService().get(companyId); + if (!companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); + var projectMap = projectService().listCompanyProjects(companyId,false); var taskMap = taskDb.listTasks(projectMap.keySet()); var taskTree = new HashMap>(); taskMap.values().stream().filter(task -> !is0(task.estimatedTime())).forEach(task -> placeInTree(task,taskTree,taskMap)); @@ -196,7 +195,7 @@ public class TaskModule extends BaseHandler implements TaskService { } catch (NumberFormatException e) { throw invalidFieldException(LIMIT,"number"); } - Set projectIds = registry.projectService().listUserProjects(user.id(), true).keySet(); + Set projectIds = projectService().listUserProjects(user.id(), true).keySet(); var list = taskDb.listUserTasks(user.id(), limit, offset, false).stream() .filter(task -> projectIds.contains(task.projectId())) // drop tasks assigned to project we are not member of .map(Task::toMap) @@ -206,7 +205,7 @@ public class TaskModule extends BaseHandler implements TaskService { @Override public HashMap listCompanyTasks(long companyId) throws UmbrellaException { - var projectList = registry.projectService().listCompanyProjects(companyId,false); + var projectList = projectService().listCompanyProjects(companyId,false); return taskDb.listTasks(projectList.keySet()); } @@ -222,7 +221,7 @@ public class TaskModule extends BaseHandler implements TaskService { for (var entry : taskDb.getMembers(task).entrySet()){ var userId = entry.getKey(); var permission = entry.getValue(); - var user = userMap.computeIfAbsent(userId,k -> registry.userService().loadUser(userId)); + var user = userMap.computeIfAbsent(userId,k -> userService().loadUser(userId)); task.members().put(userId,new Member(user,permission)); } } @@ -267,7 +266,7 @@ public class TaskModule extends BaseHandler implements TaskService { if (member.permission() == ASSIGNEE) members.put(member.user().id(),new Member(member.user(),EDIT)); } } - members.put(userId,new Member(registry.userService().loadUser(userId),permission)); + members.put(userId,new Member(userService().loadUser(userId),permission)); task.dirty(MEMBERS); } } @@ -301,8 +300,8 @@ public class TaskModule extends BaseHandler implements TaskService { if (!(json.has(PROJECT_ID) && json.get(PROJECT_ID) instanceof Number pid)) throw missingFieldException(PROJECT_ID); if (!(json.has(MEMBERS) && json.get(MEMBERS) instanceof JSONObject memberData)) throw missingFieldException(MEMBERS); long projectId = pid.longValue(); - var project = registry.projectService().load(projectId); - registry.projectService().loadMembers(List.of(project)); + var project = projectService().load(projectId); + projectService().loadMembers(List.of(project)); var member = project.members().get(user.id()); if (member == null || member.permission() == READ_ONLY) throw forbidden("You are not allowed to create new tasks in this project"); for (var key : memberData.keySet()){ @@ -331,7 +330,7 @@ public class TaskModule extends BaseHandler implements TaskService { } if (json.has(TAGS) && json.get(TAGS) instanceof JSONArray arr){ var tagList = arr.toList().stream().filter(e -> e instanceof String).map(String.class::cast).toList(); - registry.tagService().save(TASK,task.id(),null,tagList); + tagService().save(TASK,task.id(),null,tagList); } return sendContent(ex,loadMembers(task)); } diff --git a/time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java b/time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java index 36bddbe..b49fdb3 100644 --- a/time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java +++ b/time/src/main/java/de/srsoftware/umbrella/time/TimeModule.java @@ -35,14 +35,13 @@ public class TimeModule extends BaseHandler implements TimeService { } - private final ModuleRegistry registry; private final TimeDb timeDb; public TimeModule(ModuleRegistry registry, Configuration config) throws UmbrellaException { + super(registry); var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE)); timeDb = new SqliteDb(connect(dbFile)); - this.registry = registry.add(this); } @Override @@ -50,7 +49,7 @@ public class TimeModule extends BaseHandler implements TimeService { addCors(ex); try { Optional token = SessionToken.from(ex).map(Token::of); - var user = registry.userService().loadUser(token); + var user = userService().loadUser(token); if (user.isEmpty()) return unauthorized(ex); var head = path.pop(); return switch (head) { @@ -106,11 +105,11 @@ public class TimeModule extends BaseHandler implements TimeService { var json = json(ex); if (!(json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number cid)) throw missingFieldException(COMPANY_ID); var companyId = cid.longValue(); - var company = registry.companyService().get(companyId); - if (!registry.companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); + var company = companyService().get(companyId); + if (!companyService().membership(companyId,user.id())) throw forbidden("You are mot a member of company {0}",company.name()); if (!(json.has(PROJECT_ID) && json.get(PROJECT_ID) instanceof Number pid)) throw missingFieldException(PROJECT_ID); long projectId = pid.longValue(); - Map tasksOfProject = registry.taskService().listProjectTasks(projectId); + Map tasksOfProject = taskService().listProjectTasks(projectId); List> times = timeDb.listTimes(tasksOfProject.keySet()) .stream().filter(not(Time::isClosed)) diff --git a/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java b/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java index 6ed15a4..ea4a70a 100644 --- a/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java +++ b/user/src/main/java/de/srsoftware/umbrella/user/UserModule.java @@ -69,7 +69,6 @@ public class UserModule extends BaseHandler implements UserService { private static final System.Logger LOG = System.getLogger("User"); private final UserDb users; private final LoginServiceDb logins; - private final ModuleRegistry registry; private final HashMap stateMap = new HashMap<>(); // map from state to OIDC provider name private final HashMap tokenMap = new HashMap<>(); @@ -82,11 +81,11 @@ public class UserModule extends BaseHandler implements UserService { } public UserModule(ModuleRegistry registry, Configuration config) throws UmbrellaException { + super(registry); var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingConfigException(CONFIG_DATABASE)); // may be splitted in separate db files later logins = new SqliteDB(connect(dbFile)); users = new SqliteDB(connect(dbFile)); - this.registry = registry.add(this); } private boolean deleteOIDC(HttpExchange ex, UmbrellaUser user, Path path) throws IOException { @@ -504,7 +503,7 @@ public class UserModule extends BaseHandler implements UserService { var fills = Map.of("url",url); var message = new Message(user,subject,content,fills,null); var envelope = new Envelope(message,user); - registry.postBox().send(envelope); + postBox().send(envelope); } catch (UmbrellaException e){ return send(ex,e); } diff --git a/web/src/main/java/de/srsoftware/umbrella/web/WebHandler.java b/web/src/main/java/de/srsoftware/umbrella/web/WebHandler.java index 9c5da97..d42f13d 100644 --- a/web/src/main/java/de/srsoftware/umbrella/web/WebHandler.java +++ b/web/src/main/java/de/srsoftware/umbrella/web/WebHandler.java @@ -8,11 +8,16 @@ import static java.net.HttpURLConnection.HTTP_NOT_FOUND; import com.sun.net.httpserver.HttpExchange; import de.srsoftware.tools.Path; import de.srsoftware.umbrella.core.BaseHandler; +import de.srsoftware.umbrella.core.ModuleRegistry; import java.io.ByteArrayOutputStream; import java.io.IOException; public class WebHandler extends BaseHandler { + public WebHandler(ModuleRegistry registry){ + super(registry); + } + @Override public boolean doGet(Path path, HttpExchange ex) throws IOException { LOG.log(DEBUG,"doGet({0},ex)",path);