Skip to content

Commit

Permalink
Adding workspaces
Browse files Browse the repository at this point in the history
  • Loading branch information
JulianFun123 committed Nov 10, 2024
1 parent 6c8b21e commit b87cd6f
Show file tree
Hide file tree
Showing 22 changed files with 781 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ public PaginatedResponse<DomainResponse> getAll(Exchange exchange, @Attrib("user

@Post
@With("auth")
public DomainResponse create(@Body CreateDomainRequest request, @Attrib("user") User user) {
public DomainResponse create(@Body CreateDomainRequest request, @Attrib("user") User user, @Attrib("token") AccessToken accessToken) {
accessToken.checkPermission("domains:write");
Domain domain = new Domain();

request.name = request.name.toLowerCase();
Expand Down Expand Up @@ -167,6 +168,8 @@ public ActionResponse delete(@Path("id") String id, @Attrib("token") AccessToken
@Post("/{id}/dns-check")
@With("auth")
public ActionResponse triggerDomainCheck(@Path("id") String id, @Attrib("token") AccessToken accessToken, @Attrib("user") User user) {
accessToken.checkPermission("domains:write");

Domain domain = Domain.get(id, false);
if (domain == null)
throw new NotFoundException();
Expand All @@ -175,7 +178,6 @@ public ActionResponse triggerDomainCheck(@Path("id") String id, @Attrib("token")
if (domainUser == null || domainUser.role != DomainUser.Role.ADMIN)
throw new PermissionsDeniedException();

accessToken.checkPermission("domains:write");

domain.updateStatus();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
import de.interaapps.punyshort.helper.RequestHelper;
import de.interaapps.punyshort.model.database.AccessToken;
import de.interaapps.punyshort.model.database.ShortenLink;
import de.interaapps.punyshort.model.database.ShortenLinkTag;
import de.interaapps.punyshort.model.database.User;
import de.interaapps.punyshort.model.database.domains.Domain;
import de.interaapps.punyshort.model.database.stats.ShortenLinkClickPerDateStats;
import de.interaapps.punyshort.model.database.stats.ShortenLinkCountriesStats;
import de.interaapps.punyshort.model.database.workspaces.Workspace;
import de.interaapps.punyshort.model.database.workspaces.WorkspaceDomain;
import de.interaapps.punyshort.model.database.workspaces.WorkspaceUser;
import de.interaapps.punyshort.model.requests.links.ShortenLinkRequest;
import de.interaapps.punyshort.model.responses.ActionResponse;
import de.interaapps.punyshort.model.responses.PaginatedResponse;
Expand Down Expand Up @@ -53,7 +57,7 @@ public ShortenLinkResponse create(@Body ShortenLinkRequest request, @Attrib("use
checkLongLink(request.longLink);


Domain domain = getAndCheckDomainAccess(request.domain, user);
Domain domain = getAndCheckDomainAccess(request.domain, user, request.workspaceId);
shortenLink.domain = domain.id;

String path = "";
Expand All @@ -65,7 +69,7 @@ public ShortenLinkResponse create(@Body ShortenLinkRequest request, @Attrib("use
} while (ShortenLink.get(domain, path) != null);
}

if (path.equals("")) {
if (path.isEmpty()) {
if (!domain.isPublic) {
if (user == null) {
throw new AuthenticationException();
Expand All @@ -82,12 +86,37 @@ public ShortenLinkResponse create(@Body ShortenLinkRequest request, @Attrib("use
shortenLink.userId = user.id;
}


if (request.workspaceId != null) {
if (user == null) throw new AuthenticationException();

accessToken.checkPermission("workspaces:write");

Workspace workspace = Workspace.getById(request.workspaceId);

if (workspace == null) throw new NotFoundException();

WorkspaceUser workspaceUser = workspace.getUser(user.id);
if (workspaceUser == null) throw new PermissionsDeniedException();

shortenLink.workspaceId = workspace.id;
}

shortenLink.saveAndUpdateLinkCache(domain);

if (request.tags != null) {
for (String tag : request.tags) {
ShortenLinkTag sTag = new ShortenLinkTag();
sTag.linkId = shortenLink.id;
sTag.tag = tag;
sTag.save();
}
}

return new ShortenLinkResponse(shortenLink, domain);
}

public Domain getAndCheckDomainAccess(String domainId, User user) {
public Domain getAndCheckDomainAccess(String domainId, User user, String workspaceId) {
Domain domain = Domain.get(domainId);

if (domain == null) {
Expand All @@ -99,6 +128,19 @@ public Domain getAndCheckDomainAccess(String domainId, User user) {
}
}

if (workspaceId != null) {
Workspace workspace = Workspace.getById(workspaceId);
WorkspaceDomain workspaceDomain = workspace.getDomain(domainId);

if (workspace.getUser(user.id) == null)
throw new PermissionsDeniedException();

if (workspaceDomain == null && !domain.isPublic)
throw new PermissionsDeniedException();
else
return domain;
}

if (!domain.isPublic) {
if (user == null) {
throw new AuthenticationException();
Expand Down Expand Up @@ -141,14 +183,31 @@ public String getAndCheckPath(String path, User user, Domain domain) {
public PaginatedResponse<ShortenLinkResponse> getAll(Exchange exchange, @Attrib("user") User user, @Attrib("token") AccessToken accessToken) {
accessToken.checkPermission("shorten_links:read");

Query<ShortenLink> userLinks = Repo.get(ShortenLink.class).where("userId", user.id);
Query<ShortenLink> userLinks = Repo.get(ShortenLink.class).query();

userLinks.and(q -> {
q.where("userId", user.id);
q.orWhere(orQuery -> orQuery
.whereNotNull("workspaceId")
.whereExists(Workspace.class, w -> w
.where(Workspace.class, "id", "=", ShortenLink.class, "workspaceId")
.whereExists(WorkspaceUser.class, u ->
u.where(WorkspaceUser.class, "workspaceId", "=", Workspace.class, "id")
.where("userId", user.id)
.where("state", WorkspaceUser.State.ACCEPTED)
)
));
return q;
});

userLinks.whereExists(Domain.class, d -> d.where(ShortenLink.class, "domain", "=", Domain.class, "id"));

RequestHelper.defaultNavigation(exchange, userLinks);
RequestHelper.filterTags(userLinks, exchange.getQueryParameters());
RequestHelper.orderBy(userLinks, exchange, "created_at", true);

PaginationData pagination = RequestHelper.pagination(userLinks, exchange);

return new PaginatedResponse<>(userLinks.all().stream().map(r -> {
ShortenLinkResponse shortenLinkResponse = new ShortenLinkResponse(r);

Expand Down Expand Up @@ -181,7 +240,9 @@ public ActionResponse delete(@Path("id") String id, @Attrib("token") AccessToken
ShortenLink shortenLink = ShortenLink.get(id);
if (shortenLink == null)
throw new NotFoundException();

accessToken.checkPermission("shorten_links:delete");
shortenLink.checkUserAccess(user);

shortenLink.delete();
return new ActionResponse(true);
Expand All @@ -193,7 +254,9 @@ public ActionResponse edit(@Body ShortenLinkRequest request, @Path("id") String
ShortenLink shortenLink = ShortenLink.get(id);
if (shortenLink == null)
throw new NotFoundException();

accessToken.checkPermission("shorten_links:write");
shortenLink.checkUserAccess(user);

boolean checkPath = false;
if (request.path != null && !request.path.equals(shortenLink.path)) {
Expand All @@ -202,7 +265,7 @@ public ActionResponse edit(@Body ShortenLinkRequest request, @Path("id") String
}

if (request.domain != null && !request.domain.equals(shortenLink.domain)) {
shortenLink.domain = getAndCheckDomainAccess(request.domain, user).id;
shortenLink.domain = getAndCheckDomainAccess(request.domain, user, shortenLink.workspaceId).id;
checkPath = true;
}

Expand All @@ -214,6 +277,19 @@ public ActionResponse edit(@Body ShortenLinkRequest request, @Path("id") String
shortenLink.longLink = request.longLink;
}

if (request.tags != null) {
List<String> tags = shortenLink.getTags();
request.tags.stream().filter(t -> !tags.contains(t)).forEach(tag -> {
ShortenLinkTag pTag = new ShortenLinkTag();
pTag.linkId = shortenLink.id;
pTag.tag = tag;
pTag.save();
});
tags.stream().filter(t -> !request.tags.contains(t)).forEach(t -> {
Repo.get(ShortenLinkTag.class).where("linkId", shortenLink.id).where("tag", t).delete();
});
}

shortenLink.saveAndUpdateLinkCache();

return new ActionResponse(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package de.interaapps.punyshort.controller.workspaces;

import de.interaapps.punyshort.controller.HttpController;
import de.interaapps.punyshort.exceptions.NotFoundException;
import de.interaapps.punyshort.exceptions.PermissionsDeniedException;
import de.interaapps.punyshort.exceptions.WorkspaceSlugInvalidException;
import de.interaapps.punyshort.exceptions.WorkspaceTakenException;
import de.interaapps.punyshort.helper.RequestHelper;
import de.interaapps.punyshort.model.database.AccessToken;
import de.interaapps.punyshort.model.database.ShortenLink;
import de.interaapps.punyshort.model.database.User;
import de.interaapps.punyshort.model.database.domains.Domain;
import de.interaapps.punyshort.model.database.workspaces.Workspace;
import de.interaapps.punyshort.model.database.workspaces.WorkspaceDomain;
import de.interaapps.punyshort.model.database.workspaces.WorkspaceUser;
import de.interaapps.punyshort.model.requests.workspaces.AddDomainRequest;
import de.interaapps.punyshort.model.requests.workspaces.CreateWorkspaceInvitationRequest;
import de.interaapps.punyshort.model.requests.workspaces.CreateWorkspaceRequest;
import de.interaapps.punyshort.model.responses.ActionResponse;
import de.interaapps.punyshort.model.responses.PaginatedResponse;
import de.interaapps.punyshort.model.responses.PaginationData;
import de.interaapps.punyshort.model.responses.domains.DomainResponse;
import de.interaapps.punyshort.model.responses.workspaces.WorkspaceResponse;
import org.javawebstack.httpserver.Exchange;
import org.javawebstack.httpserver.router.annotation.PathPrefix;
import org.javawebstack.httpserver.router.annotation.With;
import org.javawebstack.httpserver.router.annotation.params.Attrib;
import org.javawebstack.httpserver.router.annotation.params.Body;
import org.javawebstack.httpserver.router.annotation.params.Path;
import org.javawebstack.httpserver.router.annotation.verbs.Delete;
import org.javawebstack.httpserver.router.annotation.verbs.Get;
import org.javawebstack.httpserver.router.annotation.verbs.Post;
import org.javawebstack.orm.Repo;
import org.javawebstack.orm.query.Query;

import java.util.regex.Pattern;
import java.util.stream.Collectors;

@PathPrefix("/v1/workspaces/{id}/domains")
public class WorkspaceDomainsController extends HttpController {
@Get
@With("auth")
public PaginatedResponse<DomainResponse> getAll(Exchange exchange, @Path("id") String id, @Attrib("user") User user, @Attrib("token") AccessToken accessToken) {
accessToken.checkPermission("workspaces.domains:read");

Workspace workspace = Workspace.getById(id);

if (workspace == null) throw new NotFoundException();

WorkspaceUser workspaceUser = workspace.getUser(user.id);

if (workspaceUser == null || workspaceUser.role != WorkspaceUser.Role.ADMIN)
throw new PermissionsDeniedException();

Query<Domain> workspaceDomainsQuery = Domain.getByWorkspace(workspace.id, user);

RequestHelper.defaultNavigation(exchange, workspaceDomainsQuery);
RequestHelper.orderBy(workspaceDomainsQuery, exchange, "created_at", false);

PaginationData pagination = RequestHelper.pagination(workspaceDomainsQuery, exchange);
return new PaginatedResponse<>(workspaceDomainsQuery.all().stream().map(d -> new DomainResponse(d, false)).collect(Collectors.toList()), pagination);
}

@Post
@With("auth")
public DomainResponse add(@Body AddDomainRequest request, @Path("id") String id, @Attrib("user") User user, @Attrib("token") AccessToken accessToken) {
accessToken.checkPermission("workspaces.domains:write");

Workspace workspace = Workspace.getById(id);
if (workspace == null) throw new NotFoundException();

WorkspaceUser workspaceUser = workspace.getUser(user.id);

if (workspaceUser == null || workspaceUser.role != WorkspaceUser.Role.ADMIN)
throw new PermissionsDeniedException();

Domain domain = Domain.get(request.domainId);
if (domain == null) throw new NotFoundException();

if (!domain.isPublic && domain.getUser(user.id) == null)
throw new PermissionsDeniedException();

workspace.addDomain(domain);

return new DomainResponse(domain, false);
}

@Delete("/{domainId}")
@With("auth")
public ActionResponse delete(@Path("id") String id, @Path("domainId") String domainId, @Attrib("token") AccessToken accessToken, @Attrib("user") User user) {
accessToken.checkPermission("workspaces.domains:delete");

Workspace workspace = Workspace.getById(id);
if (workspace == null) throw new NotFoundException();

WorkspaceUser workspaceUser = workspace.getUser(user.id);

if (workspaceUser == null || workspaceUser.role != WorkspaceUser.Role.ADMIN)
throw new PermissionsDeniedException();

Domain domain = Domain.get(domainId);
if (domain == null) throw new NotFoundException();

workspace.removeDomain(domain);

return new ActionResponse(true);
}
}
Loading

0 comments on commit b87cd6f

Please sign in to comment.