Browse Source

implemented document creation

this required a major refactoring of the object model
feature/document
Stephan Richter 4 months ago
parent
commit
163bcebf4f
  1. 2
      backend/build.gradle.kts
  2. 6
      backend/src/main/java/de/srsoftware/umbrella/backend/Application.java
  3. 1
      build.gradle.kts
  4. 2
      company/build.gradle.kts
  5. 32
      company/src/main/java/de/srsoftware/umbrella/company/CompanyModule.java
  6. 10
      company/src/main/java/de/srsoftware/umbrella/company/Constants.java
  7. 52
      company/src/main/java/de/srsoftware/umbrella/company/SqliteDb.java
  8. 12
      company/src/main/java/de/srsoftware/umbrella/company/api/CompanyDb.java
  9. 1
      core/build.gradle.kts
  10. 7
      core/src/main/java/de/srsoftware/umbrella/core/BaseHandler.java
  11. 12
      core/src/main/java/de/srsoftware/umbrella/core/Constants.java
  12. 28
      core/src/main/java/de/srsoftware/umbrella/core/UmbrellaException.java
  13. 1
      core/src/main/java/de/srsoftware/umbrella/core/Util.java
  14. 9
      core/src/main/java/de/srsoftware/umbrella/core/api/CompanyService.java
  15. 2
      core/src/main/java/de/srsoftware/umbrella/core/api/UserService.java
  16. 46
      core/src/main/java/de/srsoftware/umbrella/core/exceptions/UmbrellaException.java
  17. 29
      core/src/main/java/de/srsoftware/umbrella/core/model/Company.java
  18. 8
      core/src/main/java/de/srsoftware/umbrella/core/model/EmailAddress.java
  19. 6
      core/src/main/java/de/srsoftware/umbrella/core/model/UmbrellaUser.java
  20. 2
      documents/build.gradle.kts
  21. 10
      documents/src/main/java/de/srsoftware/umbrella/documents/Constants.java
  22. 59
      documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java
  23. 2
      documents/src/main/java/de/srsoftware/umbrella/documents/DocumentDb.java
  24. 3
      documents/src/main/java/de/srsoftware/umbrella/documents/SqliteDb.java
  25. 11
      documents/src/main/java/de/srsoftware/umbrella/documents/model/Customer.java
  26. 2
      documents/src/main/java/de/srsoftware/umbrella/documents/model/PositionList.java
  27. 14
      documents/src/main/java/de/srsoftware/umbrella/documents/model/Sender.java
  28. 38
      frontend/src/routes/document/AddDocument.svelte
  29. 1
      legacy/build.gradle.kts
  30. 2
      legacy/src/main/java/de/srsoftware/umbrella/legacy/LegacyApi.java
  31. 1
      messages/build.gradle.kts
  32. 2
      messages/src/main/java/de/srsoftware/umbrella/message/MessageDb.java
  33. 5
      messages/src/main/java/de/srsoftware/umbrella/message/MessageSystem.java
  34. 2
      messages/src/main/java/de/srsoftware/umbrella/message/SqliteMessageDb.java
  35. 12
      messages/src/main/java/de/srsoftware/umbrella/message/model/Attachment.java
  36. 12
      messages/src/main/java/de/srsoftware/umbrella/message/model/Envelope.java
  37. 12
      messages/src/main/java/de/srsoftware/umbrella/message/model/Message.java
  38. 1
      translations/build.gradle.kts
  39. 1
      user/build.gradle.kts
  40. 34
      user/src/main/java/de/srsoftware/umbrella/user/UserModule.java
  41. 2
      user/src/main/java/de/srsoftware/umbrella/user/api/LoginServiceDb.java
  42. 2
      user/src/main/java/de/srsoftware/umbrella/user/api/UserDb.java
  43. 2
      user/src/main/java/de/srsoftware/umbrella/user/sqlite/SqliteDB.java

2
backend/build.gradle.kts

@ -11,6 +11,7 @@ application{ @@ -11,6 +11,7 @@ application{
}
dependencies{
implementation(project(":company"))
implementation(project(":core"))
implementation(project(":documents"))
implementation(project(":legacy"))
@ -23,7 +24,6 @@ dependencies{ @@ -23,7 +24,6 @@ dependencies{
implementation("de.srsoftware:tools.optionals:1.0.0")
implementation("de.srsoftware:tools.slf4j2syslog:1.0.1") // this provides a slf4j implementation that forwards to System.Logger
implementation("de.srsoftware:tools.util:2.0.3")
implementation("org.json:json:20240303")
}
tasks.jar {

6
backend/src/main/java/de/srsoftware/umbrella/backend/Application.java

@ -8,7 +8,8 @@ import static java.lang.System.Logger.Level.INFO; @@ -8,7 +8,8 @@ import static java.lang.System.Logger.Level.INFO;
import com.sun.net.httpserver.HttpServer;
import de.srsoftware.configuration.JsonConfig;
import de.srsoftware.tools.ColorLogger;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.company.CompanyModule;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.documents.DocumentApi;
import de.srsoftware.umbrella.legacy.LegacyApi;
import de.srsoftware.umbrella.message.MessageApi;
@ -49,7 +50,8 @@ public class Application { @@ -49,7 +50,8 @@ public class Application {
var server = HttpServer.create(new InetSocketAddress(port), 0);
var userModule = new UserModule(config,messageSystem);
var documentApi = new DocumentApi(userModule, config);
var companyModule = new CompanyModule(config, userModule);
var documentApi = new DocumentApi(companyModule, config);
var legacyApi = new LegacyApi(userModule.userDb(),config);
var messageApi = new MessageApi(messageSystem);
var webHandler = new WebHandler();

1
build.gradle.kts

@ -42,6 +42,7 @@ subprojects { @@ -42,6 +42,7 @@ subprojects {
testImplementation("org.junit.jupiter:junit-jupiter")
implementation("de.srsoftware:tools.http:6.0.4")
implementation("de.srsoftware:tools.logging:1.3.2")
implementation("org.json:json:20240303")
}
tasks.withType<Test>() {

2
company/build.gradle.kts

@ -2,5 +2,7 @@ description = "Umbrella : Companies" @@ -2,5 +2,7 @@ description = "Umbrella : Companies"
dependencies{
implementation(project(":core"))
implementation("de.srsoftware:configuration.api:1.0.2")
implementation("de.srsoftware:tools.jdbc:1.3.2")
}

32
company/src/main/java/de/srsoftware/umbrella/company/CompanyModule.java

@ -1,21 +1,45 @@ @@ -1,21 +1,45 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.company;
import static de.srsoftware.umbrella.company.Constants.CONFIG_DATABASE;
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import de.srsoftware.configuration.Configuration;
import de.srsoftware.umbrella.company.api.CompanyDb;
import de.srsoftware.umbrella.core.api.CompanyService;
import de.srsoftware.umbrella.core.api.UserService;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Company;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import java.util.List;
import java.util.Collection;
import java.util.HashSet;
public class CompanyModule implements CompanyService {
private final UserService users;
private final CompanyDb companyDb;
public CompanyModule(UserService userService){
public CompanyModule(Configuration config, UserService userService) throws UmbrellaException {
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE));
companyDb = new SqliteDb(connect(dbFile));
users = userService;
}
@Override
public List<UmbrellaUser> getMembers(long companyId) {
return null;
public Company get(long companyId) throws UmbrellaException {
return companyDb.load(companyId);
}
@Override
public Collection<UmbrellaUser> getMembers(long companyId) throws UmbrellaException {
var members = new HashSet<UmbrellaUser>();
for (var userId : companyDb.getMembers(companyId)) members.add(users.loadUser(userId));
return members;
}
@Override
public UserService userService() {
return users;
}
}

10
company/src/main/java/de/srsoftware/umbrella/company/Constants.java

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.company;
public class Constants {
private Constants(){}
public static final String CONFIG_DATABASE = "umbrella.modules.company.database";
public static final String TABLE_COMPANIES_USERS = "companies_users";
public static final String TABLE_COMPANIES = "companies";
}

52
company/src/main/java/de/srsoftware/umbrella/company/SqliteDb.java

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.company;
import static de.srsoftware.tools.jdbc.Condition.equal;
import static de.srsoftware.tools.jdbc.Query.select;
import static de.srsoftware.umbrella.company.Constants.TABLE_COMPANIES;
import static de.srsoftware.umbrella.company.Constants.TABLE_COMPANIES_USERS;
import static de.srsoftware.umbrella.core.Constants.*;
import de.srsoftware.umbrella.company.api.CompanyDb;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Company;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashSet;
public class SqliteDb implements CompanyDb {
private final Connection db;
public SqliteDb(Connection connection) {
db = connection;
}
@Override
public Collection<Long> getMembers(long companyId) throws UmbrellaException {
try {
var rs = select("*").from(TABLE_COMPANIES_USERS).where(COMPANY_ID, equal(companyId)).exec(db);
var ids = new HashSet<Long>();
while (rs.next()) ids.add(rs.getLong(USER_ID));
rs.close();
return ids;
} catch (SQLException e) {
throw new UmbrellaException("Failed to load members of company {0}",companyId);
}
}
@Override
public Company load(long companyId) throws UmbrellaException {
try {
var rs = select("*").from(TABLE_COMPANIES).where(ID, equal(companyId)).exec(db);
Company company = null;
if (rs.next()) company = Company.of(rs);
rs.close();
if (company == null) throw new UmbrellaException("Could not load company {0}",companyId);
return company;
} catch (SQLException e){
throw new UmbrellaException("Could not load company {0}",companyId);
}
}
}

12
company/src/main/java/de/srsoftware/umbrella/company/api/CompanyDb.java

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.company.api;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Company;
import java.util.Collection;
public interface CompanyDb {
Collection<Long> getMembers(long companyId) throws UmbrellaException;
Company load(long companyId) throws UmbrellaException;
}

1
core/build.gradle.kts

@ -13,7 +13,6 @@ dependencies { @@ -13,7 +13,6 @@ dependencies {
implementation("de.srsoftware:tools.mime:1.1.2")
implementation("de.srsoftware:tools.optionals:1.0.0")
implementation("de.srsoftware:tools.util:2.0.3")
implementation("org.json:json:20240303")
implementation("org.xerial:sqlite-jdbc:3.49.0.0")
testImplementation(platform("org.junit:junit-bom:5.10.0"))
testImplementation("org.junit.jupiter:junit-jupiter")

7
core/src/main/java/de/srsoftware/umbrella/core/BaseHandler.java

@ -10,6 +10,7 @@ import static java.text.MessageFormat.format; @@ -10,6 +10,7 @@ import static java.text.MessageFormat.format;
import com.sun.net.httpserver.HttpExchange;
import de.srsoftware.tools.Path;
import de.srsoftware.tools.PathHandler;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
@ -35,7 +36,7 @@ public abstract class BaseHandler extends PathHandler { @@ -35,7 +36,7 @@ public abstract class BaseHandler extends PathHandler {
return sendEmptyResponse(HTTP_FORBIDDEN,ex);
}
public record Document(String mime, byte[] bytes){}
public record Page(String mime, byte[] bytes){}
public boolean load(Path path, HttpExchange ex) throws IOException {
try {
@ -47,7 +48,7 @@ public abstract class BaseHandler extends PathHandler { @@ -47,7 +48,7 @@ public abstract class BaseHandler extends PathHandler {
}
}
public Document load(String resourcePath) throws IOException, UmbrellaException {
public Page load(String resourcePath) throws IOException, UmbrellaException {
var url = getClass().getClassLoader().getResource(resourcePath);
if (url == null) throw new UmbrellaException(HTTP_NOT_FOUND,"{0} not found!",resourcePath);
LOG.log(DEBUG,"Trying to load {0}",url);
@ -56,7 +57,7 @@ public abstract class BaseHandler extends PathHandler { @@ -56,7 +57,7 @@ public abstract class BaseHandler extends PathHandler {
var mime = conn.getContentType();
try (var stream = conn.getInputStream()){
stream.transferTo(bos);
return new Document(mime,bos.toByteArray());
return new Page(mime,bos.toByteArray());
} catch (Exception e) {
LOG.log(WARNING,"Failed to load {0}",url);
throw new UmbrellaException(HTTP_NOT_FOUND,"Failed to load {0}",url);

12
core/src/main/java/de/srsoftware/umbrella/core/Constants.java

@ -64,4 +64,16 @@ public class Constants { @@ -64,4 +64,16 @@ public class Constants {
public static final String USER_LIST = "user_list";
public static final String UTF8 = UTF_8.displayName();
public static final String VALUE = "value";
public static final String COMPANY_ID = "company_id";
public static final String FIELD_COURT = "court";
public static final String FIELD_TAX_NUMBER = "tax_number";
public static final String FIELD_PHONE = "phone";
public static final String DECIMAL_SEPARATOR = "decimal_separator";
public static final String THOUSANDS_SEPARATOR = "thousands_separator";
public static final String LAST_CUSTOMER_NUMBER = "last_customer_number";
public static final String DECIMALS = "decimals";
public static final String CUSTOMER_NUMBER_PREFIX = "customer_number_prefix";
public static final String FIELD_CURRENCY = "currency";
public static final String FIELD_BANK_ACCOUNT = "bank_account";
}

28
core/src/main/java/de/srsoftware/umbrella/core/UmbrellaException.java

@ -1,28 +0,0 @@ @@ -1,28 +0,0 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.core;
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_SERVER_ERROR;
import static java.text.MessageFormat.format;
public class UmbrellaException extends Exception{
private final int statusCode;
public UmbrellaException(String message, Object ... fills){
this(HTTP_SERVER_ERROR,message,fills);
}
public UmbrellaException(int statusCode, String message, Object ... fills){
super(format(message,fills));
this.statusCode = statusCode;
}
public UmbrellaException causedBy(Exception e) {
initCause(e);
return this;
}
public int statusCode(){
return statusCode;
}
}

1
core/src/main/java/de/srsoftware/umbrella/core/Util.java

@ -9,6 +9,7 @@ import static java.lang.System.Logger.Level.WARNING; @@ -9,6 +9,7 @@ import static java.lang.System.Logger.Level.WARNING;
import static java.nio.charset.StandardCharsets.UTF_8;
import de.srsoftware.tools.Query;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;

9
core/src/main/java/de/srsoftware/umbrella/core/api/CompanyService.java

@ -1,9 +1,14 @@ @@ -1,9 +1,14 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.core.api;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Company;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import java.util.List;
import java.util.Collection;
public interface CompanyService {
public List<UmbrellaUser> getMembers(long companyId);
public Collection<UmbrellaUser> getMembers(long companyId) throws UmbrellaException;
public UserService userService();
Company get(long companyId) throws UmbrellaException;
}

2
core/src/main/java/de/srsoftware/umbrella/core/api/UserService.java

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
package de.srsoftware.umbrella.core.api;
import com.sun.net.httpserver.HttpExchange;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Token;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import java.util.Optional;

46
core/src/main/java/de/srsoftware/umbrella/core/exceptions/UmbrellaException.java

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.core.exceptions;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_SERVER_ERROR;
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_UNPROCESSABLE;
import static java.lang.System.Logger.Level.ERROR;
import static java.text.MessageFormat.format;
public class UmbrellaException extends Exception{
private final int statusCode;
public UmbrellaException(String message, Object ... fills){
this(HTTP_SERVER_ERROR,message,fills);
}
public UmbrellaException(int statusCode, String message, Object ... fills){
super(format(message,fills));
this.statusCode = statusCode;
}
public UmbrellaException causedBy(Exception e) {
initCause(e);
return this;
}
public static UmbrellaException invalidFieldException(String field,String expected){
return new UmbrellaException(HTTP_UNPROCESSABLE, ERROR_INVALID_FIELD, field, expected);
}
public static UmbrellaException missingConfigException(String field){
System.getLogger("Configuration").log(ERROR,ERROR_MISSING_CONFIG, field);
return new UmbrellaException(HTTP_SERVER_ERROR, ERROR_MISSING_CONFIG, field);
}
public static UmbrellaException missingFieldException(String field){
return new UmbrellaException(HTTP_UNPROCESSABLE, ERROR_MISSING_FIELD, field);
}
public int statusCode(){
return statusCode;
}
}

29
documents/src/main/java/de/srsoftware/umbrella/documents/model/Company.java → core/src/main/java/de/srsoftware/umbrella/core/model/Company.java

@ -1,10 +1,11 @@ @@ -1,10 +1,11 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.documents.model;
package de.srsoftware.umbrella.core.model;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.documents.Constants.*;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.json.JSONException;
import org.json.JSONObject;
@ -31,4 +32,26 @@ public record Company(long id, String name, String address, String court, String @@ -31,4 +32,26 @@ public record Company(long id, String name, String address, String court, String
throw new UmbrellaException(500,"Failed to convert JSON to Company!").causedBy(e);
}
}
public static Company of(ResultSet json) throws UmbrellaException {
try {
var id = json.getLong(ID);
var name = json.getString(NAME);
var address = json.getString(ADDRESS);
var email = json.getString(EMAIL);
var phone = json.getString(FIELD_PHONE);
var bankAccount = json.getString(FIELD_BANK_ACCOUNT);
var court = json.getString(FIELD_COURT);
var currency = json.getString(FIELD_CURRENCY);
var taxId = json.getString(FIELD_TAX_NUMBER);
var decimals = json.getInt(DECIMALS);
var decimalSep = json.getString(DECIMAL_SEPARATOR);
var thousandsSep = json.getString(THOUSANDS_SEPARATOR);
var lastCustomerNumber = json.getLong(LAST_CUSTOMER_NUMBER);
var customerNumberPrefix = json.getString(CUSTOMER_NUMBER_PREFIX);
return new Company(id,name,address,court,taxId,phone,decimalSep,thousandsSep,lastCustomerNumber,decimals,customerNumberPrefix,currency,email,bankAccount);
} catch (SQLException e){
throw new UmbrellaException(500,"Failed to convert ResultSet to Company!").causedBy(e);
}
}
}

8
core/src/main/java/de/srsoftware/umbrella/core/model/EmailAddress.java

@ -4,7 +4,8 @@ package de.srsoftware.umbrella.core.model; @@ -4,7 +4,8 @@ package de.srsoftware.umbrella.core.model;
import static de.srsoftware.tools.Optionals.allSet;
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.util.Objects;
public class EmailAddress {
private final String email;
@ -15,6 +16,11 @@ public class EmailAddress { @@ -15,6 +16,11 @@ public class EmailAddress {
email = addr;
}
@Override
public boolean equals(Object obj) {
return obj instanceof EmailAddress other && Objects.equals(email,other.email);
}
@Override
public String toString() {
return email;

6
core/src/main/java/de/srsoftware/umbrella/core/model/UmbrellaUser.java

@ -3,10 +3,10 @@ package de.srsoftware.umbrella.core.model; @@ -3,10 +3,10 @@ package de.srsoftware.umbrella.core.model;
import static de.srsoftware.umbrella.core.Constants.*;
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import de.srsoftware.tools.Mappable;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@ -60,7 +60,7 @@ public class UmbrellaUser implements Mappable { @@ -60,7 +60,7 @@ public class UmbrellaUser implements Mappable {
public static UmbrellaUser of(JSONObject json) throws UmbrellaException {
if (json.has(USER)) json = json.getJSONObject(USER);
if (!json.has(ID)) throw new UmbrellaException(HTTP_BAD_REQUEST,ERROR_MISSING_FIELD,ID);
if (!json.has(ID)) throw missingFieldException(ID);
var id = json.getLong(ID);
var name = json.has(NAME) ? json.getString(NAME) : null;
var email = json.has(EMAIL) ? new EmailAddress(json.getString(EMAIL)) : null;

2
documents/build.gradle.kts

@ -1,11 +1,11 @@ @@ -1,11 +1,11 @@
description = "Umbrella : Documents"
dependencies{
implementation(project(":company"))
implementation(project(":core"))
implementation("de.srsoftware:configuration.api:1.0.2")
implementation("de.srsoftware:tools.jdbc:1.3.2")
implementation("de.srsoftware:tools.mime:1.1.2")
implementation("de.srsoftware:tools.optionals:1.0.0")
implementation("de.srsoftware:tools.util:2.0.3")
implementation("org.json:json:20240303")
}

10
documents/src/main/java/de/srsoftware/umbrella/documents/Constants.java

@ -14,26 +14,18 @@ public class Constants { @@ -14,26 +14,18 @@ public class Constants {
public static final String CONFIG_DATABASE = "umbrella.modules.document.database";
public static final String CONTACTS = "contacts";
public static final String CUSTOMER_NUMBER_PREFIX = "customer_number_prefix";
public static final String DECIMAL_SEPARATOR = "decimal_separator";
public static final String DECIMALS = "decimals";
public static final String ERROR_ADDRESS_MISSING = "{0} address does not contain street address / post code / city";
public static final String LAST_CUSTOMER_NUMBER = "last_customer_number";
public static final String THOUSANDS_SEPARATOR = "thousands_separator";
public static final String PROJECT_ID = "project_id";
public static final String FIELD_AMOUNT = "amount";
public static final String FIELD_BANK_ACCOUNT = "bank_account";
public static final String FIELD_CODE = "code";
public static final String FIELD_COMPANY = "company";
public static final String FIELD_COMPANY_ID = "company_id";
public static final String FIELD_COURT = "court";
public static final String FIELD_CUSTOMER = "customer";
public static final String FIELD_CUSTOMER_EMAIL = "customer_email";
public static final String FIELD_CUSTOMER_NUMBER = "customer_number";
public static final String FIELD_CUSTOMER_TAX_NUMBER = "customer_tax_number";
public static final String FIELD_CURRENCY = "currency";
public static final String FIELD_DEFAULT_HEADER = "default_header";
public static final String FIELD_DEFAULT_FOOTER = "default_footer";
public static final String FIELD_DEFAULT_MAIL = "type_mail_text";
@ -53,7 +45,6 @@ public class Constants { @@ -53,7 +45,6 @@ public class Constants {
public static final String FIELD_NET_PRICE = "net_price";
public static final String FIELD_NET_SUM = "net_sum";
public static final String FIELD_NEXT_TYPE = "next_type_id";
public static final String FIELD_PHONE = "phone";
public static final String FIELD_POS = "pos";
public static final String FIELD_POSITIONS = "positions";
public static final String FIELD_PRICE = "single_price";
@ -61,7 +52,6 @@ public class Constants { @@ -61,7 +52,6 @@ public class Constants {
public static final String FIELD_PROJECTS = "projects";
public static final String FIELD_RECEIVER = "receiver";
public static final String FIELD_START_TIME = "start_time";
public static final String FIELD_TAX_NUMBER = "tax_number";
public static final String FIELD_TEMPLATE_ID = "template_id";
public static final String FIELD_TASKS = "tasks";
public static final String FIELD_TAX = "tax";

59
documents/src/main/java/de/srsoftware/umbrella/documents/DocumentApi.java

@ -3,25 +3,29 @@ package de.srsoftware.umbrella.documents; @@ -3,25 +3,29 @@ package de.srsoftware.umbrella.documents;
import static de.srsoftware.tools.MimeType.MIME_FORM_URL;
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
import static de.srsoftware.umbrella.core.Constants.ERROR_MISSING_FIELD;
import static de.srsoftware.umbrella.core.Constants.SENDER;
import static de.srsoftware.umbrella.core.Paths.LIST;
import static de.srsoftware.umbrella.core.Util.request;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.documents.Constants.*;
import static de.srsoftware.umbrella.documents.model.Document.State.NEW;
import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.WARNING;
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
import static java.net.HttpURLConnection.*;
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.UmbrellaException;
import de.srsoftware.umbrella.core.api.CompanyService;
import de.srsoftware.umbrella.core.api.UserService;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Token;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import de.srsoftware.umbrella.documents.model.Type;
import de.srsoftware.umbrella.documents.model.*;
import java.io.IOException;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@ -31,15 +35,17 @@ import org.json.JSONObject; @@ -31,15 +35,17 @@ import org.json.JSONObject;
public class DocumentApi extends BaseHandler {
private final UserService users;
private final CompanyService companies;
private final Configuration config;
private final DocumentDb db;
private final UserService users;
public DocumentApi(UserService userHelper, Configuration config) throws UmbrellaException {
public DocumentApi(CompanyService companyService, Configuration config) throws UmbrellaException {
this.config = config;
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> new UmbrellaException(ERROR_MISSING_FIELD,CONFIG_DATABASE));
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingFieldException(CONFIG_DATABASE));
db = new SqliteDb(connect(dbFile));
users = userHelper;
companies = companyService;
users = companyService.userService();
}
@Override
@ -111,7 +117,7 @@ public class DocumentApi extends BaseHandler { @@ -111,7 +117,7 @@ public class DocumentApi extends BaseHandler {
private boolean listDocuments(HttpExchange ex, UmbrellaUser user, Token token) throws UmbrellaException {
try {
var json = json(ex);
if (!json.has(COMPANY)) throw new UmbrellaException(HTTP_BAD_REQUEST,ERROR_MISSING_FIELD, COMPANY);
if (!json.has(COMPANY)) throw missingFieldException(COMPANY);
long companyId = json.getLong(COMPANY);
var companies = getLegacyCompanies(ex,user, token);
var company = companies.get(companyId);
@ -126,17 +132,34 @@ public class DocumentApi extends BaseHandler { @@ -126,17 +132,34 @@ public class DocumentApi extends BaseHandler {
}
}
private boolean postDocument(HttpExchange ex, UmbrellaUser umbrellaUser) throws IOException, UmbrellaException {
private boolean postDocument(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException {
var json = json(ex);
if (!(json.has(COMPANY) && json.get(COMPANY) instanceof String cid) || cid.isBlank()) throw new UmbrellaException(HTTP_BAD_REQUEST,ERROR_MISSING_FIELD,COMPANY);
long companyId;
try {
companyId = Long.parseLong(cid);
} catch (NumberFormatException nfe){
throw new UmbrellaException(HTTP_BAD_REQUEST,nfe.getMessage());
}
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 = companies.get(companyId.longValue());
var members = companies.getMembers(companyId.longValue());
var match = false;
for (var member : members) match |= user.equals(member);
if (!match) return sendContent(ex,HTTP_FORBIDDEN,"You are mot a member of company "+companyId);
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);
var type = db.getType(docTypeId.intValue());
var customer = Customer.of(customerData);
Template template = new Template(6,companyId.longValue(),"unknwon",null);
String currency = company.currency();
String sep = company.decimalSeparator();
var settings = db.getCustomerSettings(companyId.longValue(),type,customer.id());
var companySettings = db.getCompanySettings(companyId.longValue(),type);
var nextNumber = companySettings.nextDocId();
String lastHead = settings.header();
String lastFooter = settings.footer();
var sender = Sender.of(senderData);
LOG.log(DEBUG,json.toString(2));
return notImplemented(ex,"{0}.postDocument(…)",this);
var doc = new Document(0,companyId.longValue(),nextNumber,type, LocalDate.now(), NEW,template,null,lastHead,lastFooter,currency,sep,sender,customer,new PositionList());
var saved = db.save(doc);
db.step(companySettings);
return sendContent(ex,saved.toMap());
}
}

2
documents/src/main/java/de/srsoftware/umbrella/documents/DocumentDb.java

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
package de.srsoftware.umbrella.documents;
import de.srsoftware.tools.Pair;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.documents.model.CompanySettings;
import de.srsoftware.umbrella.documents.model.CustomerSettings;
import de.srsoftware.umbrella.documents.model.Document;

3
documents/src/main/java/de/srsoftware/umbrella/documents/SqliteDb.java

@ -6,6 +6,7 @@ import static de.srsoftware.tools.jdbc.Condition.equal; @@ -6,6 +6,7 @@ import static de.srsoftware.tools.jdbc.Condition.equal;
import static de.srsoftware.tools.jdbc.Condition.in;
import static de.srsoftware.tools.jdbc.Query.*;
import static de.srsoftware.tools.jdbc.Query.SelectQuery.ALL;
import static de.srsoftware.umbrella.company.Constants.*;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.documents.Constants.*;
import static de.srsoftware.umbrella.documents.model.Document.DEFAULT_THOUSANDS_SEPARATOR;
@ -16,7 +17,7 @@ import static java.time.ZoneOffset.UTC; @@ -16,7 +17,7 @@ import static java.time.ZoneOffset.UTC;
import de.srsoftware.tools.Pair;
import de.srsoftware.tools.jdbc.Query;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.documents.model.*;
import de.srsoftware.umbrella.documents.model.Type;
import java.sql.Connection;

11
documents/src/main/java/de/srsoftware/umbrella/documents/model/Customer.java

@ -2,10 +2,11 @@ @@ -2,10 +2,11 @@
package de.srsoftware.umbrella.documents.model;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.documents.Constants.FIELD_TAX_ID;
import de.srsoftware.tools.Mappable;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
@ -63,10 +64,10 @@ public final class Customer implements Mappable { @@ -63,10 +64,10 @@ public final class Customer implements Mappable {
}
public static Customer of(JSONObject json) throws UmbrellaException {
if (!json.has(ID) || !(json.get(ID) instanceof String id)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,ID);
if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,NAME);
if (!json.has(EMAIL) || !(json.get(EMAIL) instanceof String email)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,EMAIL);
if (!json.has(FIELD_TAX_ID) || !(json.get(FIELD_TAX_ID) instanceof String taxId)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,FIELD_TAX_ID);
if (!json.has(ID) || !(json.get(ID) instanceof String id)) throw missingFieldException(ID);
if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw missingFieldException(NAME);
if (!json.has(EMAIL) || !(json.get(EMAIL) instanceof String email)) throw missingFieldException(EMAIL);
if (!json.has(FIELD_TAX_ID) || !(json.get(FIELD_TAX_ID) instanceof String taxId)) throw missingFieldException(FIELD_TAX_ID);
return new Customer(id,name,email,taxId);
}

2
documents/src/main/java/de/srsoftware/umbrella/documents/model/PositionList.java

@ -5,7 +5,7 @@ import static de.srsoftware.umbrella.core.Constants.*; @@ -5,7 +5,7 @@ import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.documents.Constants.*;
import de.srsoftware.tools.Pair;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONObject;

14
documents/src/main/java/de/srsoftware/umbrella/documents/model/Sender.java

@ -1,12 +1,12 @@ @@ -1,12 +1,12 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.documents.model;
import static de.srsoftware.umbrella.core.Constants.ERROR_MISSING_FIELD;
import static de.srsoftware.umbrella.core.Constants.NAME;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.documents.Constants.*;
import de.srsoftware.tools.Mappable;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
@ -65,10 +65,10 @@ public final class Sender implements Mappable { @@ -65,10 +65,10 @@ public final class Sender implements Mappable {
}
public static Sender of(JSONObject json) throws UmbrellaException {
if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,NAME);
if (!json.has(FIELD_BANK_ACCOUNT) || !(json.get(FIELD_BANK_ACCOUNT) instanceof String bankAccount)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,FIELD_BANK_ACCOUNT);
if (!json.has(FIELD_TAX_ID) || !(json.get(FIELD_TAX_ID) instanceof String taxId)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,FIELD_TAX_ID);
if (!json.has(FIELD_COURT) || !(json.get(FIELD_COURT) instanceof String court)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,FIELD_COURT);
if (!json.has(NAME) || !(json.get(NAME) instanceof String name)) throw missingFieldException(NAME);
if (!json.has(FIELD_BANK_ACCOUNT) || !(json.get(FIELD_BANK_ACCOUNT) instanceof String bankAccount)) throw missingFieldException(FIELD_BANK_ACCOUNT);
if (!json.has(FIELD_TAX_ID) || !(json.get(FIELD_TAX_ID) instanceof String taxId)) throw missingFieldException(FIELD_TAX_ID);
if (!json.has(FIELD_COURT) || !(json.get(FIELD_COURT) instanceof String court)) throw missingFieldException(FIELD_COURT);
return new Sender(name,bankAccount,taxId,court);
}

38
frontend/src/routes/document/AddDocument.svelte

@ -9,13 +9,13 @@ @@ -9,13 +9,13 @@
let error = null;
let docType = $state(null);
let document = $state({
type : router.query.document_type,
company : router.query.company_id,
type : +router.query.document_type,
customer : {
addr : ''
name : ''
},
sender : {
name : 'sender'
name : 'sender',
company : +router.query.company_id
}
});
@ -24,13 +24,13 @@ @@ -24,13 +24,13 @@
var resp = await fetch(url,{ credentials: 'include'});
if (resp.ok){
const companies = await resp.json();
company = companies[document.company];
company = companies[document.sender.company];
document.sender.name = '';
if (company.name) document.sender.name += company.name+"\n";
if (company.address) document.sender.name += company.address+"\n";
if (company.tax_number) document.sender.tax_id = company.tax_number;
if (company.name) document.sender.name += company.name+"\n";
if (company.address) document.sender.name += company.address+"\n";
if (company.tax_number) document.sender.tax_id = company.tax_number;
if (company.bank_account) document.sender.bank_account = company.bank_account;
if (company.court) document.sender.court = company.court;
if (company.court) document.sender.court = company.court;
} else {
error = await resp.text();
}
@ -59,13 +59,13 @@ @@ -59,13 +59,13 @@
var name = (contact.N.given+" "+contact.N.family).trim()+"\n";
if (name != addr) addr += name;
}
if (contact.ADR.street) addr += contact.ADR.street+"\n";
if (contact.ADR.street) addr += contact.ADR.street+"\n";
if (contact.ADR.locality) addr += contact.ADR.post_code + " "+ contact.ADR.locality + "\n";
if (contact.ADR.county) addr += contact.ADR.country+"\n";
document.customer.addr = addr;
document.customer.tax_number = contact['X-TAX-NUMBER'];
document.customer.id = contact['X-CUSTOMER-NUMBER'];
document.customer.email = contact.EMAIL.val;
if (contact.ADR.county) addr += contact.ADR.country+"\n";
document.customer.name = addr;
document.customer.tax_id = contact['X-TAX-NUMBER'];
document.customer.id = contact['X-CUSTOMER-NUMBER'];
document.customer.email = contact.EMAIL.val;
}
async function submit(){
@ -76,6 +76,8 @@ @@ -76,6 +76,8 @@
body: JSON.stringify(document)
});
if (resp.ok){
const json = await resp.json();
router.navigate(`/document/${json.id}/view`);
} else {
error = await resp.text();
}
@ -101,12 +103,12 @@ @@ -101,12 +103,12 @@
<legend>{t('document.customer')}</legend>
<ContactSelector caption={t('document.select_customer')} onselect={contactSelected} />
<label>
<textarea bind:value={document.customer.addr}></textarea>
<textarea bind:value={document.customer.name}></textarea>
{t('document.customer_address')}
</label>
<label>
<input bind:value={document.customer.tax_number} />
{t('document.tax_number')}
<input bind:value={document.customer.tax_id} />
{t('document.tax_id')}
</label>
<label>
<input bind:value={document.customer.id} />

1
legacy/build.gradle.kts

@ -9,6 +9,5 @@ dependencies{ @@ -9,6 +9,5 @@ dependencies{
implementation("de.srsoftware:tools.optionals:1.0.0")
implementation("de.srsoftware:tools.util:2.0.3")
implementation("org.bitbucket.b_c:jose4j:0.9.6")
implementation("org.json:json:20240303")
implementation("org.xerial:sqlite-jdbc:3.49.0.0")
}

2
legacy/src/main/java/de/srsoftware/umbrella/legacy/LegacyApi.java

@ -19,7 +19,7 @@ import de.srsoftware.configuration.Configuration; @@ -19,7 +19,7 @@ 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.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.Session;
import de.srsoftware.umbrella.core.model.Token;
import de.srsoftware.umbrella.core.model.UmbrellaUser;

1
messages/build.gradle.kts

@ -9,6 +9,5 @@ dependencies{ @@ -9,6 +9,5 @@ dependencies{
implementation("de.srsoftware:tools.optionals:1.0.0")
implementation("de.srsoftware:tools.util:2.0.3")
implementation("org.bitbucket.b_c:jose4j:0.9.6")
implementation("org.json:json:20240303")
implementation("org.xerial:sqlite-jdbc:3.49.0.0")
}

2
messages/src/main/java/de/srsoftware/umbrella/message/MessageDb.java

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.message;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import de.srsoftware.umbrella.message.model.Settings;

5
messages/src/main/java/de/srsoftware/umbrella/message/MessageSystem.java

@ -4,12 +4,13 @@ package de.srsoftware.umbrella.message; @@ -4,12 +4,13 @@ package de.srsoftware.umbrella.message;
import static de.srsoftware.tools.PathHandler.CONTENT_TYPE;
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingConfigException;
import static de.srsoftware.umbrella.message.Constants.*;
import static java.lang.System.Logger.Level.*;
import de.srsoftware.configuration.Configuration;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.api.Translator;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import de.srsoftware.umbrella.message.model.CombinedMessage;
import de.srsoftware.umbrella.message.model.Envelope;
@ -70,7 +71,7 @@ public class MessageSystem implements PostBox { @@ -70,7 +71,7 @@ public class MessageSystem implements PostBox {
private final Translator translator;
public MessageSystem(Translator translator, Configuration config) throws UmbrellaException {
var messageDbFile = config.get(CONFIG_DB).orElseThrow(() -> new UmbrellaException(500,ERROR_MISSING_CONFIG,CONFIG_DB));
var messageDbFile = config.get(CONFIG_DB).orElseThrow(() -> missingConfigException(CONFIG_DB));
db = new SqliteMessageDb(connect(messageDbFile));
this.translator = translator;

2
messages/src/main/java/de/srsoftware/umbrella/message/SqliteMessageDb.java

@ -9,7 +9,7 @@ import static java.lang.System.Logger.Level.ERROR; @@ -9,7 +9,7 @@ import static java.lang.System.Logger.Level.ERROR;
import static java.lang.System.Logger.Level.WARNING;
import static java.text.MessageFormat.format;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import de.srsoftware.umbrella.message.model.Settings;
import java.sql.Connection;

12
messages/src/main/java/de/srsoftware/umbrella/message/model/Attachment.java

@ -2,8 +2,10 @@ @@ -2,8 +2,10 @@
package de.srsoftware.umbrella.message.model;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.invalidFieldException;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.util.Arrays;
import java.util.Base64;
import java.util.Objects;
@ -16,11 +18,11 @@ public record Attachment(String name, String mime, byte[] content) { @@ -16,11 +18,11 @@ public record Attachment(String name, String mime, byte[] content) {
public static <T> Attachment of(JSONObject json) throws UmbrellaException {
for (var key : Set.of(NAME, MIME, DATA)) {
if (!json.has(key)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,key);
if (!json.has(key)) throw missingFieldException(key);
}
if (!(json.get(NAME) instanceof String name)) throw new UmbrellaException(400,ERROR_INVALID_FIELD, NAME,STRING);
if (!(json.get(MIME) instanceof String mime)) throw new UmbrellaException(400,ERROR_INVALID_FIELD, MIME,STRING);
if (!(json.get(DATA) instanceof String data)) throw new UmbrellaException(400,ERROR_INVALID_FIELD, DATA,STRING);
if (!(json.get(NAME) instanceof String name)) throw invalidFieldException(NAME,STRING);
if (!(json.get(MIME) instanceof String mime)) throw invalidFieldException(MIME,STRING);
if (!(json.get(DATA) instanceof String data)) throw invalidFieldException(DATA,STRING);
return new Attachment(name,mime, BASE64.decode(data));
}

12
messages/src/main/java/de/srsoftware/umbrella/message/model/Envelope.java

@ -1,12 +1,12 @@ @@ -1,12 +1,12 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.message.model;
import static de.srsoftware.umbrella.core.Constants.ERROR_INVALID_FIELD;
import static de.srsoftware.umbrella.core.Constants.ERROR_MISSING_FIELD;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.invalidFieldException;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.message.Constants.*;
import static java.text.MessageFormat.format;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.EmailAddress;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import java.util.HashSet;
@ -36,14 +36,14 @@ public class Envelope { @@ -36,14 +36,14 @@ public class Envelope {
* @throws UmbrellaException
*/
public static Envelope from(JSONObject json) throws UmbrellaException {
if (!json.has(RECEIVERS)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,RECEIVERS);
if (!json.has(RECEIVERS)) throw missingFieldException(RECEIVERS);
var message = Message.from(json);
var obj = json.get(RECEIVERS);
if (obj instanceof JSONObject) obj = new JSONArray(List.of(obj));
if (!(obj instanceof JSONArray receiverList)) throw new UmbrellaException(400,ERROR_INVALID_FIELD,RECEIVERS,JSONARRAY);
if (!(obj instanceof JSONArray receiverList)) throw invalidFieldException(RECEIVERS,JSONARRAY);
var receivers = new HashSet<UmbrellaUser>();
for (var o : receiverList){
if (!(o instanceof JSONObject receiverData)) throw new UmbrellaException(400,ERROR_INVALID_FIELD,"entries of "+RECEIVERS,JSONOBJECT);
if (!(o instanceof JSONObject receiverData)) throw invalidFieldException("entries of "+RECEIVERS,JSONOBJECT);
receivers.add(UmbrellaUser.of(receiverData));
}
return new Envelope(message,receivers);

12
messages/src/main/java/de/srsoftware/umbrella/message/model/Message.java

@ -3,10 +3,12 @@ package de.srsoftware.umbrella.message.model; @@ -3,10 +3,12 @@ package de.srsoftware.umbrella.message.model;
import static de.srsoftware.tools.Optionals.isSet;
import static de.srsoftware.umbrella.core.Constants.*;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.invalidFieldException;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.message.Constants.*;
import static java.text.MessageFormat.format;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
import java.util.*;
import org.json.JSONArray;
@ -15,11 +17,11 @@ import org.json.JSONObject; @@ -15,11 +17,11 @@ import org.json.JSONObject;
public record Message(UmbrellaUser sender, String subject, String body, Map<String,String> fills, List<Attachment> attachments) {
public static Message from(JSONObject json) throws UmbrellaException {
for (var key : Set.of(SENDER, SUBJECT, BODY)) {
if (!json.has(key)) throw new UmbrellaException(400,ERROR_MISSING_FIELD,key);
if (!json.has(key)) throw missingFieldException(key);
}
if (!(json.get(SENDER) instanceof JSONObject senderObject)) throw new UmbrellaException(400,ERROR_INVALID_FIELD, SENDER,JSONOBJECT);
if (!(json.get(SUBJECT) instanceof String subject && isSet(subject))) throw new UmbrellaException(400,ERROR_INVALID_FIELD, SUBJECT,STRING);
if (!(json.get(BODY) instanceof String body && isSet(body))) throw new UmbrellaException(400,ERROR_INVALID_FIELD, BODY,STRING);
if (!(json.get(SENDER) instanceof JSONObject senderObject)) throw invalidFieldException(SENDER,JSONOBJECT);
if (!(json.get(SUBJECT) instanceof String subject && isSet(subject))) throw invalidFieldException(SUBJECT,STRING);
if (!(json.get(BODY) instanceof String body && isSet(body))) throw invalidFieldException(BODY,STRING);
var user = UmbrellaUser.of(senderObject);
if (!(user instanceof UmbrellaUser sender)) throw new UmbrellaException(400,"Sender is not an umbrella user!");

1
translations/build.gradle.kts

@ -2,5 +2,4 @@ description = "Umbrella : Translations" @@ -2,5 +2,4 @@ description = "Umbrella : Translations"
dependencies{
implementation(project(":core"))
implementation("org.json:json:20240303")
}

1
user/build.gradle.kts

@ -9,6 +9,5 @@ dependencies{ @@ -9,6 +9,5 @@ dependencies{
implementation("de.srsoftware:tools.optionals:1.0.0")
implementation("de.srsoftware:tools.util:2.0.3")
implementation("org.bitbucket.b_c:jose4j:0.9.6")
implementation("org.json:json:20240303")
implementation("org.xerial:sqlite-jdbc:3.49.0.0")
}

34
user/src/main/java/de/srsoftware/umbrella/user/UserModule.java

@ -12,6 +12,8 @@ import static de.srsoftware.umbrella.core.ResponseCode.*; @@ -12,6 +12,8 @@ import static de.srsoftware.umbrella.core.ResponseCode.*;
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_SERVER_ERROR;
import static de.srsoftware.umbrella.core.Util.open;
import static de.srsoftware.umbrella.core.Util.request;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingConfigException;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingFieldException;
import static de.srsoftware.umbrella.user.Constants.*;
import static de.srsoftware.umbrella.user.Paths.*;
import static de.srsoftware.umbrella.user.Paths.IMPERSONATE;
@ -29,8 +31,8 @@ import de.srsoftware.configuration.Configuration; @@ -29,8 +31,8 @@ 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.UmbrellaException;
import de.srsoftware.umbrella.core.api.UserService;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.EmailAddress;
import de.srsoftware.umbrella.core.model.Token;
import de.srsoftware.umbrella.core.model.UmbrellaUser;
@ -84,7 +86,7 @@ public class UserModule extends BaseHandler implements UserService { @@ -84,7 +86,7 @@ public class UserModule extends BaseHandler implements UserService {
}
public UserModule(Configuration config, MessageSystem messageSystem) throws UmbrellaException {
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> new UmbrellaException(ERROR_MISSING_CONFIG,CONFIG_DATABASE));
var dbFile = config.get(CONFIG_DATABASE).orElseThrow(() -> missingConfigException(CONFIG_DATABASE));
// may be splitted in separate db files later
logins = new SqliteDB(connect(dbFile));
messages = messageSystem;
@ -97,11 +99,15 @@ public class UserModule extends BaseHandler implements UserService { @@ -97,11 +99,15 @@ public class UserModule extends BaseHandler implements UserService {
private boolean deleteOIDC(HttpExchange ex, UmbrellaUser user, Path path) throws IOException {
var head = path.pop();
return switch (head){
case CONNECTED -> deleteServiceConnection(ex,user);
case null -> super.doGet(path,ex);
default -> deleteService(ex,user,head);
};
try {
return switch (head) {
case CONNECTED -> deleteServiceConnection(ex, user);
case null -> super.doGet(path, ex);
default -> deleteService(ex, user, head);
};
} catch (UmbrellaException e) {
return send(ex,e);
}
}
private boolean deleteService(HttpExchange ex, UmbrellaUser user, String serviceName) throws IOException {
@ -114,7 +120,7 @@ public class UserModule extends BaseHandler implements UserService { @@ -114,7 +120,7 @@ public class UserModule extends BaseHandler implements UserService {
}
}
private boolean deleteServiceConnection(HttpExchange ex, UmbrellaUser user) throws IOException {
private boolean deleteServiceConnection(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException {
if (user == null) return sendContent(ex,HTTP_SERVER_ERROR,"Expected user object to be of type DbUser");
JSONObject json;
try {
@ -123,8 +129,8 @@ public class UserModule extends BaseHandler implements UserService { @@ -123,8 +129,8 @@ public class UserModule extends BaseHandler implements UserService {
LOG.log(WARNING,"Request does not contain valid JSON",e);
return sendContent(ex,HTTP_FAILED_DEPENDENCY,"Request does not contain valid JSON");
}
if (!(json.has(FOREIGN_ID) && json.get(FOREIGN_ID) instanceof String foreignId && !foreignId.isBlank())) return sendContent(ex,HTTP_UNPROCESSABLE,format(ERROR_MISSING_FIELD,FOREIGN_ID));
if (!(json.has(SERVICE_ID) && json.get(SERVICE_ID) instanceof String serviceId && !serviceId.isBlank())) return sendContent(ex,HTTP_UNPROCESSABLE,format(ERROR_MISSING_FIELD,SERVICE_ID));
if (!(json.has(FOREIGN_ID) && json.get(FOREIGN_ID) instanceof String foreignId && !foreignId.isBlank())) throw missingFieldException(FOREIGN_ID);
if (!(json.has(SERVICE_ID) && json.get(SERVICE_ID) instanceof String serviceId && !serviceId.isBlank())) throw missingFieldException(SERVICE_ID);
try {
@ -501,10 +507,10 @@ public class UserModule extends BaseHandler implements UserService { @@ -501,10 +507,10 @@ public class UserModule extends BaseHandler implements UserService {
if (!(requestingUser instanceof DbUser user && user.permissions().contains(MANAGE_LOGIN_SERVICES))) return forbidden(ex);
try {
var json = json(ex);
if (!json.has(NAME) || !(json.get(NAME) instanceof String name) || name.isBlank()) return sendContent(ex,HTTP_UNPROCESSABLE,format(ERROR_MISSING_FIELD,NAME));
if (!json.has(URL) || !(json.get(URL) instanceof String url) || url.isBlank()) return sendContent(ex,HTTP_UNPROCESSABLE,format(ERROR_MISSING_FIELD,URL));
if (!json.has(CLIENT_ID) || !(json.get(CLIENT_ID) instanceof String clientId) || clientId.isBlank()) return sendContent(ex,HTTP_UNPROCESSABLE,format(ERROR_MISSING_FIELD,CLIENT_ID));
if (!json.has(CLIENT_SECRET) || !(json.get(CLIENT_SECRET) instanceof String secret) || secret.isBlank()) return sendContent(ex,HTTP_UNPROCESSABLE,format(ERROR_MISSING_FIELD,CLIENT_SECRET));
if (!json.has(NAME) || !(json.get(NAME) instanceof String name) || name.isBlank()) throw missingFieldException(NAME);
if (!json.has(URL) || !(json.get(URL) instanceof String url) || url.isBlank()) throw missingFieldException(URL);
if (!json.has(CLIENT_ID) || !(json.get(CLIENT_ID) instanceof String clientId) || clientId.isBlank()) throw missingFieldException(CLIENT_ID);
if (!json.has(CLIENT_SECRET) || !(json.get(CLIENT_SECRET) instanceof String secret) || secret.isBlank()) throw missingFieldException(CLIENT_SECRET);
var service = logins.save(new LoginService(name,url,clientId,secret, DEFAULT_FIELD));
return sendContent(ex,service.toMap());
} catch (UmbrellaException e) {

2
user/src/main/java/de/srsoftware/umbrella/user/api/LoginServiceDb.java

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.user.api;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.user.model.ForeignLogin;
import de.srsoftware.umbrella.user.model.LoginService;
import java.util.List;

2
user/src/main/java/de/srsoftware/umbrella/user/api/UserDb.java

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
/* © SRSoftware 2025 */
package de.srsoftware.umbrella.user.api;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.EmailAddress;
import de.srsoftware.umbrella.core.model.Session;
import de.srsoftware.umbrella.core.model.Token;

2
user/src/main/java/de/srsoftware/umbrella/user/sqlite/SqliteDB.java

@ -12,7 +12,7 @@ import static java.text.MessageFormat.format; @@ -12,7 +12,7 @@ import static java.text.MessageFormat.format;
import de.srsoftware.tools.PasswordHasher;
import de.srsoftware.tools.jdbc.Query;
import de.srsoftware.umbrella.core.UmbrellaException;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import de.srsoftware.umbrella.core.model.EmailAddress;
import de.srsoftware.umbrella.core.model.Session;
import de.srsoftware.umbrella.core.model.Token;

Loading…
Cancel
Save