extended search to projects
This commit is contained in:
@@ -5,13 +5,18 @@ 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.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ProjectDb {
|
||||
void dropMember(long projectId, long userId);
|
||||
Map<Long, Project> find(long userId, Collection<String> keys, boolean fulltext);
|
||||
Map<Long, Permission> getMembers(Project project);
|
||||
Project load(long projectId) throws UmbrellaException;
|
||||
Map<Long, Project> ofCompany(long companyId, boolean includeClosed) throws UmbrellaException;
|
||||
|
||||
Map<Long, Project> ofUser(long userId, boolean includeClosed) throws UmbrellaException;
|
||||
|
||||
Project save(Project prj) throws UmbrellaException;
|
||||
|
||||
@@ -4,6 +4,7 @@ package de.srsoftware.umbrella.project;
|
||||
import static de.srsoftware.umbrella.core.ConnectionProvider.connect;
|
||||
import static de.srsoftware.umbrella.core.Constants.*;
|
||||
import static de.srsoftware.umbrella.core.Paths.LIST;
|
||||
import static de.srsoftware.umbrella.core.Paths.SEARCH;
|
||||
import static de.srsoftware.umbrella.core.Util.mapValues;
|
||||
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*;
|
||||
import static de.srsoftware.umbrella.core.model.Permission.*;
|
||||
@@ -29,12 +30,12 @@ import org.json.JSONObject;
|
||||
|
||||
public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
|
||||
private final ProjectDb projects;
|
||||
private final ProjectDb projectDb;
|
||||
|
||||
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));
|
||||
projectDb = new SqliteDb(connect(dbFile));
|
||||
}
|
||||
|
||||
private void addMember(Project project, long userId) {
|
||||
@@ -101,6 +102,7 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
var head = path.pop();
|
||||
return switch (head) {
|
||||
case LIST -> postProjectList(ex, user.get());
|
||||
case SEARCH -> postSearch(user.get(),ex);
|
||||
case null -> postProject(ex, user.get());
|
||||
default -> {
|
||||
var projectId = Long.parseLong(head);
|
||||
@@ -120,12 +122,12 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
|
||||
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);
|
||||
projectDb.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));
|
||||
var project = loadMembers(projectDb.load(projectId));
|
||||
if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name());
|
||||
var map = project.toMap();
|
||||
project.companyId().map(companyService()::get).map(Company::toMap).ifPresent(data -> map.put(COMPANY,data));
|
||||
@@ -133,7 +135,7 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
}
|
||||
|
||||
public Map<Long, Project> listCompanyProjects(long companyId, boolean includeClosed) throws UmbrellaException {
|
||||
var projectList = projects.ofCompany(companyId, includeClosed);
|
||||
var projectList = projectDb.ofCompany(companyId, includeClosed);
|
||||
loadMembers(projectList.values());
|
||||
return projectList;
|
||||
}
|
||||
@@ -147,7 +149,7 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
|
||||
@Override
|
||||
public Map<Long, Project> listUserProjects(long userId, boolean includeClosed) throws UmbrellaException {
|
||||
var projectMap = projects.ofUser(userId, includeClosed);
|
||||
var projectMap = projectDb.ofUser(userId, includeClosed);
|
||||
loadMembers(projectMap.values());
|
||||
return projectMap;
|
||||
}
|
||||
@@ -159,14 +161,14 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
|
||||
@Override
|
||||
public Project load(long projectId) {
|
||||
return projects.load(projectId);
|
||||
return projectDb.load(projectId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Project> loadMembers(Collection<Project> projectList) {
|
||||
var userMap = new HashMap<Long,UmbrellaUser>();
|
||||
for (var project : projectList){
|
||||
for (var entry : projects.getMembers(project).entrySet()){
|
||||
for (var entry : projectDb.getMembers(project).entrySet()){
|
||||
var userId = entry.getKey();
|
||||
var permission = entry.getValue();
|
||||
var user = userMap.computeIfAbsent(userId,k -> userService().loadUser(userId));
|
||||
@@ -199,14 +201,14 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
}
|
||||
|
||||
private boolean patchProject(HttpExchange ex, long projectId, UmbrellaUser user) throws IOException, UmbrellaException {
|
||||
var project = loadMembers(projects.load(projectId));
|
||||
var project = loadMembers(projectDb.load(projectId));
|
||||
if (!project.hasMember(user)) throw forbidden("You are not a member of {0}",project.name());
|
||||
var json = json(ex);
|
||||
if (json.has(DROP_MEMBER) && json.get(DROP_MEMBER) instanceof Number id) dropMember(project,id.longValue());
|
||||
if (json.has(MEMBERS) && json.get(MEMBERS) instanceof JSONObject memberJson) patchMembers(project,memberJson);
|
||||
if (json.has(NEW_MEMBER) && json.get(NEW_MEMBER) instanceof Number num) addMember(project,num.longValue());
|
||||
|
||||
projects.save(project.patch(json));
|
||||
projectDb.save(project.patch(json));
|
||||
return sendContent(ex,project.toMap());
|
||||
}
|
||||
|
||||
@@ -218,7 +220,7 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
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));
|
||||
return sendContent(ex, projectDb.save(projectId,newState));
|
||||
}
|
||||
|
||||
private boolean postProject(HttpExchange ex, UmbrellaUser user) throws IOException, UmbrellaException {
|
||||
@@ -241,7 +243,7 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
}
|
||||
var owner = Map.of(user.id(),new Member(user,OWNER));
|
||||
var prj = new Project(0,name,description, OPEN.code(),companyId,showClosed, owner, PREDEFINED);
|
||||
prj = projects.save(prj);
|
||||
prj = projectDb.save(prj);
|
||||
|
||||
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();
|
||||
@@ -257,4 +259,14 @@ public class ProjectModule extends BaseHandler implements ProjectService {
|
||||
if (json.has(COMPANY_ID) && json.get(COMPANY_ID) instanceof Number companyId) return listCompanyProjects(ex, user, companyId.longValue());
|
||||
return listUserProjects(ex,user,showClosed);
|
||||
}
|
||||
|
||||
|
||||
private boolean postSearch(UmbrellaUser user, HttpExchange ex) throws IOException {
|
||||
var json = json(ex);
|
||||
if (!(json.has(KEY) && json.get(KEY) instanceof String key)) throw missingFieldException(KEY);
|
||||
var keys = Arrays.asList(key.split(" "));
|
||||
var fulltext = json.has(FULLTEXT) && json.get(FULLTEXT) instanceof Boolean val && val;
|
||||
var projects = projectDb.find(user.id(),keys,fulltext);
|
||||
return sendContent(ex,mapValues(projects));
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import static de.srsoftware.umbrella.core.model.Status.COMPLETE;
|
||||
import static de.srsoftware.umbrella.core.model.Status.OPEN;
|
||||
import static de.srsoftware.umbrella.project.Constants.*;
|
||||
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.BaseDb;
|
||||
@@ -18,6 +19,7 @@ import de.srsoftware.umbrella.core.model.Project;
|
||||
import de.srsoftware.umbrella.core.model.Status;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -163,7 +165,24 @@ CREATE TABLE IF NOT EXISTS {0} (
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<Long, Project> find(long userId, Collection<String> keys, boolean fulltext) {
|
||||
try {
|
||||
var projects = new HashMap<Long,Project>();
|
||||
var query = select(ALL).from(TABLE_PROJECTS).leftJoin(ID,TABLE_PROJECT_USERS,PROJECT_ID).where(USER_ID, equal(userId));
|
||||
for (var key : keys) query.where(NAME,like("%"+key+"%"));
|
||||
LOG.log(WARNING,"Full-text search not implemented for projects");
|
||||
var rs = query.exec(db);
|
||||
while (rs.next()){
|
||||
var project = Project.of(rs);
|
||||
projects.put(project.id(),project);
|
||||
}
|
||||
rs.close();
|
||||
return projects;
|
||||
} catch (SQLException e) {
|
||||
throw new UmbrellaException("Failed to load items from database");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, Project> ofUser(long userId, boolean includeClosed) throws UmbrellaException {
|
||||
|
||||
Reference in New Issue
Block a user