completed user-defined states
This commit is contained in:
@@ -3,9 +3,11 @@ package de.srsoftware.umbrella.project;
|
||||
|
||||
public class Constants {
|
||||
private Constants(){}
|
||||
|
||||
public static final String CONFIG_DATABASE = "umbrella.modules.project.database";
|
||||
public static final String DB_VERSION = "project_db_version";
|
||||
public static final String PERMISSIONS = "permissions";
|
||||
public static final String TABLE_CUSTOM_STATES = "custom_states";
|
||||
public static final String TABLE_PROJECTS = "projects";
|
||||
public static final String TABLE_PROJECT_USERS = "projects_users";
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ package de.srsoftware.umbrella.project;
|
||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||
import de.srsoftware.umbrella.core.model.Permission;
|
||||
import de.srsoftware.umbrella.core.model.Project;
|
||||
import de.srsoftware.umbrella.core.model.Status;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface ProjectDb {
|
||||
@@ -14,4 +16,6 @@ public interface ProjectDb {
|
||||
Map<Long, Project> ofUser(long userId, boolean includeClosed) throws UmbrellaException;
|
||||
|
||||
Project save(Project prj) throws UmbrellaException;
|
||||
|
||||
Status save(long projectId, Status newState);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import static de.srsoftware.umbrella.core.model.Status.OPEN;
|
||||
import static de.srsoftware.umbrella.core.model.Status.PREDEFINED;
|
||||
import static de.srsoftware.umbrella.project.Constants.CONFIG_DATABASE;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
|
||||
import static java.net.HttpURLConnection.HTTP_OK;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
@@ -73,7 +74,6 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
head = path.pop();
|
||||
yield switch (head) {
|
||||
case null -> getProject(ex, projectId, user.get());
|
||||
case STATES -> super.doGet(path, ex); // TODO THIS SHOULD NO LONGER BE REQUIRED
|
||||
default -> super.doGet(path, ex);
|
||||
};
|
||||
}
|
||||
@@ -121,15 +121,30 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
if (user.isEmpty()) return unauthorized(ex);
|
||||
var head = path.pop();
|
||||
return switch (head) {
|
||||
case LIST -> postProjectList(ex,user.get());
|
||||
case null -> postProject(ex,user.get());
|
||||
default -> super.doGet(path,ex);
|
||||
case LIST -> postProjectList(ex, user.get());
|
||||
case null -> postProject(ex, user.get());
|
||||
default -> {
|
||||
var projectId = Long.parseLong(head);
|
||||
head = path.pop();
|
||||
yield switch (head){
|
||||
case STATE -> postNewState(ex,projectId,user.get());
|
||||
case null, default -> super.doGet(path, ex);
|
||||
};
|
||||
}
|
||||
};
|
||||
} catch (NumberFormatException e){
|
||||
return sendContent(ex,HTTP_BAD_REQUEST,"Invalid project id");
|
||||
} catch (UmbrellaException e){
|
||||
return send(ex,e);
|
||||
}
|
||||
}
|
||||
|
||||
private void dropMember(Project project, long userId) {
|
||||
if (project.members().get(userId).permission() == OWNER) throw forbidden("You may not remove the owner of the project");
|
||||
projects.dropMember(project.id(),userId);
|
||||
project.members().remove(userId);
|
||||
}
|
||||
|
||||
private boolean getProject(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException, UmbrellaException {
|
||||
var project = loadMembers(projects.load(projectId));
|
||||
if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name());
|
||||
@@ -216,12 +231,16 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
return sendContent(ex,project.toMap());
|
||||
}
|
||||
|
||||
private void dropMember(Project project, long userId) {
|
||||
if (project.members().get(userId).permission() == OWNER) throw forbidden("You may not remove the owner of the project");
|
||||
projects.dropMember(project.id(),userId);
|
||||
project.members().remove(userId);
|
||||
}
|
||||
|
||||
private boolean postNewState(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException {
|
||||
var project = loadMembers(load(projectId));
|
||||
if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name());
|
||||
var json = json(ex);
|
||||
if (!(json.has(CODE) && json.get(CODE) instanceof Number code)) throw missingFieldException(CODE);
|
||||
if (!(json.has(NAME) && json.get(NAME) instanceof String name)) throw missingFieldException(NAME);
|
||||
var newState = new Status(name,code.intValue());
|
||||
return sendContent(ex,projects.save(projectId,newState));
|
||||
}
|
||||
|
||||
private boolean postProject(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException {
|
||||
var json = json(ex);
|
||||
|
||||
@@ -17,7 +17,10 @@ import de.srsoftware.tools.jdbc.Query;
|
||||
import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
|
||||
import de.srsoftware.umbrella.core.model.Permission;
|
||||
import de.srsoftware.umbrella.core.model.Project;
|
||||
import de.srsoftware.umbrella.core.model.Status;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
@@ -34,40 +37,60 @@ public class SqliteDb implements ProjectDb {
|
||||
init();
|
||||
}
|
||||
|
||||
private int createTables() {
|
||||
createProjectTables();
|
||||
return createSettingsTable();
|
||||
}
|
||||
|
||||
private void createProjectTables() {
|
||||
private void createProjectTable() {
|
||||
var createTable = """
|
||||
CREATE TABLE IF NOT EXISTS {0} (
|
||||
`{1}` INTEGER PRIMARY KEY,
|
||||
`{2}` INTEGER,
|
||||
`{3}` VARCHAR(255) NOT NULL,
|
||||
`{4}` TEXT,
|
||||
`{5}` INT DEFAULT {6},
|
||||
`{7}` BOOLEAN DEFAULT 0
|
||||
)""";
|
||||
CREATE TABLE IF NOT EXISTS {0} (
|
||||
`{1}` INTEGER PRIMARY KEY,
|
||||
`{2}` INTEGER,
|
||||
`{3}` VARCHAR(255) NOT NULL,
|
||||
`{4}` TEXT,
|
||||
`{5}` INT DEFAULT {6},
|
||||
`{7}` BOOLEAN DEFAULT 0
|
||||
)""";
|
||||
try {
|
||||
var stmt = db.prepareStatement(format(createTable,TABLE_PROJECTS, ID, COMPANY_ID, NAME, DESCRIPTION, STATUS, OPEN.code(), SHOW_CLOSED));
|
||||
var stmt = db.prepareStatement(format(createTable, TABLE_PROJECTS, ID, COMPANY_ID, NAME, DESCRIPTION, STATUS, OPEN.code(), SHOW_CLOSED));
|
||||
stmt.execute();
|
||||
stmt.close();
|
||||
} catch (SQLException e) {
|
||||
LOG.log(ERROR,ERROR_FAILED_CREATE_TABLE,TABLE_PROJECTS ,e);
|
||||
LOG.log(ERROR, ERROR_FAILED_CREATE_TABLE, TABLE_PROJECTS, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void createStatesTable(){
|
||||
var sql = """
|
||||
CREATE TABLE IF NOT EXISTS custom_states (
|
||||
project_id LONG NOT NULL,
|
||||
code INT NOT NULL,
|
||||
name VARCHAR(64) NOT NULL,
|
||||
PRIMARY KEY (project_id, code)
|
||||
);
|
||||
""";
|
||||
try {
|
||||
var stmt = db.prepareStatement(format(sql));
|
||||
stmt.execute();
|
||||
stmt.close();
|
||||
} catch (SQLException e) {
|
||||
LOG.log(ERROR, ERROR_FAILED_CREATE_TABLE, TABLE_CUSTOM_STATES, e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
long count = 0L;
|
||||
try {
|
||||
ResultSet rs = select("COUNT(*)").from(TABLE_PROJECTS).exec(db);
|
||||
if (rs.next()) count = rs.getLong(1);
|
||||
rs.close();
|
||||
} catch (SQLException ignored) {
|
||||
// go on with table creation
|
||||
}
|
||||
}
|
||||
|
||||
createTable = """
|
||||
private int createTables() {
|
||||
int currentVersion = createSettingsTable();
|
||||
switch (currentVersion){
|
||||
case 0:
|
||||
createProjectTable();
|
||||
createUsersTable();
|
||||
case 1:
|
||||
createStatesTable();
|
||||
}
|
||||
return setCurrentVersion(2);
|
||||
}
|
||||
|
||||
private void createUsersTable(){
|
||||
var createTable = """
|
||||
CREATE TABLE IF NOT EXISTS {0} (
|
||||
{1} INT NOT NULL,
|
||||
{2} INT NOT NULL,
|
||||
@@ -97,15 +120,11 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255)
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
Integer version = null;
|
||||
var version = 0;
|
||||
try {
|
||||
var rs = Query.select(VALUE).from(TABLE_SETTINGS).where(KEY, equal(DB_VERSION)).exec(db);
|
||||
if (rs.next()) version = rs.getInt(VALUE);
|
||||
rs.close();
|
||||
if (version == null) {
|
||||
version = INITIAL_DB_VERSION;
|
||||
insertInto(TABLE_SETTINGS, KEY, VALUE).values(DB_VERSION,version).execute(db).close();
|
||||
}
|
||||
|
||||
return version;
|
||||
} catch (SQLException e) {
|
||||
@@ -152,6 +171,10 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255)
|
||||
if (rs.next()) result = Project.of(rs);
|
||||
rs.close();
|
||||
if (result == null) throw UmbrellaException.notFound("No project found for id {0}",projectId);
|
||||
rs = select(ALL).from(TABLE_CUSTOM_STATES).where(PROJECT_ID,equal(projectId)).exec(db);
|
||||
var states = result.allowedStates();
|
||||
while (rs.next()) states.add(Status.of(rs));
|
||||
rs.close();
|
||||
return result;
|
||||
} catch (SQLException e) {
|
||||
throw new UmbrellaException("Failed to load project from database");
|
||||
@@ -236,4 +259,24 @@ CREATE TABLE IF NOT EXISTS {0} ( {1} VARCHAR(255) PRIMARY KEY, {2} VARCHAR(255)
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Status save(long projectId, Status newState) {
|
||||
try {
|
||||
insertInto(TABLE_CUSTOM_STATES,PROJECT_ID,CODE,NAME).values(projectId,newState.code(),newState.name()).execute(db).close();
|
||||
return newState;
|
||||
} catch (SQLException e) {
|
||||
throw new UmbrellaException("Failed to create custom state!");
|
||||
}
|
||||
}
|
||||
|
||||
private int setCurrentVersion(int version) {
|
||||
try {
|
||||
replaceInto(TABLE_SETTINGS, KEY, VALUE).values(DB_VERSION,version).execute(db).close();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user