Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add and delete site image routes #191

Merged
merged 9 commits into from
Jul 3, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,13 @@ void editStewardship(
void nameSiteEntry(JWTData userData, int siteId, NameSiteEntryRequest nameSiteEntryRequest);

/**
* Used to update the image of a site. The `image` field of the most recent entry in the
* `site_entries` table associated with the specified site will be updated. Only users who are
* owners of the specified site, Admins, or Super Admins can perform this action. If the given URL
* is NULL, any pre-existing site image for the specified site will be deleted
* Used to upload a new image for a site entry with the given ID. The image must be given in the
* format of data:image/{extension};base64,{imageData}. For each image, a new row in the
* `SITE_IMAGES` table will be created. Only users who are Admins, or Super Admins can perform
* this action.
*/
void uploadSiteImage(JWTData userData, int siteId, UploadSiteImageRequest uploadSiteImageRequest);
void uploadSiteImage(
JWTData userData, int siteEntryId, UploadSiteImageRequest uploadSiteImageRequest);

/** Removes the site image with the given image ID */
void deleteSiteImage(JWTData userData, int imageId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class SiteEntry {

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "MM/dd/yyyy")
private final Timestamp createdAt;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "MM/dd/yyyy")
private final Timestamp updatedAt;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@

public class UploadSiteImageRequest extends ApiDto {
private String image;
private Boolean anonymous;

public UploadSiteImageRequest(String image) {
public UploadSiteImageRequest(String image, Boolean anonymous) {
this.image = image;
this.anonymous = anonymous;
}

public UploadSiteImageRequest() {}
Expand All @@ -18,18 +20,29 @@ public String getImage() {
return image;
}

public Boolean getAnonymous() {
return anonymous;
}

public void setImage(String image) {
this.image = image;
}

public void setAnon(Boolean anonymous) {
this.anonymous = anonymous;
}

@Override
public List<String> validateFields(String fieldPrefix) throws HandledException {
String fieldName = fieldPrefix + "upload_image_request.";
List<String> fields = new ArrayList<>();

if (image != null && urlInvalid(image)) {
if (image == null) {
fields.add(fieldName + "image");
}
if (anonymous == null) {
fields.add(fieldName + "anonymous");
}

return fields;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.codeforcommunity.exceptions;

import com.codeforcommunity.rest.FailureHandler;
import io.vertx.ext.web.RoutingContext;

public class ForbiddenException extends HandledException {
private final String message;

public ForbiddenException(String message) {
this.message = message;
}

@Override
public void callHandler(FailureHandler handler, RoutingContext ctx) {
handler.handleForbidden(ctx, this.message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public void handleAuth(RoutingContext ctx) {
end(ctx, "Unauthorized user", 401);
}

public void handleForbidden(RoutingContext ctx, String message) {
end(ctx, message, 403);
}

public void handleMissingParameter(RoutingContext ctx, MissingParameterException e) {
String message =
String.format("Missing required path parameter: %s", e.getMissingParameterName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,24 +299,24 @@ private void handleNameSiteEntry(RoutingContext ctx) {
}

private void registerUploadSiteImage(Router router) {
Route uploadImage = router.post("/:site_id/upload_image");
Route uploadImage = router.post("/site_image/:site_entry_id");
uploadImage.handler(this::handleUploadSiteImage);
}

private void handleUploadSiteImage(RoutingContext ctx) {
JWTData userData = ctx.get("jwt_data");
int siteId = RestFunctions.getRequestParameterAsInt(ctx.request(), "site_id");
int siteEntryId = RestFunctions.getRequestParameterAsInt(ctx.request(), "site_entry_id");

UploadSiteImageRequest uploadSiteImageRequest =
RestFunctions.getJsonBodyAsClass(ctx, UploadSiteImageRequest.class);

processor.uploadSiteImage(userData, siteId, uploadSiteImageRequest);
processor.uploadSiteImage(userData, siteEntryId, uploadSiteImageRequest);

end(ctx.response(), 200);
}

private void registerDeleteSiteImage(Router router) {
Route deleteImage = router.post("/delete_image/:image_id");
Route deleteImage = router.delete("/site_image/:image_id");
deleteImage.handler(this::handleDeleteSiteImage);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.codeforcommunity.enums;

public enum ImageApprovalStatus {
SUBMITTED("SUBMITTED"),
APPROVED("APPROVED");

private final String approvalStatus;

ImageApprovalStatus(String approvalStatus) {
this.approvalStatus = approvalStatus;
}

public String getApprovalStatus() {
return approvalStatus;
}

public static ImageApprovalStatus from(String approvalStatus) {
for (ImageApprovalStatus imageApprovalStatus : ImageApprovalStatus.values()) {
if (imageApprovalStatus.approvalStatus.equalsIgnoreCase(approvalStatus)) {
return imageApprovalStatus;
}
}

throw new IllegalArgumentException(
String.format(
"Given approvalStatus `%s` doesn't correspond to any `ImageApprovalStatus`",
approvalStatus));
}
}
2 changes: 1 addition & 1 deletion deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"aws_secret_key": "AWS_SECRET_ACCESS_KEY",
"aws_s3_bucket_url": "AWS_S3_BUCKET_URL",
"aws_s3_bucket_name": "AWS_S3_BUCKET_NAME",
"aws_s3_upload_dir": "AWS_S3_BUCKET_DIR",
# "aws_s3_upload_dir": "AWS_S3_BUCKET_DIR",

# Database Properties
"database_url": "DB_DOMAIN",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE site_images ADD COLUMN approval_status VARCHAR(10) DEFAULT 'SUBMITTED';
ALTER TABLE site_images ADD COLUMN anonymous BOOLEAN DEFAULT FALSE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for removing the unnecessary imports-- are the other changes just formatting?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah these were actually just changes that were applied automatically when I ran mvn clean install

Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
package com.codeforcommunity.processor;

import static org.jooq.generated.tables.Users.USERS;

import com.codeforcommunity.api.IProtectedEmailerProcessor;
import com.codeforcommunity.auth.JWTData;
import com.codeforcommunity.dto.emailer.AddTemplateRequest;
import com.codeforcommunity.dto.emailer.LoadTemplateResponse;
import com.codeforcommunity.dto.leaderboard.LeaderboardEntry;
import com.codeforcommunity.enums.PrivilegeLevel;
import com.codeforcommunity.enums.ReservationAction;
import com.codeforcommunity.exceptions.UserDoesNotExistException;
import com.codeforcommunity.requester.S3Requester;

import org.jooq.DSLContext;

import java.util.List;

import static org.jooq.impl.DSL.count;
import static org.jooq.generated.tables.Users.USERS;
import org.jooq.generated.tables.records.UsersRecord;

public class ProtectedEmailerProcessorImpl extends AbstractProcessor
implements IProtectedEmailerProcessor {

static public String TEMPLATE_DIR = "email_templates";
public static String TEMPLATE_DIR = "email_templates";

private final DSLContext db;

public ProtectedEmailerProcessorImpl(DSLContext db) { this.db = db; }
public ProtectedEmailerProcessorImpl(DSLContext db) {
this.db = db;
}

@Override
public void addTemplate(JWTData userData, AddTemplateRequest addTemplateRequest) {
Expand All @@ -43,18 +38,14 @@ public LoadTemplateResponse loadTemplate(JWTData userData, String templateName)
LoadTemplateResponse s3Response = S3Requester.loadHTML(templateName, TEMPLATE_DIR);
int userId = Integer.parseInt(s3Response.getAuthor());
// has ID of author, replace with fullname of author
UsersRecord user = db.selectFrom(USERS)
.where(USERS.ID.eq(userId)).fetchOne();
UsersRecord user = db.selectFrom(USERS).where(USERS.ID.eq(userId)).fetchOne();
if (user == null) {
throw new UserDoesNotExistException(userId);
}

String fullname = user.getFirstName() + " " + user.getLastName();
LoadTemplateResponse loadTemplateResponse = new LoadTemplateResponse(
s3Response.getTemplate(),
s3Response.getName(),
fullname
);
LoadTemplateResponse loadTemplateResponse =
new LoadTemplateResponse(s3Response.getTemplate(), s3Response.getName(), fullname);

return loadTemplateResponse;
}
Expand Down
Loading