|
|
|
|
@ -4,11 +4,13 @@ package de.srsoftware.umbrella.files;
@@ -4,11 +4,13 @@ package de.srsoftware.umbrella.files;
|
|
|
|
|
import static de.srsoftware.umbrella.core.ConnectionProvider.connect; |
|
|
|
|
import static de.srsoftware.umbrella.core.Constants.*; |
|
|
|
|
import static de.srsoftware.umbrella.core.ModuleRegistry.*; |
|
|
|
|
import static de.srsoftware.umbrella.core.ResponseCode.HTTP_SERVER_ERROR; |
|
|
|
|
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.*; |
|
|
|
|
import static de.srsoftware.umbrella.files.Constants.CONFIG_DATABASE; |
|
|
|
|
import static de.srsoftware.umbrella.files.Constants.CONFIG_FILESTORE; |
|
|
|
|
import static java.net.HttpURLConnection.HTTP_OK; |
|
|
|
|
import static java.nio.charset.StandardCharsets.UTF_8; |
|
|
|
|
import static java.text.MessageFormat.format; |
|
|
|
|
|
|
|
|
|
import com.sun.net.httpserver.HttpExchange; |
|
|
|
|
import de.srsoftware.configuration.Configuration; |
|
|
|
|
@ -51,6 +53,110 @@ public class FileModule extends BaseHandler implements FileService {
@@ -51,6 +53,110 @@ public class FileModule extends BaseHandler implements FileService {
|
|
|
|
|
ModuleRegistry.add(this); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public boolean doDelete(Path path, HttpExchange ex) throws IOException { |
|
|
|
|
addCors(ex); |
|
|
|
|
try { |
|
|
|
|
Optional<Token> token = SessionToken.from(ex).map(Token::of); |
|
|
|
|
var user = userService().loadUser(token); |
|
|
|
|
if (user.isEmpty()) return unauthorized(ex); |
|
|
|
|
var head = path.pop(); |
|
|
|
|
return switch (head){ |
|
|
|
|
case COMPANY -> deleteCompanyFile(path, ex, user.get()); |
|
|
|
|
case PROJECT -> deleteProjectFile(path, ex, user.get()); |
|
|
|
|
case USER -> deleteUserFile(path, ex, user.get()); |
|
|
|
|
case null, default -> throw UmbrellaException.notFound("invalid location: {0}", head); |
|
|
|
|
}; |
|
|
|
|
} catch (UmbrellaException e) { |
|
|
|
|
return send(ex,e); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private boolean deleteCompanyFile(Path path, HttpExchange ex, UmbrellaUser user) throws IOException { |
|
|
|
|
var cpId = path.pop(); |
|
|
|
|
var companies = companyService(); |
|
|
|
|
Map<Long, Company> companyList; |
|
|
|
|
if (cpId == null){ |
|
|
|
|
companyList = companies.listCompaniesOf(user); |
|
|
|
|
var map = companyList.values().stream().collect(Collectors.toMap(company -> "/company/"+company.id(), Company::name)); |
|
|
|
|
return sendContent(ex,Map.of("dirs",map)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
long cid; |
|
|
|
|
try { |
|
|
|
|
cid = Long.parseLong(cpId); |
|
|
|
|
} catch (NumberFormatException e) { |
|
|
|
|
throw invalidFieldException(COMPANY_ID,"Long"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var company = companies.get(cid); |
|
|
|
|
var filename = "/company/"+cid; |
|
|
|
|
if (!path.empty()) filename += "/"+URLDecoder.decode(path.toString(),UTF_8); |
|
|
|
|
if (!companies.membership(cid,user.id()) && !fileDb.isPermitted(user,filename)) throw forbidden("You are not allowed to access {0}",filename); |
|
|
|
|
var file = new File(baseDir+filename); |
|
|
|
|
if (!file.exists()) throw unprocessable("{0} does not exist!",filename); |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private boolean deleteProjectFile(Path path, HttpExchange ex, UmbrellaUser user) throws IOException { |
|
|
|
|
var prjId = path.pop(); |
|
|
|
|
var projects = projectService(); |
|
|
|
|
if (prjId == null){ |
|
|
|
|
var projectList = projects.listUserProjects(user.id(),true); |
|
|
|
|
var map = projectList.values().stream().collect(Collectors.toMap(prj -> "/project/"+prj.id(),Project::name)); |
|
|
|
|
return sendContent(ex,Map.of("dirs",map)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
long pid; |
|
|
|
|
try { |
|
|
|
|
pid = Long.parseLong(prjId); |
|
|
|
|
} catch (NumberFormatException e) { |
|
|
|
|
throw invalidFieldException(PROJECT_ID,"Long"); |
|
|
|
|
} |
|
|
|
|
var project = projects.loadMembers(projects.load(pid)); |
|
|
|
|
var filename = "/project/"+pid; |
|
|
|
|
if (!path.empty()) filename += "/"+URLDecoder.decode(path.toString(),UTF_8); |
|
|
|
|
if (!project.hasMember(user) && !fileDb.isPermitted(user,filename)) throw forbidden("You are not allowed to access {0}",filename); |
|
|
|
|
return deleteFile(ex, new File(baseDir+filename)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static boolean dropDir(File dir) { |
|
|
|
|
File[] nested = dir.listFiles(); |
|
|
|
|
if (nested != null) { |
|
|
|
|
for (File file : nested) { |
|
|
|
|
if (!dropDir(file)) return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return dir.delete(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private boolean deleteFile(HttpExchange ex, File file) throws IOException { |
|
|
|
|
if (!file.exists()) throw unprocessable("{0} does not exist!",file.getName()); |
|
|
|
|
if (!dropDir(file)) return sendContent(ex,HTTP_SERVER_ERROR,format("Failed to delete {0}",file.getName())); |
|
|
|
|
Map<String,Object> map = getDirectory(file.getParentFile()); |
|
|
|
|
map.put("title",file.getName()); |
|
|
|
|
return sendContent(ex,map); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private boolean deleteUserFile(Path path, HttpExchange ex, UmbrellaUser user) { |
|
|
|
|
var userId = path.pop(); |
|
|
|
|
if (userId == null) throw missingFieldException(USER_ID); |
|
|
|
|
long uid; |
|
|
|
|
try { |
|
|
|
|
uid = Long.parseLong(userId); |
|
|
|
|
} catch (NumberFormatException e) { |
|
|
|
|
throw invalidFieldException(PROJECT_ID,"Long"); |
|
|
|
|
} |
|
|
|
|
var filename = "/user/"+uid; |
|
|
|
|
if (!path.empty()) filename += "/"+URLDecoder.decode(path.toString(),UTF_8); |
|
|
|
|
if (uid != user.id() && !fileDb.isPermitted(user,filename)) throw forbidden("You are not allowed to access {0}",filename); |
|
|
|
|
var file = new File(baseDir+filename); |
|
|
|
|
if (!file.exists()) throw unprocessable("{0} does not exist!",filename); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public boolean doGet(Path path, HttpExchange ex) throws IOException { |
|
|
|
|
addCors(ex); |
|
|
|
|
|