ChatMessageController.java

1
package edu.ucsb.cs156.happiercows.controllers;
2
3
import com.fasterxml.jackson.databind.ObjectMapper;
4
import io.swagger.v3.oas.annotations.tags.Tag;
5
import lombok.extern.slf4j.Slf4j;
6
import io.swagger.v3.oas.annotations.Operation;
7
import io.swagger.v3.oas.annotations.Parameter;
8
import org.springframework.beans.factory.annotation.Autowired;
9
import org.springframework.http.HttpStatus;
10
import org.springframework.http.ResponseEntity;
11
import org.springframework.security.access.prepost.PreAuthorize;
12
import org.springframework.security.core.context.SecurityContextHolder;
13
import org.springframework.web.bind.annotation.*;
14
import org.springframework.data.domain.Page;
15
import org.springframework.data.domain.PageRequest;
16
import org.springframework.data.domain.Sort;
17
18
import edu.ucsb.cs156.happiercows.entities.ChatMessage;
19
import edu.ucsb.cs156.happiercows.repositories.ChatMessageRepository;
20
21
import edu.ucsb.cs156.happiercows.entities.User;
22
import edu.ucsb.cs156.happiercows.entities.UserCommons;
23
import edu.ucsb.cs156.happiercows.repositories.UserCommonsRepository;
24
25
import org.springframework.security.core.Authentication;
26
27
28
import java.util.Optional;
29
30
@Tag(name = "Chat Message")
31
@RequestMapping("/api/chat")
32
@RestController
33
@Slf4j
34
public class ChatMessageController extends ApiController{
35
36
    @Autowired
37
    private ChatMessageRepository chatMessageRepository;
38
39
    @Autowired
40
    private UserCommonsRepository userCommonsRepository;
41
42
    @Autowired
43
    ObjectMapper mapper;
44
45
    @Operation(summary = "Get all chat messages", description = "Get all chat messages associated with a specific commons.")
46
    @PreAuthorize("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')")
47
    @GetMapping("/get")
48
    public ResponseEntity<Object> getChatMessages(@Parameter(description = "The id of the common") @RequestParam Long commonsId,
49
                                            @Parameter(name="page") @RequestParam int page,
50
                                            @Parameter(name="size") @RequestParam int size) {
51
        
52
        // Make sure the user is part of the commons or is an admin
53
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
54 3 1. getChatMessages : negated conditional → KILLED
2. lambda$getChatMessages$0 : replaced boolean return with false for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::lambda$getChatMessages$0 → KILLED
3. lambda$getChatMessages$0 : replaced boolean return with true for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::lambda$getChatMessages$0 → KILLED
        if (!auth.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))){
55
            log.info("User is not an admin");
56
            User user = getCurrentUser().getUser();
57
            Long userId = user.getId();
58
            Optional<UserCommons> userCommonsLookup = userCommonsRepository.findByCommonsIdAndUserId(commonsId, userId);
59
60 1 1. getChatMessages : negated conditional → KILLED
            if (!userCommonsLookup.isPresent()) {
61 1 1. getChatMessages : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::getChatMessages → KILLED
                return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
62
            }
63
        }
64
65
        // Return the list of non-hidden chat messages
66
        Page<ChatMessage> messages = chatMessageRepository.findByCommonsId(commonsId, PageRequest.of(page, size, Sort.by("timestamp").descending()));
67 1 1. getChatMessages : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::getChatMessages → KILLED
        return ResponseEntity.ok(messages);
68
    }
69
70
    @Operation(summary = "Get all chat messages (Admins)", description = "Get all chat messages associated with a specific commons, even the hidden ones. Used only by admins")
71
    @PreAuthorize("hasRole('ROLE_ADMIN')")
72
    @GetMapping("/admin/get")
73
    public ResponseEntity<Object> getAllChatMessages(@Parameter(description = "The id of the common") @RequestParam Long commonsId,
74
                                                    @Parameter(name="page") @RequestParam int page,
75
                                                    @Parameter(name="size") @RequestParam int size) {
76
        
77
        // Return the list of chat messages
78
        Page<ChatMessage> messages = chatMessageRepository.findAllByCommonsId(commonsId, PageRequest.of(page, size, Sort.by("timestamp").descending()));
79 1 1. getAllChatMessages : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::getAllChatMessages → KILLED
        return ResponseEntity.ok(messages);
80
    }
81
82
    
83
    @Operation(summary = "Get hidden chat messages", description = "Get all hidden chat messages associated with a specific commons. Used only by admins")
84
    @PreAuthorize("hasRole('ROLE_ADMIN')")
85
    @GetMapping("/admin/hidden")
86
    public ResponseEntity<Object> getHiddenChatMessages(@Parameter(description = "The id of the common") @RequestParam Long commonsId,
87
                                                    @Parameter(name="page") @RequestParam int page,
88
                                                    @Parameter(name="size") @RequestParam int size) {
89
        
90
        // Return the list of hidden chat messages
91
        Page<ChatMessage> messages = chatMessageRepository.findByCommonsIdAndHidden(commonsId, PageRequest.of(page, size, Sort.by("timestamp").descending()));
92 1 1. getHiddenChatMessages : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::getHiddenChatMessages → KILLED
        return ResponseEntity.ok(messages);
93
    }
94
    
95
    
96
    @Operation(summary = "Create a chat message", description = "Create a chat message associated with a specific commons")
97
    @PreAuthorize("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')")
98
    @PostMapping("/post")
99
    public ResponseEntity<Object> createChatMessage(@Parameter(description = "The id of the common") @RequestParam Long commonsId,
100
                                                    @Parameter(description = "The message to be sent") @RequestParam String content) {
101
        
102
        User user = getCurrentUser().getUser();
103
        Long userId = user.getId();
104
105
        // Make sure the user is part of the commons or is an admin
106
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
107 3 1. createChatMessage : negated conditional → KILLED
2. lambda$createChatMessage$1 : replaced boolean return with false for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::lambda$createChatMessage$1 → KILLED
3. lambda$createChatMessage$1 : replaced boolean return with true for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::lambda$createChatMessage$1 → KILLED
        if (!auth.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))){
108
            log.info("User is not an admin");
109
            Optional<UserCommons> userCommonsLookup = userCommonsRepository.findByCommonsIdAndUserId(commonsId, userId);
110
111 1 1. createChatMessage : negated conditional → KILLED
            if (!userCommonsLookup.isPresent()) {
112 1 1. createChatMessage : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::createChatMessage → KILLED
                return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
113
            }
114
        }
115
116
        // Create the chat message
117
        ChatMessage chatMessage = ChatMessage.builder()
118
        .commonsId(commonsId)
119
        .userId(userId)
120
        .message(content)
121
        .hidden(false)
122
        .dm(false)
123
        .toUserId(0)
124
        .build();
125
126
        // Save the message
127
        chatMessageRepository.save(chatMessage);
128
129 1 1. createChatMessage : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::createChatMessage → KILLED
        return ResponseEntity.ok(chatMessage);
130
    }
131
132
    @Operation(summary = "Delete a chat message", description = "Delete a chat message associated with a specific commons")
133
    @PreAuthorize("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')")
134
    @PutMapping("/hide")
135
    public ResponseEntity<Object> hideChatMessage(@Parameter(description = "The id of the chat message") @RequestParam Long chatMessageId) {
136
137
        // Try to get the chat message
138
        Optional<ChatMessage> chatMessageLookup = chatMessageRepository.findById(chatMessageId);
139 1 1. hideChatMessage : negated conditional → KILLED
        if (!chatMessageLookup.isPresent()) {
140 1 1. hideChatMessage : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::hideChatMessage → KILLED
            return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
141
        }
142
        ChatMessage chatMessage = chatMessageLookup.get();
143
144
        User user = getCurrentUser().getUser();
145
        Long userId = user.getId();
146
147
        // Check if the user is the author of the message
148 1 1. hideChatMessage : negated conditional → KILLED
        if (chatMessage.getUserId() != userId) {
149
            // Check if the user is an admin
150
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
151 3 1. hideChatMessage : negated conditional → KILLED
2. lambda$hideChatMessage$2 : replaced boolean return with false for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::lambda$hideChatMessage$2 → KILLED
3. lambda$hideChatMessage$2 : replaced boolean return with true for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::lambda$hideChatMessage$2 → KILLED
            if (!auth.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))){
152 1 1. hideChatMessage : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::hideChatMessage → KILLED
                return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
153
            }
154
        }
155
156
        // Hide the message
157 1 1. hideChatMessage : removed call to edu/ucsb/cs156/happiercows/entities/ChatMessage::setHidden → KILLED
        chatMessage.setHidden(true);
158
        chatMessageRepository.save(chatMessage);
159
160 1 1. hideChatMessage : replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::hideChatMessage → KILLED
        return ResponseEntity.ok(chatMessage);
161
    }
162
163
    
164
165
}

Mutations

54

1.1
Location : getChatMessages
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userNotInCommonsCannotGetChatMessages()]
negated conditional → KILLED

2.2
Location : lambda$getChatMessages$0
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:adminCanGetChatMessages()]
replaced boolean return with false for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::lambda$getChatMessages$0 → KILLED

3.3
Location : lambda$getChatMessages$0
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userNotInCommonsCannotGetChatMessages()]
replaced boolean return with true for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::lambda$getChatMessages$0 → KILLED

60

1.1
Location : getChatMessages
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userNotInCommonsCannotGetChatMessages()]
negated conditional → KILLED

61

1.1
Location : getChatMessages
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userNotInCommonsCannotGetChatMessages()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::getChatMessages → KILLED

67

1.1
Location : getChatMessages
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:adminCanGetChatMessages()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::getChatMessages → KILLED

79

1.1
Location : getAllChatMessages
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:adminCanGetAllChatMessages()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::getAllChatMessages → KILLED

92

1.1
Location : getHiddenChatMessages
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:adminCanGetHiddenChatMessages()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::getHiddenChatMessages → KILLED

107

1.1
Location : createChatMessage
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:adminCanPostChatMessages()]
negated conditional → KILLED

2.2
Location : lambda$createChatMessage$1
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:adminCanPostChatMessages()]
replaced boolean return with false for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::lambda$createChatMessage$1 → KILLED

3.3
Location : lambda$createChatMessage$1
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userNotInCommonsCannotPostChatMessages()]
replaced boolean return with true for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::lambda$createChatMessage$1 → KILLED

111

1.1
Location : createChatMessage
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userNotInCommonsCannotPostChatMessages()]
negated conditional → KILLED

112

1.1
Location : createChatMessage
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userNotInCommonsCannotPostChatMessages()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::createChatMessage → KILLED

129

1.1
Location : createChatMessage
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:adminCanPostChatMessages()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::createChatMessage → KILLED

139

1.1
Location : hideChatMessage
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userCannotDeleteOtherUsersChatMessages()]
negated conditional → KILLED

140

1.1
Location : hideChatMessage
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:adminCannotHideChatMessagesThatDontExist()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::hideChatMessage → KILLED

148

1.1
Location : hideChatMessage
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userCannotDeleteOtherUsersChatMessages()]
negated conditional → KILLED

151

1.1
Location : hideChatMessage
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userCannotDeleteOtherUsersChatMessages()]
negated conditional → KILLED

2.2
Location : lambda$hideChatMessage$2
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:adminCanHideChatMessages()]
replaced boolean return with false for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::lambda$hideChatMessage$2 → KILLED

3.3
Location : lambda$hideChatMessage$2
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userCannotDeleteOtherUsersChatMessages()]
replaced boolean return with true for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::lambda$hideChatMessage$2 → KILLED

152

1.1
Location : hideChatMessage
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userCannotDeleteOtherUsersChatMessages()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::hideChatMessage → KILLED

157

1.1
Location : hideChatMessage
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userCanDeleteTheirOwnChatMessages()]
removed call to edu/ucsb/cs156/happiercows/entities/ChatMessage::setHidden → KILLED

160

1.1
Location : hideChatMessage
Killed by : edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests.[engine:junit-jupiter]/[class:edu.ucsb.cs156.happiercows.controllers.ChatMessageControllerTests]/[method:userCanDeleteTheirOwnChatMessages()]
replaced return value with null for edu/ucsb/cs156/happiercows/controllers/ChatMessageController::hideChatMessage → KILLED

Active mutators

Tests examined


Report generated by PIT 1.7.3