Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 7779d8bd

Přidáno uživatelem Jakub Danek před více než 5 roky(ů)

re #37 secured access to deleting vacation requests

Disable unused edit vacation endpoint.

Zobrazit rozdíly:

server/src/main/java/org/danekja/ymanager/business/ApiManager.java
1 1
package org.danekja.ymanager.business;
2 2

  
3
import org.danekja.ymanager.business.auth.anot.CanModifyVacation;
3 4
import org.danekja.ymanager.business.auth.anot.IsOwner;
4 5
import org.danekja.ymanager.domain.*;
5 6
import org.danekja.ymanager.dto.DefaultSettings;
......
14 15
import org.springframework.dao.DataAccessException;
15 16
import org.springframework.stereotype.Component;
16 17

  
18
import javax.annotation.security.DenyAll;
17 19
import java.time.LocalDate;
18 20
import java.util.List;
19 21
import java.util.Optional;
......
206 208
    }
207 209

  
208 210
    @Override
209
    @IsOwner
210
    public void changeVacation(Long userId, VacationDay vacationDay) throws RESTFullException {
211
    //TODO not called anyway, allow after reimplementation
212
    @DenyAll
213
    public void changeVacation(VacationDay vacationDay) throws RESTFullException {
211 214
        try {
212 215
            Optional<Vacation> vacation = vacationRepository.getVacationDay(vacationDay.getId());
213 216
            if (vacation.isPresent()) {
......
268 271
    }
269 272

  
270 273
    @Override
271
    public void deleteVacation(Long userId, Long vacationId) throws RESTFullException {
274
    @CanModifyVacation
275
    public void deleteVacation(Long vacationId) throws RESTFullException {
272 276
        try {
273
            User user = userRepository.getUser(userId);
274 277
            Optional<Vacation> vacation = vacationRepository.getVacationDay(vacationId);
275 278

  
276 279
            if (!vacation.isPresent()) {
......
278 281
            }
279 282

  
280 283
            Vacation vacationDay = vacation.get();
284
            User user = userRepository.getUser(vacationDay.getUserId());
281 285

  
282 286
            if (vacationDay.getDate().isAfter(LocalDate.now())) {
283 287
                if (!vacationDay.getStatus().equals(Status.REJECTED)) {
server/src/main/java/org/danekja/ymanager/business/Manager.java
25 25

  
26 26
    void changeSettings(Long userId, UserSettings settings) throws RESTFullException;
27 27

  
28
    void changeVacation(Long userId, VacationDay vacationDay) throws RESTFullException;
28
    void changeVacation(VacationDay vacationDay) throws RESTFullException;
29 29

  
30 30
    void changeRequest(RequestType type, BasicRequest request) throws RESTFullException;
31 31

  
32
    void deleteVacation(Long userId, Long vacationId) throws RESTFullException;
32
    void deleteVacation(Long vacationId) throws RESTFullException;
33 33
}
server/src/main/java/org/danekja/ymanager/business/auth/anot/CanModifyVacation.java
1
package org.danekja.ymanager.business.auth.anot;
2

  
3
import org.springframework.security.access.prepost.PreAuthorize;
4

  
5
import java.lang.annotation.*;
6

  
7
/**
8
 * Methods annotated with this interface can be called either by EMPLOYER role
9
 * or owner of the given vacation instance.
10
 * <p>
11
 * This annotation expects method to have {@code Long vacationId} argument.
12
 */
13
@Target({ElementType.METHOD, ElementType.TYPE})
14
@Retention(RetentionPolicy.RUNTIME)
15
@Inherited
16
@Documented
17
@PreAuthorize("hasPermission(#vacationId, 'Vacation', null)")
18
public @interface CanModifyVacation {
19

  
20
}
server/src/main/java/org/danekja/ymanager/business/auth/permissions/VacationModifyPermisionEvaluator.java
1
package org.danekja.ymanager.business.auth.permissions;
2

  
3
import org.danekja.ymanager.domain.User;
4
import org.danekja.ymanager.domain.UserRole;
5
import org.danekja.ymanager.domain.Vacation;
6
import org.danekja.ymanager.repository.VacationRepository;
7
import org.slf4j.Logger;
8
import org.slf4j.LoggerFactory;
9
import org.springframework.beans.factory.annotation.Autowired;
10
import org.springframework.security.core.Authentication;
11
import org.springframework.stereotype.Component;
12

  
13
import java.io.Serializable;
14
import java.util.Objects;
15

  
16
/**
17
 * {@link TypedPermissionEvaluator} for checking permissions for {@link Vacation} objects.
18
 * <p>
19
 * Invoke via {@code hasPermissions(<id parameter name>, 'Vacation', null)} permission syntax in security annotations.
20
 */
21
@Component
22
public class VacationModifyPermisionEvaluator implements TypedPermissionEvaluator {
23

  
24
    private static final Logger LOG = LoggerFactory.getLogger(VacationModifyPermisionEvaluator.class);
25

  
26
    private final VacationRepository vacationRepository;
27

  
28
    @Autowired
29
    public VacationModifyPermisionEvaluator(VacationRepository vacationRepository) {
30
        this.vacationRepository = vacationRepository;
31
    }
32

  
33
    @Override
34
    public String getTargetType() {
35
        return Vacation.class.getSimpleName();
36
    }
37

  
38
    @Override
39
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
40
        if (targetDomainObject != null && Vacation.class.isAssignableFrom(targetDomainObject.getClass())) {
41
            Vacation target = (Vacation) targetDomainObject;
42

  
43
            LOG.debug("Checking permission of {} to vacation: {}", authentication.getName(), target.getId());
44

  
45
            if (authentication.getAuthorities().parallelStream().anyMatch(o -> Objects.equals(o.getAuthority(), UserRole.EMPLOYER.name()))) {
46

  
47
                LOG.debug("Permission of {} to vacation: {} granted to employer", authentication.getName(), target.getId());
48
                return true;
49

  
50
            } else {
51

  
52
                boolean canDo = Objects.equals(target.getUserId(), ((User) authentication.getPrincipal()).getId());
53
                LOG.debug("Permission of {} to vacation: {} for employee: {}", authentication.getName(), target.getId(), canDo);
54
                return canDo;
55

  
56
            }
57
        }
58

  
59
        LOG.warn("Checking permission of {} to vacation: {} failed - null or invalid type of object", authentication.getName(), targetDomainObject);
60
        return false;
61
    }
62

  
63
    @Override
64
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
65
        if (targetId != null && Long.class.isAssignableFrom(targetId.getClass()) && Objects.equals(Vacation.class.getSimpleName(), targetType)) {
66
            return hasPermission(authentication, vacationRepository.getVacationDay((Long) targetId).orElse(null), permission);
67
        }
68

  
69
        return false;
70
    }
71
}
server/src/main/java/org/danekja/ymanager/ws/rest/ApiController.java
139 139
    @RequestMapping(value = "/user/calendar/edit", method=PUT)
140 140
    public ResponseEntity userCalendarEdit(
141 141
            @RequestParam(value = "lang", required = false) String lang,
142
            @RequestBody VacationDay vacationDay,
143
            Authentication auth)
142
            @RequestBody VacationDay vacationDay)
144 143
    {
145
        //TODO make api endpoint contain userId in path as part of #39, also drop the edit part of path
144
        //TODO make api endpoint point to vacation endpoint as part of #39, also drop the edit part of path
146 145
        //TODO drop the auth parameter afterwards
147 146
        return handle(Language.getLanguage(lang), () ->
148
                manager.changeVacation(((User) auth.getPrincipal()).getId(), vacationDay)
147
                manager.changeVacation(vacationDay)
149 148
        );
150 149
    }
151 150

  
......
164 163

  
165 164
    @RequestMapping(value = "/calendar/{id}/delete", method=DELETE)
166 165
    public ResponseEntity calendarDelete(
167
            @PathVariable("id") String id,
166
            @PathVariable("id") Long id,
168 167
            @RequestParam(value = "lang", required = false) String lang)
169 168
    {
170 169
        return handle(Language.getLanguage(lang), () ->
171
            manager.deleteVacation(getUserId("me"), StringUtils.isNumeric(id) ? Long.parseLong(id) : -1)
170
                manager.deleteVacation(id)
172 171
        );
173 172
    }
174 173

  

Také k dispozici: Unified diff