File size: 16,314 Bytes
9373c61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5cfe5c4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
package com.dalab.policyengine.web.rest;

import java.net.URI;
import java.time.Instant;
import java.util.List;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import com.dalab.common.security.SecurityUtils;
import com.dalab.policyengine.dto.EventAnalyticsDTO;
import com.dalab.policyengine.dto.EventStreamDTO;
import com.dalab.policyengine.dto.EventSubscriptionInputDTO;
import com.dalab.policyengine.dto.EventSubscriptionOutputDTO;
import com.dalab.policyengine.model.EventSubscriptionStatus;
import com.dalab.policyengine.model.EventType;
import com.dalab.policyengine.service.IEventSubscriptionService;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;

/**

 * REST controller for Event Center functionality.

 * Provides endpoints for managing event subscriptions, streaming events, and analytics.

 */
@RestController
@RequestMapping("/api/v1/policyengine/events")
@Tag(name = "Event Center", description = "Endpoints for Event Center management, streaming, and analytics")
public class EventCenterController {

    private static final Logger log = LoggerFactory.getLogger(EventCenterController.class);

    private final IEventSubscriptionService eventSubscriptionService;

    @Autowired
    public EventCenterController(IEventSubscriptionService eventSubscriptionService) {
        this.eventSubscriptionService = eventSubscriptionService;
    }

    // Endpoint 1: Subscription Management
    @PostMapping("/subscriptions")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Create event subscription",

        description = "Create a new event subscription to receive notifications for specific event types and conditions"

    )
    @ApiResponses(value = {

        @ApiResponse(responseCode = "201", description = "Event subscription created successfully"),

        @ApiResponse(responseCode = "400", description = "Invalid subscription configuration"),

        @ApiResponse(responseCode = "403", description = "Insufficient permissions to create subscription")

    })
    public ResponseEntity<EventSubscriptionOutputDTO> createSubscription(

            @Parameter(description = "Event subscription configuration")

            @Valid @RequestBody EventSubscriptionInputDTO inputDTO) {
        log.info("REST request to create Event Subscription: {}", inputDTO.getName());
        
        UUID creatorUserId = SecurityUtils.getAuthenticatedUserId();
        EventSubscriptionOutputDTO createdSubscription = eventSubscriptionService.createSubscription(inputDTO, creatorUserId);
        
        URI location = ServletUriComponentsBuilder.fromCurrentRequest()
                .path("/{id}")
                .buildAndExpand(createdSubscription.getId())
                .toUri();
        
        return ResponseEntity.created(location).body(createdSubscription);
    }

    @GetMapping("/subscriptions")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Get user's event subscriptions",

        description = "Retrieve event subscriptions for the authenticated user with optional filtering"

    )
    public ResponseEntity<Page<EventSubscriptionOutputDTO>> getUserSubscriptions(

            @PageableDefault(size = 20, sort = "name") Pageable pageable,

            @RequestParam(required = false) String status,

            @RequestParam(required = false) String nameContains) {
        log.info("REST request to get Event Subscriptions for user with filters: status={}, nameContains={}", status, nameContains);
        
        UUID userId = SecurityUtils.getAuthenticatedUserId();
        Page<EventSubscriptionOutputDTO> subscriptionsPage = eventSubscriptionService.getSubscriptionsForUser(
                userId, pageable, status, nameContains);
        
        return ResponseEntity.ok(subscriptionsPage);
    }

    @GetMapping("/subscriptions/{subscriptionId}")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Get event subscription by ID",

        description = "Retrieve detailed information about a specific event subscription"

    )
    public ResponseEntity<EventSubscriptionOutputDTO> getSubscriptionById(@PathVariable UUID subscriptionId) {
        log.info("REST request to get Event Subscription by id: {}", subscriptionId);
        
        EventSubscriptionOutputDTO subscription = eventSubscriptionService.getSubscriptionById(subscriptionId);
        return ResponseEntity.ok(subscription);
    }

    @PutMapping("/subscriptions/{subscriptionId}")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Update event subscription",

        description = "Update configuration of an existing event subscription"

    )
    public ResponseEntity<EventSubscriptionOutputDTO> updateSubscription(

            @PathVariable UUID subscriptionId,

            @Valid @RequestBody EventSubscriptionInputDTO inputDTO) {
        log.info("REST request to update Event Subscription: {}", subscriptionId);
        
        UUID updaterUserId = SecurityUtils.getAuthenticatedUserId();
        EventSubscriptionOutputDTO updatedSubscription = eventSubscriptionService.updateSubscription(
                subscriptionId, inputDTO, updaterUserId);
        
        return ResponseEntity.ok(updatedSubscription);
    }

    @DeleteMapping("/subscriptions/{subscriptionId}")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Delete event subscription",

        description = "Delete an event subscription and stop receiving notifications"

    )
    public ResponseEntity<Void> deleteSubscription(@PathVariable UUID subscriptionId) {
        log.info("REST request to delete Event Subscription: {}", subscriptionId);
        
        eventSubscriptionService.deleteSubscription(subscriptionId);
        return ResponseEntity.noContent().build();
    }

    @PutMapping("/subscriptions/{subscriptionId}/status")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Update subscription status",

        description = "Enable, disable, pause, or archive an event subscription"

    )
    public ResponseEntity<EventSubscriptionOutputDTO> updateSubscriptionStatus(

            @PathVariable UUID subscriptionId,

            @RequestParam EventSubscriptionStatus status) {
        log.info("REST request to update Event Subscription status: {} to {}", subscriptionId, status);
        
        UUID updaterUserId = SecurityUtils.getAuthenticatedUserId();
        EventSubscriptionOutputDTO updatedSubscription = eventSubscriptionService.updateSubscriptionStatus(
                subscriptionId, status, updaterUserId);
        
        return ResponseEntity.ok(updatedSubscription);
    }

    // Endpoint 2: Event Streaming
    @GetMapping("/stream")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Get real-time event stream",

        description = "Retrieve real-time events matching user's subscriptions for the Event Center dashboard"

    )
    @ApiResponses(value = {

        @ApiResponse(responseCode = "200", description = "Event stream retrieved successfully"),

        @ApiResponse(responseCode = "403", description = "Insufficient permissions to access event stream")

    })
    public ResponseEntity<List<EventStreamDTO>> getEventStream(

            @Parameter(description = "Maximum number of events to return (default: 50)")

            @RequestParam(defaultValue = "50") Integer limit) {
        log.info("REST request to get Event Stream with limit: {}", limit);
        
        UUID userId = SecurityUtils.getAuthenticatedUserId();
        List<EventStreamDTO> eventStream = eventSubscriptionService.getEventStreamForUser(userId, limit);
        
        return ResponseEntity.ok(eventStream);
    }

    @GetMapping("/stream/all")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN')")
    @Operation(

        summary = "Get all event stream (Admin only)",

        description = "Retrieve real-time events from all subscriptions across the platform"

    )
    public ResponseEntity<List<EventStreamDTO>> getAllEventStream(

            @RequestParam(defaultValue = "100") Integer limit) {
        log.info("REST request to get All Event Stream with limit: {}", limit);
        
        List<EventStreamDTO> eventStream = eventSubscriptionService.getAllEventStream(limit);
        return ResponseEntity.ok(eventStream);
    }

    // Endpoint 3: Historical Events
    @GetMapping("/subscriptions/{subscriptionId}/history")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Get historical events for subscription",

        description = "Retrieve paginated historical events that matched a specific subscription"

    )
    public ResponseEntity<Page<EventStreamDTO>> getHistoricalEvents(

            @PathVariable UUID subscriptionId,

            @PageableDefault(size = 50, sort = "timestamp") Pageable pageable) {
        log.info("REST request to get Historical Events for subscription: {}", subscriptionId);
        
        Page<EventStreamDTO> historicalEvents = eventSubscriptionService.getHistoricalEventsForSubscription(
                subscriptionId, pageable);
        
        return ResponseEntity.ok(historicalEvents);
    }

    // Endpoint 4: Event Analytics
    @GetMapping("/analytics")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Get event analytics dashboard",

        description = "Retrieve comprehensive analytics for user's event subscriptions including trends, metrics, and insights"

    )
    @ApiResponses(value = {

        @ApiResponse(responseCode = "200", description = "Event analytics retrieved successfully"),

        @ApiResponse(responseCode = "403", description = "Insufficient permissions to access analytics")

    })
    public ResponseEntity<EventAnalyticsDTO> getEventAnalytics(

            @Parameter(description = "Start time for analytics (defaults to 24 hours ago)")

            @RequestParam(required = false) String fromTime,

            @Parameter(description = "End time for analytics (defaults to now)")

            @RequestParam(required = false) String toTime) {
        log.info("REST request to get Event Analytics with time range: {} to {}", fromTime, toTime);
        
        UUID userId = SecurityUtils.getAuthenticatedUserId();
        
        if (fromTime != null && toTime != null) {
            Instant from = Instant.parse(fromTime);
            Instant to = Instant.parse(toTime);
            EventAnalyticsDTO analytics = eventSubscriptionService.getEventAnalyticsForTimeRange(userId, from, to);
            return ResponseEntity.ok(analytics);
        } else {
            EventAnalyticsDTO analytics = eventSubscriptionService.getEventAnalyticsForUser(userId);
            return ResponseEntity.ok(analytics);
        }
    }

    @GetMapping("/analytics/system")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN')")
    @Operation(

        summary = "Get system-wide event analytics (Admin only)",

        description = "Retrieve comprehensive analytics across all subscriptions and users in the platform"

    )
    public ResponseEntity<EventAnalyticsDTO> getSystemEventAnalytics() {
        log.info("REST request to get System Event Analytics");
        
        EventAnalyticsDTO analytics = eventSubscriptionService.getSystemEventAnalytics();
        return ResponseEntity.ok(analytics);
    }

    // Endpoint 5: Rule Testing
    @PostMapping("/test-rule")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Test event rule condition",

        description = "Test an event rule condition against sample event data to validate rule logic before creating subscription"

    )
    @ApiResponses(value = {

        @ApiResponse(responseCode = "200", description = "Rule test completed successfully"),

        @ApiResponse(responseCode = "400", description = "Invalid rule condition or sample data")

    })
    public ResponseEntity<Boolean> testEventRule(

            @Parameter(description = "MVEL rule condition to test")

            @RequestParam String ruleCondition,

            @Parameter(description = "Sample event data for testing")

            @Valid @RequestBody EventStreamDTO sampleEvent) {
        log.info("REST request to test Event Rule condition: {}", ruleCondition);
        
        boolean ruleMatches = eventSubscriptionService.testEventRule(ruleCondition, sampleEvent);
        
        return ResponseEntity.ok(ruleMatches);
    }

    // Endpoint 6: Configuration Helpers
    @GetMapping("/config/event-types")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Get available event types",

        description = "Retrieve list of all available event types for subscription configuration"

    )
    public ResponseEntity<List<EventType>> getAvailableEventTypes() {
        log.info("REST request to get Available Event Types");
        
        List<EventType> eventTypes = eventSubscriptionService.getAvailableEventTypes();
        return ResponseEntity.ok(eventTypes);
    }

    @GetMapping("/config/source-services")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Get available source services",

        description = "Retrieve list of all available source services for subscription configuration"

    )
    public ResponseEntity<List<String>> getAvailableSourceServices() {
        log.info("REST request to get Available Source Services");
        
        List<String> sourceServices = eventSubscriptionService.getAvailableSourceServices();
        return ResponseEntity.ok(sourceServices);
    }

    @PostMapping("/config/validate")
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_POLICY_MANAGER', 'ROLE_USER')")
    @Operation(

        summary = "Validate subscription configuration",

        description = "Validate event subscription configuration before creation to catch errors early"

    )
    public ResponseEntity<Void> validateSubscriptionConfiguration(

            @Valid @RequestBody EventSubscriptionInputDTO inputDTO) {
        log.info("REST request to validate Subscription Configuration: {}", inputDTO.getName());
        
        eventSubscriptionService.validateSubscriptionConfiguration(inputDTO);
        return ResponseEntity.ok().build();
    }
}