diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/common/media/TakedownNoticeRequestContext_CustomFieldSerializer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/common/media/TakedownNoticeRequestContext_CustomFieldSerializer.java new file mode 100644 index 00000000000..dad5d723511 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/common/media/TakedownNoticeRequestContext_CustomFieldSerializer.java @@ -0,0 +1,60 @@ +package com.google.gwt.user.client.rpc.core.com.sap.sse.common.media; + +import java.util.Arrays; + +import com.google.gwt.user.client.rpc.CustomFieldSerializer; +import com.google.gwt.user.client.rpc.SerializationException; +import com.google.gwt.user.client.rpc.SerializationStreamReader; +import com.google.gwt.user.client.rpc.SerializationStreamWriter; +import com.sap.sse.common.Util; +import com.sap.sse.common.media.NatureOfClaim; +import com.sap.sse.common.media.TakedownNoticeRequestContext; + +public class TakedownNoticeRequestContext_CustomFieldSerializer extends CustomFieldSerializer { + + @Override + public void serializeInstance(SerializationStreamWriter streamWriter, TakedownNoticeRequestContext instance) + throws SerializationException { + serialize(streamWriter, instance); + } + + public static void serialize(SerializationStreamWriter streamWriter, TakedownNoticeRequestContext instance) + throws SerializationException { + streamWriter.writeString(instance.getContextDescriptionMessageKey()); + streamWriter.writeString(instance.getContextDescriptionMessageParameter()); + streamWriter.writeString(instance.getContentUrl()); + streamWriter.writeString(instance.getNatureOfClaim().name()); + streamWriter.writeString(instance.getReportingUserComment()); + streamWriter.writeObject(Util.toArray(instance.getSupportingURLs(), new String[0])); + streamWriter.writeString(instance.getUsername()); + } + + @Override + public boolean hasCustomInstantiateInstance() { + return true; + } + + @Override + public TakedownNoticeRequestContext instantiateInstance(SerializationStreamReader streamReader) + throws SerializationException { + return instantiate(streamReader); + } + + public static TakedownNoticeRequestContext instantiate(SerializationStreamReader streamReader) + throws SerializationException { + return new TakedownNoticeRequestContext(streamReader.readString(), streamReader.readString(), + streamReader.readString(), NatureOfClaim.valueOf(streamReader.readString()), streamReader.readString(), + Arrays.asList((String[]) streamReader.readObject()), streamReader.readString()); + } + + @Override + public void deserializeInstance(SerializationStreamReader streamReader, TakedownNoticeRequestContext instance) + throws SerializationException { + deserialize(streamReader, instance); + } + + public static void deserialize(SerializationStreamReader streamReader, TakedownNoticeRequestContext instance) { + // Done by instantiateInstance + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/qrcode/QRCodePresenter.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/qrcode/QRCodePresenter.java index 266ac7cd7e0..d8002a82b64 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/qrcode/QRCodePresenter.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/qrcode/QRCodePresenter.java @@ -12,6 +12,7 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.gwt.home.desktop.places.qrcode.QRCodePlace.InvitationMode; import com.sap.sailing.gwt.ui.shared.MarkDTO; import com.sap.sailing.gwt.ui.shared.QRCodeEvent; +import com.sap.sailing.landscape.common.SharedLandscapeConstants; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Triple; @@ -57,7 +58,7 @@ public class QRCodePresenter { private boolean isSecureServer(Triple correctServerHost) { String host = correctServerHost.getB(); - if (host.endsWith("sapsailing.com")) { + if (host.endsWith(SharedLandscapeConstants.DEFAULT_DOMAIN_NAME)) { return true; } if (host.equals("127.0.0.1")) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java index f350b1fd8a7..d9d481c5170 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java @@ -407,7 +407,7 @@ public class RaceBoardPanel } } taggingComponent = new TaggingComponent(parent, componentContext, stringMessages, sailingService, withSecurity.getUserService(), timer, - raceTimesInfoProvider, sharedTagTimePoint, sharedTagTitle, leaderboardDTO, sailingServiceWrite); + raceTimesInfoProvider, sharedTagTimePoint, sharedTagTitle, leaderboardDTO, sailingServiceWrite, selectedRaceIdentifier); addChildComponent(taggingComponent); taggingComponent.setVisible(showTaggingComponent); // Determine if the screen is large enough to initially display the leaderboard panel on the left side of the diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagButtonDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagButtonDialog.java index a692c8f4ebb..8d48e25cb6e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagButtonDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagButtonDialog.java @@ -19,6 +19,7 @@ import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.SimplePanel; +import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.dto.TagDTO; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; @@ -109,13 +110,13 @@ public class TagButtonDialog extends DialogBox { * {@link TaggingComponent} which creates this {@link TagButtonDialog}. * @param footerPanel * footer panel of {@link TaggingComponent} - * @param sailingServiceWrite - * Sailing Service of {@link TaggingComponent} * @param stringMessages * string messages of {@link TaggingComponent} + * @param sailingServiceWrite + * Sailing Service of {@link TaggingComponent} */ public TagButtonDialog(TaggingComponent taggingComponent, TagFooterPanel footerPanel, SailingServiceAsync sailingService, - StringMessages stringMessages, UserService userService) { + StringMessages stringMessages, UserService userService, RaceIdentifier raceIdentifier) { this.taggingComponent = taggingComponent; this.stringMessages = stringMessages; this.footerPanel = footerPanel; @@ -141,7 +142,7 @@ public class TagButtonDialog extends DialogBox { } } }); - tagPreviewPanel = new TagPreviewPanel(taggingComponent, inputPanel, stringMessages, userService); + tagPreviewPanel = new TagPreviewPanel(taggingComponent, inputPanel, stringMessages, userService, raceIdentifier); tagButtonTable = createTable(footerPanel, inputPanel, tagPreviewPanel); tagButtonTable.addRedrawHandler(() -> { // center dialog when content of tagButtonTable changes (table needs to be redrawn) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagCell.java index 20a7ec33c7e..27f8e741493 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagCell.java @@ -22,6 +22,7 @@ import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.google.gwt.safehtml.shared.SafeUri; import com.google.gwt.safehtml.shared.UriUtils; import com.google.gwt.user.client.Window; +import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.dto.TagDTO; import com.sap.sailing.gwt.settings.client.raceboard.RaceBoardPerspectiveOwnSettings; import com.sap.sailing.gwt.ui.client.GwtUrlHelper; @@ -75,12 +76,12 @@ public class TagCell extends AbstractCell { * image URL * @param comment * comment - * * @return {@link SafeHtml HTML template} */ - @Template("
⋯
{3}
") + @Template("
⋯
{3}
") SafeHtml contentWithCommentWithImage(String classTagImage, String classTagComment, SafeUri imageURL, - SafeHtml comment, String classMenuIcon, String classMediaWrapper); + SafeHtml comment, String classMenuIcon, String classMediaWrapper, String imageUrlAsSanitizedString, + String takedownNoticeContext, String username); /** * Renders content with mixed configuration (comment, no image). @@ -96,11 +97,11 @@ public class TagCell extends AbstractCell { * Renders content with mixed configuration (image, no comment). * @param imageURL * image URL - * * @return {@link SafeHtml HTML template} */ - @Template("
⋯
") - SafeHtml contentWithoutCommentWithImage(String classTagImage, SafeUri imageURL, String classMenuIcon, String classMediaWrapper); + @Template("
⋯
") + SafeHtml contentWithoutCommentWithImage(String classTagImage, SafeUri imageURL, String classMenuIcon, + String classMediaWrapper, String imageUrlAsSanitizedString, String takedownNoticeContext, String username); /** * Renders heading buttons to share, edit or delete a tag. @@ -141,6 +142,7 @@ public class TagCell extends AbstractCell { private final StringMessages stringMessages; private final UserService userService; private final boolean isPreviewCell; + private final RaceIdentifier raceIdentifier; /** * Displays the content of a {@link TagDTO tag} by using {@link SafeHtmlTemplates}. @@ -150,13 +152,15 @@ public class TagCell extends AbstractCell { * @param isPreviewCell * should be true if {@link TagCell cell} is used as {@link TagPreviewPanel preview cell}, * otherwise false + * @param raceIdentifier used to construct take-down notice text */ - TagCell(TaggingComponent taggingComponent, StringMessages stringMessages, UserService userService, boolean isPreviewCell) { + TagCell(TaggingComponent taggingComponent, StringMessages stringMessages, UserService userService, boolean isPreviewCell, RaceIdentifier raceIdentifier) { super("click"); this.taggingComponent = taggingComponent; this.stringMessages = stringMessages; this.userService = userService; this.isPreviewCell = isPreviewCell; + this.raceIdentifier = raceIdentifier; sharedResources.ensureInjected(); } @@ -186,12 +190,17 @@ public class TagCell extends AbstractCell { if (!tag.getComment().isEmpty() && trustedImageURL == null) { content = tagCellTemplate.contentWithCommentWithoutImage(style.tagCellComment(), safeComment); } else if (tag.getComment().isEmpty() && trustedImageURL != null) { - TakedownNoticeRequestDialog.ensureJSFunctionInstalled(); - content = tagCellTemplate.contentWithoutCommentWithImage(style.tagCellImage(), trustedImageURL, sharedResources.media_menu_icon(), sharedResources.media_wrapper()); + TakedownNoticeRequestDialog.ensureJSFunctionInstalled(userService); + content = tagCellTemplate.contentWithoutCommentWithImage(style.tagCellImage(), trustedImageURL, + sharedResources.media_menu_icon(), sharedResources.media_wrapper(), + new SafeHtmlBuilder().appendEscaped(trustedImageURL.asString()).toSafeHtml().asString(), + tag.getTag()+", "+tag.getRaceTimepoint()+", "+raceIdentifier, userService.getCurrentUser() == null ? "" : userService.getCurrentUser().getName()); } else if (!tag.getComment().isEmpty() && trustedImageURL != null) { - TakedownNoticeRequestDialog.ensureJSFunctionInstalled(); + TakedownNoticeRequestDialog.ensureJSFunctionInstalled(userService); content = tagCellTemplate.contentWithCommentWithImage(style.tagCellImage(), style.tagCellComment(), - trustedImageURL, safeComment, sharedResources.media_menu_icon(), sharedResources.media_wrapper()); + trustedImageURL, safeComment, sharedResources.media_menu_icon(), sharedResources.media_wrapper(), + new SafeHtmlBuilder().appendEscaped(trustedImageURL.asString()).toSafeHtml().asString(), + tag.getTag()+", "+tag.getRaceTimepoint()+", "+raceIdentifier, userService.getCurrentUser() == null ? "" : userService.getCurrentUser().getName()); } SafeHtml icon = SafeHtmlUtils.EMPTY_SAFE_HTML; if (!tag.isVisibleForPublic()) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagFooterPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagFooterPanel.java index 7b56803e7e9..d9eefd5bca5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagFooterPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagFooterPanel.java @@ -1,6 +1,7 @@ package com.sap.sailing.gwt.ui.raceboard.tagging; import com.google.gwt.user.client.ui.FlowPanel; +import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.raceboard.tagging.TaggingComponent.State; @@ -24,9 +25,9 @@ public class TagFooterPanel extends FlowPanel { * @param taggingComponent * required to instantiate {@link TagModificationPanel} and {@link TagButtonPanel} */ - protected TagFooterPanel(TaggingComponent taggingComponent, SailingServiceAsync sailingService, StringMessages stringMessages, UserService userService) { + protected TagFooterPanel(TaggingComponent taggingComponent, SailingServiceAsync sailingService, StringMessages stringMessages, UserService userService, RaceIdentifier raceIdentifier) { this.taggingComponent = taggingComponent; - tagModificationPanel = new TagModificationPanel(taggingComponent, this, sailingService, stringMessages, userService); + tagModificationPanel = new TagModificationPanel(taggingComponent, this, sailingService, stringMessages, userService, raceIdentifier); tagButtonPanel = new TagButtonPanel(taggingComponent, this, stringMessages, userService); // Tag-buttons are only shown if amount of tag-buttons is greater then 0! setTagButtonsVisibility(true); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagModificationPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagModificationPanel.java index 8f0526c577a..7eb91eb21c9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagModificationPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagModificationPanel.java @@ -4,6 +4,7 @@ import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Panel; +import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.dto.TagDTO; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; @@ -38,7 +39,7 @@ public class TagModificationPanel extends FlowPanel { * required for creation of {@link TagButton tag-buttons} */ protected TagModificationPanel(TaggingComponent taggingComponent, TagFooterPanel tagFooterPanel, - SailingServiceAsync sailingService, StringMessages stringMessages, UserService userService) { + SailingServiceAsync sailingService, StringMessages stringMessages, UserService userService, RaceIdentifier raceIdentifier) { this.taggingComponent = taggingComponent; this.stringMessages = stringMessages; setStyleName(style.tagModificationPanel()); @@ -77,7 +78,7 @@ public class TagModificationPanel extends FlowPanel { editCustomTagButtons.addStyleName("gwt-Button"); editCustomTagButtons.addClickHandler(event -> { if (taggingComponent.isLoggedInAndRaceLogAvailable()) { - new TagButtonDialog(taggingComponent, tagFooterPanel, sailingService, stringMessages, userService); + new TagButtonDialog(taggingComponent, tagFooterPanel, sailingService, stringMessages, userService, raceIdentifier); } }); inputPanel.getOkButton().setText(stringMessages.tagAddTag()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagPreviewPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagPreviewPanel.java index 02126de4fbc..b69b156e3b3 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagPreviewPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagPreviewPanel.java @@ -6,6 +6,7 @@ import java.util.List; import com.google.gwt.user.cellview.client.CellList; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Label; +import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.dto.TagDTO; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.raceboard.tagging.TaggingPanelResources.TagPanelStyle; @@ -36,12 +37,12 @@ public class TagPreviewPanel extends FlowPanel { * references input fields used to get current user input */ protected TagPreviewPanel(TaggingComponent taggingComponent, TagInputPanel inputPanel, StringMessages stringMessages, - UserService userService) { + UserService userService, RaceIdentifier raceIdentifier) { this.taggingComponent = taggingComponent; this.userService = userService; setStyleName(style.tagPreviewPanel()); - tagPreviewCellList = new CellList(new TagCell(taggingComponent, stringMessages, userService, true), + tagPreviewCellList = new CellList(new TagCell(taggingComponent, stringMessages, userService, true, raceIdentifier), resources); listContainingPreviewTag = new ArrayList(); add(new Label(stringMessages.tagPreview())); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TaggingComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TaggingComponent.java index 72d0a266bec..6bca51524cb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TaggingComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TaggingComponent.java @@ -27,6 +27,7 @@ import com.google.gwt.view.client.CellPreviewEvent; import com.google.gwt.view.client.CellPreviewEvent.Handler; import com.google.gwt.view.client.NoSelectionModel; import com.google.gwt.view.client.SingleSelectionModel; +import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; @@ -170,7 +171,7 @@ public class TaggingComponent extends ComponentWithoutSettings public TaggingComponent(Component parent, ComponentContext context, StringMessages stringMessages, SailingServiceAsync sailingService, UserService userService, Timer timer, RaceTimesInfoProvider raceTimesInfoProvider, TimePoint timePointToHighlight, String tagToHighlight, - StrippedLeaderboardDTO leaderboardDTO, SailingServiceWriteAsync sailingServiceWrite) { + StrippedLeaderboardDTO leaderboardDTO, SailingServiceWriteAsync sailingServiceWrite, RaceIdentifier raceIdentifier) { super(parent, context); this.stringMessages = stringMessages; this.sailingService = sailingService; @@ -185,7 +186,7 @@ public class TaggingComponent extends ComponentWithoutSettings style.ensureInjected(); TaggingPanelResources.INSTANCE.cellListStyle().ensureInjected(); TaggingPanelResources.INSTANCE.cellTableStyle().ensureInjected(); - tagCellList = new CellList(new TagCell(this, stringMessages, userService, false), + tagCellList = new CellList(new TagCell(this, stringMessages, userService, false, raceIdentifier), TaggingPanelResources.INSTANCE); tagSelectionModel = new SingleSelectionModel(); tagListProvider = new TagListProvider(); @@ -200,7 +201,7 @@ public class TaggingComponent extends ComponentWithoutSettings } }; filterbarAndContentPanel = new HeaderPanel(); - tagFooterPanel = new TagFooterPanel(this, sailingService, stringMessages, userService); + tagFooterPanel = new TagFooterPanel(this, sailingService, stringMessages, userService, raceIdentifier); footerPanel = new ScrollPanel(tagFooterPanel); filterbarPanel = new TagFilterPanel(this, stringMessages, userService); contentPanel = new FlowPanel(); diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/media/NatureOfClaim.java b/java/com.sap.sse.common/src/com/sap/sse/common/media/NatureOfClaim.java new file mode 100644 index 00000000000..ec9e8a0ce66 --- /dev/null +++ b/java/com.sap.sse.common/src/com/sap/sse/common/media/NatureOfClaim.java @@ -0,0 +1,8 @@ +package com.sap.sse.common.media; + +public enum NatureOfClaim { + NONE, + COPYRIGHT_INFRINGEMENT, + DEFAMATORY_CONTENT, + OTHER +} \ No newline at end of file diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/media/TakedownNoticeRequestContext.java b/java/com.sap.sse.common/src/com/sap/sse/common/media/TakedownNoticeRequestContext.java index befc7e5abf8..39e7d6a534b 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/media/TakedownNoticeRequestContext.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/media/TakedownNoticeRequestContext.java @@ -1,5 +1,7 @@ package com.sap.sse.common.media; +import java.io.Serializable; + /** * Whenever media content is made available that may have been uploaded by an end user, there is a possibility that * other users would like to request this content to be taken down, hidden or otherwise made unavailable. Reasons for @@ -16,14 +18,9 @@ package com.sap.sse.common.media; * @author Axel Uhl (d043530) * */ -public class TakedownNoticeRequestContext { - public static enum NatureOfClaim { - NONE, - COPYRIGHT_INFRINGEMENT, - DEFAMATORY_CONTENT, - OTHER - } - +public class TakedownNoticeRequestContext implements Serializable { + private static final long serialVersionUID = -7013553116801501898L; + /** * A message key for a message that takes as parameters the following strings: *
    diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages.java index f9783b39864..088a8fdfd9a 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages.java @@ -119,4 +119,5 @@ public interface StringMessages extends Messages { String natureOfTakedownClaim(); String comment(); String supportingURLs(); + String mustBeLoggedInAndWithValidatedEmail(); } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages.properties b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages.properties index 99d18e4d892..05025f5e8dd 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages.properties +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages.properties @@ -104,4 +104,5 @@ takedownNoticeDialogTitle=Take-Down Notice Request takedownNoticeDialogMessage=Please fill in this form to to elaborate on your request to remove the media reachable under URL "{0}" from this site and to prove your case. By submitting this request, you assert that you are the copyright holder or an authorized agent and that the content in question infringes your rights. You understand that submitting a false claim can result in legal consequences. natureOfTakedownClaim=Nature of claim comment=Comment -supportingURLs=Supporting URLs \ No newline at end of file +supportingURLs=Supporting URLs +mustBeLoggedInAndWithValidatedEmail=You must be logged in and have your e-mail address validated in order to send a media take-down notice. \ No newline at end of file diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages_de.properties b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages_de.properties index a0af14a501c..f6a45e36c21 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages_de.properties +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/StringMessages_de.properties @@ -102,4 +102,5 @@ takedownNoticeDialogTitle=Antrag auf Entfernung von Inhalten takedownNoticeDialogMessage=Bitte dieses Formular ausfüllen, um den Antrag auf Entfernung der unter der URL „{0}“ erreichbaren Medien von dieser Website zu begründen und den Anspruch nachzuweisen. Mit dem Absenden dieses Antrags wird bestätigt, der Urheberrechtsinhaber oder ein bevollmächtigter Vertreter zu sein und dass die betreffenden Inhalte die Rechte verletzen. Die Abgabe einer falschen Erklärung kann rechtliche Konsequenzen nach sich ziehen. natureOfTakedownClaim=Art des Anspruchs comment=Kommentar -supportingURLs=Verweise zum Belegen des Anspruchs \ No newline at end of file +supportingURLs=Verweise zum Belegen des Anspruchs +mustBeLoggedInAndWithValidatedEmail=Anmeldung mit einem Konto mit validierter e-Mail-Adresse erforderlich, um die Entfernung von Medien zu beantragen. \ No newline at end of file diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/media/TakedownNoticeRequestDialog.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/media/TakedownNoticeRequestDialog.java index 7ae149c61ab..349cbb07b95 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/media/TakedownNoticeRequestDialog.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/media/TakedownNoticeRequestDialog.java @@ -6,8 +6,9 @@ import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextArea; import com.google.gwt.user.client.ui.Widget; +import com.sap.sse.common.Util; +import com.sap.sse.common.media.NatureOfClaim; import com.sap.sse.common.media.TakedownNoticeRequestContext; -import com.sap.sse.common.media.TakedownNoticeRequestContext.NatureOfClaim; import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.Notification; import com.sap.sse.gwt.client.Notification.NotificationType; @@ -28,6 +29,7 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog; * */ public class TakedownNoticeRequestDialog extends DataEntryDialog { + private static TakedownNoticeService serviceToUseForTakedownNotice; private final String contextDescriptionMessageKey; private final String contextDescriptionMessageParameter; private final String contentUrl; @@ -44,9 +46,26 @@ public class TakedownNoticeRequestDialog extends DataEntryDialog + * + * To use this in an {@code onclick} callback function of an element defined by a {@code @Template}, you have to + * "park" the parameters in attributes of the element and access them from within the {@code onclick} handler + * using the {@code getAttribute} method, e.g., like this: + * + *
    +     *   <div class='{0}'
    +     *          takedown-contextDescriptionMessageKey='{1}'
    +     *          takedown-contextDescriptionMessageParameter='{2}'
    +     *          takedown-contentUrl='{3}' takedown-username='{4}'
    +     *          onclick=\"showTakedownNoticeRequestDialog(this.getAttribute('takedown-contextDescriptionMessageKey'), this.getAttribute('takedown-contextDescriptionMessageParameter'), this.getAttribute('takedown-contentUrl'), this.getAttribute('takedown-username'))\">⋯</div>
    +     * 
    */ - public static native void ensureJSFunctionInstalled() /*-{ + public static void ensureJSFunctionInstalled(TakedownNoticeService serviceToUseForTakedownNotice) { + TakedownNoticeRequestDialog.serviceToUseForTakedownNotice = serviceToUseForTakedownNotice; + ensureJSFunctionInstalled(); + } + + private static native void ensureJSFunctionInstalled() /*-{ if ($wnd.showTakedownNoticeRequestDialog == null) { $wnd.showTakedownNoticeRequestDialog = $entry(function(contextDescriptionMessageKey, contextDescriptionMessageParameter, contentUrl, username) { @com.sap.sse.gwt.client.media.TakedownNoticeRequestDialog::showTakedownNoticeRequestDialog(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)(contextDescriptionMessageKey, contextDescriptionMessageParameter, contentUrl, username); @@ -56,8 +75,20 @@ public class TakedownNoticeRequestDialog extends DataEntryDialog() { + @Override + public void ok(TakedownNoticeRequestContext editedObject) { + serviceToUseForTakedownNotice.fileTakedownNotice(editedObject); + } + + @Override + public void cancel() { + } + }).show(); + } } public TakedownNoticeRequestDialog(String contextDescriptionMessageKey, String contextDescriptionMessageParameter, diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/media/TakedownNoticeService.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/media/TakedownNoticeService.java new file mode 100644 index 00000000000..e0fd08f82bb --- /dev/null +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/media/TakedownNoticeService.java @@ -0,0 +1,10 @@ +package com.sap.sse.gwt.client.media; + +import com.sap.sse.common.media.TakedownNoticeRequestContext; + +public interface TakedownNoticeService { + + void fileTakedownNotice(TakedownNoticeRequestContext takedownNoticeRequestContext); + + boolean isEmailAddressOfCurrentUserValidated(); +} diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementWriteService.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementWriteService.java index a7880956ef6..95d587d526f 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementWriteService.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementWriteService.java @@ -6,6 +6,7 @@ import java.util.Set; import java.util.UUID; import com.sap.sse.common.mail.MailException; +import com.sap.sse.common.media.TakedownNoticeRequestContext; import com.sap.sse.security.shared.QualifiedObjectIdentifier; import com.sap.sse.security.shared.UnauthorizedException; import com.sap.sse.security.shared.UserGroupManagementException; @@ -112,6 +113,8 @@ public interface UserManagementWriteService extends UserManagementService { void setCORSFilterConfigurationAllowedOrigins(ArrayList allowedOrigins); + void fileTakedownNotice(TakedownNoticeRequestContext takedownNoticeRequestContext) throws MailException; + // ------------------------------------------------ OAuth Interface // -------------------------------------------------------------- public String getAuthorizationUrl(CredentialDTO credential) diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementWriteServiceAsync.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementWriteServiceAsync.java index 3693844b484..5986dcddb7e 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementWriteServiceAsync.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementWriteServiceAsync.java @@ -6,6 +6,7 @@ import java.util.Set; import java.util.UUID; import com.google.gwt.user.client.rpc.AsyncCallback; +import com.sap.sse.common.media.TakedownNoticeRequestContext; import com.sap.sse.security.shared.QualifiedObjectIdentifier; import com.sap.sse.security.shared.WildcardPermission; import com.sap.sse.security.shared.dto.AccessControlListDTO; @@ -118,4 +119,6 @@ public interface UserManagementWriteServiceAsync extends UserManagementServiceAs * but must not be {@code null}. */ void setCORSFilterConfigurationAllowedOrigins(ArrayList allowedOrigins, AsyncCallback callback); + + void fileTakedownNotice(TakedownNoticeRequestContext takedownNoticeRequestContext, AsyncCallback callback); } diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserService.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserService.java index 437ebb02f42..7418097451b 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserService.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserService.java @@ -16,6 +16,7 @@ import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Triple; import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.common.media.TakedownNoticeRequestContext; import com.sap.sse.common.settings.generic.AbstractGenericSerializableSettings; import com.sap.sse.common.settings.generic.GenericSerializableSettings; import com.sap.sse.gwt.client.Notification; @@ -23,6 +24,7 @@ import com.sap.sse.gwt.client.Notification.NotificationType; import com.sap.sse.gwt.client.ServerInfoDTO; import com.sap.sse.gwt.client.Storage; import com.sap.sse.gwt.client.async.MarkedAsyncCallback; +import com.sap.sse.gwt.client.media.TakedownNoticeService; import com.sap.sse.gwt.client.xdstorage.CrossDomainStorage; import com.sap.sse.gwt.client.xdstorage.CrossDomainStorageEvent; import com.sap.sse.gwt.client.xdstorage.DelegatingCrossDomainStorageFuture; @@ -63,7 +65,7 @@ import com.sap.sse.security.ui.shared.SuccessInfo; * @author Axel Uhl (D043530) * */ -public class UserService { +public class UserService implements TakedownNoticeService { private static final Logger logger = Logger.getLogger(UserService.class.getName()); private static final StringMessages stringMessages = GWT.create(StringMessages.class); @@ -584,4 +586,24 @@ public class UserService { public ServerInfoDTO getServerInfo() { return serverInfo; } + + @Override + public void fileTakedownNotice(TakedownNoticeRequestContext takedownNoticeRequestContext) { + userManagementWriteService.fileTakedownNotice(takedownNoticeRequestContext, new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + GWT.log(caught.getMessage()); + } + + @Override + public void onSuccess(Void result) { + GWT.log("successfully filed takedown notice"); + } + }); + } + + @Override + public boolean isEmailAddressOfCurrentUserValidated() { + return getCurrentUser().isEmailValidated(); + } } diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementWriteServiceImpl.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementWriteServiceImpl.java index 6612b0b9bc8..0a88d2e5347 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementWriteServiceImpl.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementWriteServiceImpl.java @@ -19,6 +19,7 @@ import com.sap.sse.ServerInfo; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Triple; import com.sap.sse.common.mail.MailException; +import com.sap.sse.common.media.TakedownNoticeRequestContext; import com.sap.sse.security.Action; import com.sap.sse.security.SecurityService; import com.sap.sse.security.shared.HasPermissions.DefaultActions; @@ -674,8 +675,7 @@ public class UserManagementWriteServiceImpl extends UserManagementServiceImpl im AccessControlListDTO acl) throws UnauthorizedException { if (SecurityUtils.getSubject() .isPermitted(idOfAccessControlledObject.getStringPermission(DefaultActions.CHANGE_ACL))) { - - Map> aclActionsByGroup = new HashMap<>(); + final Map> aclActionsByGroup = new HashMap<>(); for (Entry> entry : acl.getActionsByUserGroup().entrySet()) { final StrippedUserGroupDTO groupDTO = entry.getKey(); final UserGroup userGroup; @@ -686,7 +686,6 @@ public class UserManagementWriteServiceImpl extends UserManagementServiceImpl im } aclActionsByGroup.put(userGroup, entry.getValue()); } - return securityDTOFactory.createAccessControlListDTO(getSecurityService() .overrideAccessControlList(idOfAccessControlledObject, aclActionsByGroup)); } else { @@ -705,4 +704,9 @@ public class UserManagementWriteServiceImpl extends UserManagementServiceImpl im getSecurityService().checkCurrentUserServerPermission(ServerActions.CONFIGURE_CORS_FILTER); getSecurityService().setCORSFilterConfigurationAllowedOrigins(ServerInfo.getName(), allowedOrigins.toArray(new String[0])); } + + @Override + public void fileTakedownNotice(TakedownNoticeRequestContext takedownNoticeRequestContext) throws MailException { + getSecurityService().fileTakedownNotice(takedownNoticeRequestContext); + } } diff --git a/java/com.sap.sse.security/resources/stringmessages/StringMessages.properties b/java/com.sap.sse.security/resources/stringmessages/StringMessages.properties index 13c47fb4672..d1e27c69840 100644 --- a/java/com.sap.sse.security/resources/stringmessages/StringMessages.properties +++ b/java/com.sap.sse.security/resources/stringmessages/StringMessages.properties @@ -1,2 +1,4 @@ emailValidationSubject=Mail Validation emailValidationMessage=Please click on the link below to validate your e-mail address for user {0}. +takedownRequestConfirmation=Dear {0},\nan e-mail with your media take-down request has been sent to {1}. The message we sent on your behalf was:\n\n{2} +takedownRequestForImageInTagColumn=Tag column in race board, {0} \ No newline at end of file diff --git a/java/com.sap.sse.security/resources/stringmessages/StringMessages_de.properties b/java/com.sap.sse.security/resources/stringmessages/StringMessages_de.properties index bf28d2dbeab..7abd0f35b0e 100644 --- a/java/com.sap.sse.security/resources/stringmessages/StringMessages_de.properties +++ b/java/com.sap.sse.security/resources/stringmessages/StringMessages_de.properties @@ -1,2 +1,4 @@ emailValidationSubject=Mail-Validierung -emailValidationMessage=Bitte den folgenden Link benutzen, um die e-Mail Adresse für den Benutzer {0} zu validieren. \ No newline at end of file +emailValidationMessage=Bitte den folgenden Link benutzen, um die e-Mail Adresse für den Benutzer {0} zu validieren. +takedownRequestConfirmation=Lieber {0},\neine e-Mail mit dem Antrag zur Löschung von Medieninhalten wurde an die Adresse {1} gesendet. Die Nachricht lautet:\n\n{2} +takedownRequestForImageInTagColumn=Kommentarspalte im "Race Board", {0} \ No newline at end of file diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java b/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java index aefdf5afa04..24a9d95eefd 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java @@ -25,6 +25,7 @@ import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.http.HttpHeaderUtil; import com.sap.sse.common.mail.MailException; +import com.sap.sse.common.media.TakedownNoticeRequestContext; import com.sap.sse.replication.ReplicableWithObjectInputStream; import com.sap.sse.security.impl.ReplicableSecurityService; import com.sap.sse.security.impl.SecurityServiceImpl; @@ -910,4 +911,6 @@ public interface SecurityService extends ReplicableWithObjectInputStreamnew NamedReentrantReadWriteLock("Subscriptions lock for user "+user.getName(), /* fair */ false))); } + + @Override + public void fileTakedownNotice(TakedownNoticeRequestContext takedownNoticeRequestContext) throws MailException { + final String SUPPORT_MAIL_ADDRESS = "support@sapsailing.com"; + final User user = getUserByName(takedownNoticeRequestContext.getUsername()); + final String email = user.getEmail(); + final StringBuilder sb = new StringBuilder() + .append("User ") + .append(takedownNoticeRequestContext.getUsername()) + .append(" with e-mail ") + .append(email) + .append(" requests that the media with URL ") + .append(takedownNoticeRequestContext.getContentUrl()) + .append(" used in context ") + .append(messages.get(Locale.ENGLISH, takedownNoticeRequestContext.getContextDescriptionMessageKey(), takedownNoticeRequestContext.getContextDescriptionMessageParameter())) + .append(" be removed from the site. The user provides the following comment:\n\n") + .append(" \"") + .append(takedownNoticeRequestContext.getReportingUserComment()) + .append("\"\n\n") + .append("The claim is of nature ") + .append(takedownNoticeRequestContext.getNatureOfClaim()) + .append("."); + if (!Util.isEmpty(takedownNoticeRequestContext.getSupportingURLs())) { + sb.append("\n\nThe user provided the following additional URLs to substantiate or prove the claim:\n"); + for (final String url : takedownNoticeRequestContext.getSupportingURLs()) { + sb.append(" - "); + sb.append(url); + sb.append("\n"); + } + } + final String message = sb.toString(); + getMailService().sendMail(SUPPORT_MAIL_ADDRESS, "Media Take-Down Request", message); + getMailService().sendMail(email, "Media Take-Down Request Confirmation", messages.get(user.getLocaleOrDefault(), "takedownRequestConfirmation", + Util.hasLength(user.getFullName().trim()) ? user.getFullName() : user.getName(), SUPPORT_MAIL_ADDRESS, message)); + } } diff --git a/java/com.sap.sse.test/src/com/sap/sse/test/TestTakedownNoticeFactory.java b/java/com.sap.sse.test/src/com/sap/sse/test/TestTakedownNoticeFactory.java index acd83ac8e24..021c4d027c7 100644 --- a/java/com.sap.sse.test/src/com/sap/sse/test/TestTakedownNoticeFactory.java +++ b/java/com.sap.sse.test/src/com/sap/sse/test/TestTakedownNoticeFactory.java @@ -8,8 +8,8 @@ import java.util.Locale; import org.junit.Test; +import com.sap.sse.common.media.NatureOfClaim; import com.sap.sse.common.media.TakedownNoticeRequestContext; -import com.sap.sse.common.media.TakedownNoticeRequestContext.NatureOfClaim; import com.sap.sse.i18n.ResourceBundleStringMessages; import com.sap.sse.i18n.impl.ResourceBundleStringMessagesImpl; import com.sap.sse.util.TakedownNoticeFactory;