Skip to content

Commit

Permalink
Added public notification settings on own profile page
Browse files Browse the repository at this point in the history
Added missing view elements on calendar subpages
Moved EventNotificationJob into job package
  • Loading branch information
Alf-Melmac committed Aug 14, 2021
1 parent ffb5c10 commit c327d35
Show file tree
Hide file tree
Showing 18 changed files with 529 additions and 34 deletions.
16 changes: 16 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package de.webalf.slotbot.assembler;

import de.webalf.slotbot.model.NotificationSetting;
import de.webalf.slotbot.model.dtos.referenceless.NotificationSettingsReferencelessDto;
import lombok.experimental.UtilityClass;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
* @author Alf
* @since 12.08.2021
*/
@UtilityClass
public final class NotificationSettingAssembler {
private NotificationSettingsReferencelessDto toReferencelessDto(NotificationSetting notificationSetting) {
return NotificationSettingsReferencelessDto.builder()
.hoursBeforeEvent(notificationSetting.getHoursBeforeEvent())
.minutesBeforeEvent(notificationSetting.getMinutesBeforeEvent())
.build();
}

public static List<NotificationSettingsReferencelessDto> toReferencelessDtoList(Iterable<? extends NotificationSetting> notificationSettings) {
return StreamSupport.stream(notificationSettings.spliterator(), false)
.map(NotificationSettingAssembler::toReferencelessDto)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package de.webalf.slotbot.controller;

import de.webalf.slotbot.assembler.NotificationSettingAssembler;
import de.webalf.slotbot.model.dtos.NotificationSettingDto;
import de.webalf.slotbot.model.dtos.referenceless.NotificationSettingsReferencelessDto;
import de.webalf.slotbot.service.NotificationSettingsService;
import de.webalf.slotbot.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;

import static de.webalf.slotbot.util.permissions.ApplicationPermissionHelper.HAS_ROLE_EVERYONE;
import static de.webalf.slotbot.util.permissions.PermissionHelper.assertIsLoggedInUser;

/**
* @author Alf
* @since 12.08.2021
*/
@RestController
@RequestMapping("/notifications")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class NotificationSettingsController {
private final NotificationSettingsService notificationSettingsService;
private final UserService userService;

@DeleteMapping("/{userId}")
@PreAuthorize(HAS_ROLE_EVERYONE)
public ResponseEntity<Void> deleteAllByUser(@PathVariable(name = "userId") String userId) {
assertIsLoggedInUser(userId);
notificationSettingsService.deleteAllByUser(userService.find(Long.parseLong(userId)));
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}

@PutMapping("/{userId}")
@PreAuthorize(HAS_ROLE_EVERYONE)
public List<NotificationSettingsReferencelessDto> updateNotificationSettings(@PathVariable(name = "userId") String userId, @RequestBody List<NotificationSettingDto> notificationSettings) {
assertIsLoggedInUser(userId);
return NotificationSettingAssembler.toReferencelessDtoList(
notificationSettingsService.updatePublicNotificationSettings(userService.find(Long.parseLong(userId)), notificationSettings)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public ModelAndView getWizardHtml(@RequestParam(required = false) String date, @
ModelAndView mav = new ModelAndView("eventWizard");

mav.addObject(START_URL_STRING, START_URL);
addCalendarSubPageObjects(mav);
mav.addObject(EVENTS_URL_STRING, EVENTS_URL);
mav.addObject("date", date);
if (StringUtils.isNotEmpty(copyEvent) && StringUtils.onlyNumbers(copyEvent)) {
Expand Down Expand Up @@ -106,6 +107,7 @@ public ModelAndView getEventEditHtml(@PathVariable(value = "id") long eventId) {
ModelAndView mav = new ModelAndView("eventEdit");

mav.addObject(START_URL_STRING, START_URL);
addCalendarSubPageObjects(mav);
mav.addObject(EVENTS_URL_STRING, EVENTS_URL);
final Event event = eventService.findById(eventId);
mav.addObject("event", eventDetailsAssembler.toEditDto(event));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package de.webalf.slotbot.controller.website;

import de.webalf.slotbot.controller.NotificationSettingsController;
import de.webalf.slotbot.model.User;
import de.webalf.slotbot.service.NotificationSettingsService;
import de.webalf.slotbot.service.UserService;
import de.webalf.slotbot.service.external.DiscordApiService;
import de.webalf.slotbot.service.external.DiscordApiService.GuildMember;
import de.webalf.slotbot.service.external.DiscordApiService.Role;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand All @@ -17,6 +19,7 @@
import java.util.stream.Collectors;

import static de.webalf.slotbot.util.permissions.ApplicationPermissionHelper.HAS_ROLE_EVERYONE;
import static de.webalf.slotbot.util.permissions.PermissionHelper.isLoggedInUser;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;

Expand All @@ -29,6 +32,8 @@
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class ProfileWebController {
private final DiscordApiService discordApiService;
private final UserService userService;
private final NotificationSettingsService notificationSettingsService;

@GetMapping("{userId}")
@PreAuthorize(HAS_ROLE_EVERYONE)
Expand All @@ -40,10 +45,13 @@ public ModelAndView getProfile(@PathVariable(value = "userId") String userId) {
mav.addObject("user", guildMember);
mav.addObject("roles", "@" + discordApiService.getRoles(guildMember.getRoles()).stream().map(Role::getName).collect(Collectors.joining(", @")));

final Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof OAuth2User) {
OAuth2User oAuth2User = (OAuth2User) principal;
mav.addObject("ownProfile", userId.equals(oAuth2User.getAttribute("id")));
final boolean ownProfile = isLoggedInUser(userId);
mav.addObject("ownProfile", ownProfile);
if (ownProfile) {
final User user = userService.find(Long.parseLong(userId));
mav.addObject("notificationSettings", notificationSettingsService.findAllPublicSettings(user));
mav.addObject("deleteAllByUserUrl", linkTo(methodOn(NotificationSettingsController.class).deleteAllByUser(userId)).toUri().toString());
mav.addObject("putNotificationSettingsUrl", linkTo(methodOn(NotificationSettingsController.class).deleteAllByUser(userId)).toUri().toString());
}

return mav;
Expand Down
1 change: 1 addition & 0 deletions src/main/java/de/webalf/slotbot/model/Event.java
Original file line number Diff line number Diff line change
Expand Up @@ -475,5 +475,6 @@ public void archive() {
}

setDiscordInformation(null);
//TODO delete notification settings
}
}
33 changes: 33 additions & 0 deletions src/main/java/de/webalf/slotbot/model/NotificationSetting.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package de.webalf.slotbot.model;

import lombok.*;
import lombok.experimental.SuperBuilder;

import javax.persistence.*;

/**
* @author Alf
* @since 11.08.2021
*/
@Entity
@Table(name = "notification_setting", uniqueConstraints = {@UniqueConstraint(columnNames = {"id"})})
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@SuperBuilder
public class NotificationSetting extends AbstractSuperIdEntity {
@ManyToOne(optional = false)
@JoinColumn(name = "user_id", nullable = false)
@NonNull
private User user;

@Column(name = "hours_before")
private int hoursBeforeEvent;

@Column(name = "minutes_before")
private int minutesBeforeEvent;

@ManyToOne
@JoinColumn(name = "event_id")
private Event event;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package de.webalf.slotbot.model.dtos;

import de.webalf.slotbot.model.dtos.referenceless.NotificationSettingsReferencelessDto;
import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import lombok.experimental.SuperBuilder;

/**
* @author Alf
* @since 12.08.2021
*/
@EqualsAndHashCode(callSuper = true)
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
@Data
@SuperBuilder
public class NotificationSettingDto extends NotificationSettingsReferencelessDto {
private EventDto event;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package de.webalf.slotbot.model.dtos.referenceless;

import de.webalf.slotbot.model.dtos.AbstractIdEntityDto;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;
import lombok.experimental.SuperBuilder;

/**
* @author Alf
* @since 12.08.2021
*/
@EqualsAndHashCode(callSuper = true)
@RequiredArgsConstructor
@Data
@SuperBuilder
public class NotificationSettingsReferencelessDto extends AbstractIdEntityDto {
private int hoursBeforeEvent;
private int minutesBeforeEvent;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package de.webalf.slotbot.repository;

import de.webalf.slotbot.model.NotificationSetting;
import de.webalf.slotbot.model.User;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
* @author Alf
* @since 11.08.2021
*/
@Repository
public interface NotificationSettingRepository extends SuperIdEntityJpaRepository<NotificationSetting> {
List<NotificationSetting> findAllByUserAndEventIsNull(User user);

void deleteAllByUser(User user);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package de.webalf.slotbot.service;

import de.webalf.slotbot.model.NotificationSetting;
import de.webalf.slotbot.model.User;
import de.webalf.slotbot.model.dtos.NotificationSettingDto;
import de.webalf.slotbot.repository.NotificationSettingRepository;
import de.webalf.slotbot.util.DtoUtils;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
* @author Alf
* @since 11.08.2021
*/
@Service
@Transactional
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class NotificationSettingsService {
private final NotificationSettingRepository notificationSettingRepository;

/**
* Finds all {@link NotificationSetting}s for the given {@link User} that don't have an event link
*
* @param user to get settings for
* @return all public settings of user
*/
public List<NotificationSetting> findAllPublicSettings(User user) {
return notificationSettingRepository.findAllByUserAndEventIsNull(user);
}

/**
* Sets the public {@link NotificationSetting}s for the given {@link User}
*
* @param user to update settings for
* @param notificationSettingDtos new complete list with new or updated settings
* @return saved public notification settings
*/
public List<NotificationSetting> updatePublicNotificationSettings(User user, @NonNull List<NotificationSettingDto> notificationSettingDtos) {
List<NotificationSetting> notificationSettings = new ArrayList<>();
notificationSettingDtos.forEach(notificationSettingDto ->
notificationSettings.add(updateOrCreateNotificationSetting(user, notificationSettingDto)));

//Delete removed settings
final List<NotificationSetting> existingSettings = new ArrayList<>(findAllPublicSettings(user));
existingSettings.removeIf(existingSetting ->
notificationSettings.stream().anyMatch(notificationSetting -> existingSetting.getId() == notificationSetting.getId()));
notificationSettingRepository.deleteAll(existingSettings);

return notificationSettings;
}

/**
* Updates or creates a new {@link NotificationSetting} for the given user
*
* @param user to notify
* @param dto new or updated setting
* @return saved setting
*/
private NotificationSetting updateOrCreateNotificationSetting(User user, @NonNull NotificationSettingDto dto) {
final NotificationSetting notificationSetting = notificationSettingRepository.findById(dto.getId()).orElseGet(() -> NotificationSetting.builder().user(user).build());

DtoUtils.ifPresent(dto.getHoursBeforeEvent(), notificationSetting::setHoursBeforeEvent);
DtoUtils.ifPresent(dto.getMinutesBeforeEvent(), notificationSetting::setMinutesBeforeEvent);

return notificationSettingRepository.save(notificationSetting);
}

/**
* Removes all {@link NotificationSetting}s for the given user
*
* @param user to deactivate notification for
*/
public void deleteAllByUser(User user) {
notificationSettingRepository.deleteAllByUser(user);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import de.webalf.slotbot.model.Event;
import de.webalf.slotbot.model.JobInfo;
import de.webalf.slotbot.model.User;
import de.webalf.slotbot.service.EventNotificationJob;
import de.webalf.slotbot.service.EventService;
import de.webalf.slotbot.service.SchedulerService;
import de.webalf.slotbot.service.job.EventNotificationJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package de.webalf.slotbot.service;
package de.webalf.slotbot.service.job;

import de.webalf.slotbot.model.JobInfo;
import de.webalf.slotbot.util.bot.MessageHelper;
Expand Down

0 comments on commit c327d35

Please sign in to comment.