Updated API Dashboard
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
package com.rit.canteen.sales.config;
|
||||
|
||||
import com.rit.canteen.sales.model.DeveloperApiKey;
|
||||
import com.rit.canteen.sales.model.DeveloperApiLog;
|
||||
import com.rit.canteen.sales.repository.DeveloperApiKeyRepository;
|
||||
import com.rit.canteen.sales.repository.DeveloperApiLogRepository;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class DeveloperApiLogInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Autowired
|
||||
private DeveloperApiKeyRepository keyRepository;
|
||||
|
||||
@Autowired
|
||||
private DeveloperApiLogRepository logRepository;
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||
String uri = request.getRequestURI();
|
||||
if (uri.startsWith("/api/developer/v1/")) {
|
||||
String apiKeyHeader = request.getHeader("X-Developer-Key");
|
||||
String method = request.getMethod();
|
||||
int status = response.getStatus();
|
||||
String clientIp = request.getHeader("X-Forwarded-For");
|
||||
if (clientIp == null || clientIp.isEmpty()) {
|
||||
clientIp = request.getRemoteAddr();
|
||||
}
|
||||
|
||||
DeveloperApiLog log = new DeveloperApiLog();
|
||||
log.setEndpoint(uri);
|
||||
log.setMethod(method);
|
||||
log.setStatus(status);
|
||||
log.setClientIp(clientIp);
|
||||
|
||||
String responseBody = (String) request.getAttribute("developer_api_response_body");
|
||||
if (responseBody != null) {
|
||||
log.setResponseBody(responseBody);
|
||||
}
|
||||
|
||||
if (apiKeyHeader != null && !apiKeyHeader.trim().isEmpty()) {
|
||||
log.setApiKey(apiKeyHeader);
|
||||
Optional<DeveloperApiKey> keyOpt = keyRepository.findByApiKey(apiKeyHeader);
|
||||
if (keyOpt.isPresent()) {
|
||||
DeveloperApiKey key = keyOpt.get();
|
||||
log.setAppId(key.getAppId());
|
||||
log.setUserId(key.getUserId());
|
||||
log.setUserType(key.getUserType());
|
||||
}
|
||||
}
|
||||
|
||||
logRepository.save(log);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.rit.canteen.sales.config;
|
||||
|
||||
import com.rit.canteen.sales.controller.DeveloperApiController;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpResponse;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
@ControllerAdvice(assignableTypes = {DeveloperApiController.class})
|
||||
public class DeveloperApiResponseAdvice implements ResponseBodyAdvice<Object> {
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
|
||||
Class<? extends HttpMessageConverter<?>> selectedConverterType,
|
||||
ServerHttpRequest request, ServerHttpResponse response) {
|
||||
try {
|
||||
if (request instanceof ServletServerHttpRequest servletRequest) {
|
||||
HttpServletRequest httpReq = servletRequest.getServletRequest();
|
||||
if (body != null) {
|
||||
String json = objectMapper.writeValueAsString(body);
|
||||
httpReq.setAttribute("developer_api_response_body", json);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
return body;
|
||||
}
|
||||
}
|
||||
@@ -92,6 +92,7 @@ public class SecurityConfig {
|
||||
.requestMatchers(HttpMethod.PUT, "/api/orders/*").authenticated()
|
||||
.requestMatchers(HttpMethod.POST, "/api/orders/*/cancel").authenticated()
|
||||
.requestMatchers("/api/developer-keys/**").authenticated()
|
||||
.requestMatchers("/api/developer-apps/**").authenticated()
|
||||
.requestMatchers("/api/developer/v1/**").permitAll()
|
||||
.requestMatchers("/api/counter/**").hasAnyRole("MASTER", "MANAGER", "STAFF")
|
||||
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
package com.rit.canteen.sales.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* WebConfig intentionally left minimal.
|
||||
* CORS is now fully managed by SecurityConfig.corsConfigurationSource()
|
||||
* to avoid duplicate/conflicting CORS headers.
|
||||
*/
|
||||
@Configuration
|
||||
public class WebConfig {
|
||||
// CORS handled by SecurityConfig — do not add CorsRegistry here
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Autowired
|
||||
private DeveloperApiLogInterceptor logInterceptor;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(logInterceptor).addPathPatterns("/api/developer/v1/**");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.rit.canteen.sales.model.DeveloperApiLog;
|
||||
import com.rit.canteen.sales.repository.DeveloperApiLogRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -19,6 +22,30 @@ public class DeveloperApiKeyController {
|
||||
@Autowired
|
||||
private DeveloperApiKeyService keyService;
|
||||
|
||||
@Autowired
|
||||
private DeveloperApiLogRepository logRepository;
|
||||
|
||||
@GetMapping("/logs")
|
||||
public ResponseEntity<?> listLogs(
|
||||
@RequestParam(defaultValue = "0") int page,
|
||||
@RequestParam(defaultValue = "10") int size) {
|
||||
UserContext context = getUserContext();
|
||||
if (context == null) {
|
||||
return ResponseEntity.status(401).body(Map.of("error", "Unauthorized"));
|
||||
}
|
||||
org.springframework.data.domain.Pageable pageable = org.springframework.data.domain.PageRequest.of(
|
||||
page, size, org.springframework.data.domain.Sort.by("timestamp").descending());
|
||||
org.springframework.data.domain.Page<DeveloperApiLog> logPage = logRepository.findByUserIdAndUserType(
|
||||
context.userId, context.userType, pageable);
|
||||
return ResponseEntity.ok(Map.of(
|
||||
"content", logPage.getContent(),
|
||||
"currentPage", logPage.getNumber(),
|
||||
"totalItems", logPage.getTotalElements(),
|
||||
"totalPages", logPage.getTotalPages(),
|
||||
"pageSize", logPage.getSize()
|
||||
));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<?> listKeys() {
|
||||
UserContext context = getUserContext();
|
||||
@@ -56,8 +83,17 @@ public class DeveloperApiKeyController {
|
||||
permissions = "READ_PRODUCTS,READ_STALLS,READ_ORDERS,READ_WALLETS";
|
||||
}
|
||||
|
||||
Long appId = null;
|
||||
if (body.containsKey("appId") && body.get("appId") != null) {
|
||||
try {
|
||||
appId = Long.valueOf(body.get("appId").toString());
|
||||
} catch (NumberFormatException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
DeveloperApiKey newKey = keyService.createKey(context.userId, context.userType, context.identifier, name, writeAccess, permissions);
|
||||
DeveloperApiKey newKey = keyService.createKey(context.userId, context.userType, context.identifier, name, writeAccess, permissions, appId);
|
||||
return ResponseEntity.status(201).body(newKey);
|
||||
} catch (IllegalStateException e) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
package com.rit.canteen.sales.controller;
|
||||
|
||||
import com.rit.canteen.sales.model.DeveloperApp;
|
||||
import com.rit.canteen.sales.repository.DeveloperAppRepository;
|
||||
import com.rit.canteen.sales.repository.DeveloperApiKeyRepository;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/developer-apps")
|
||||
public class DeveloperAppController {
|
||||
|
||||
@Autowired
|
||||
private DeveloperAppRepository appRepository;
|
||||
|
||||
@Autowired
|
||||
private DeveloperApiKeyRepository keyRepository;
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<?> listApps() {
|
||||
UserContext context = getUserContext();
|
||||
if (context == null) {
|
||||
return ResponseEntity.status(401).body(Map.of("error", "Unauthorized"));
|
||||
}
|
||||
List<DeveloperApp> apps = appRepository.findByUserIdAndUserType(context.userId, context.userType);
|
||||
return ResponseEntity.ok(apps);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<?> createApp(@RequestBody Map<String, Object> body) {
|
||||
UserContext context = getUserContext();
|
||||
if (context == null) {
|
||||
return ResponseEntity.status(401).body(Map.of("error", "Unauthorized"));
|
||||
}
|
||||
String name = body.containsKey("name") && body.get("name") != null
|
||||
? body.get("name").toString()
|
||||
: "";
|
||||
String description = body.containsKey("description") && body.get("description") != null
|
||||
? body.get("description").toString()
|
||||
: "";
|
||||
|
||||
if (name.trim().isEmpty()) {
|
||||
return ResponseEntity.badRequest().body(Map.of("error", "App name is required"));
|
||||
}
|
||||
|
||||
DeveloperApp app = new DeveloperApp();
|
||||
app.setName(name);
|
||||
app.setDescription(description);
|
||||
app.setUserId(context.userId);
|
||||
app.setUserType(context.userType);
|
||||
app.setOwnerIdentifier(context.identifier);
|
||||
|
||||
DeveloperApp saved = appRepository.save(app);
|
||||
return ResponseEntity.status(201).body(saved);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@Transactional
|
||||
public ResponseEntity<?> deleteApp(@PathVariable Long id) {
|
||||
UserContext context = getUserContext();
|
||||
if (context == null) {
|
||||
return ResponseEntity.status(401).body(Map.of("error", "Unauthorized"));
|
||||
}
|
||||
Optional<DeveloperApp> appOpt = appRepository.findById(id);
|
||||
if (appOpt.isEmpty()) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
DeveloperApp app = appOpt.get();
|
||||
if (!app.getUserId().equals(context.userId) || !app.getUserType().equals(context.userType)) {
|
||||
return ResponseEntity.status(403).body(Map.of("error", "Unauthorized to delete this App"));
|
||||
}
|
||||
|
||||
// Delete keys associated with this App first
|
||||
keyRepository.deleteByAppId(id);
|
||||
appRepository.delete(app);
|
||||
|
||||
return ResponseEntity.ok(Map.of("success", true, "message", "App and its keys deleted successfully"));
|
||||
}
|
||||
|
||||
// ── Helper UserContext parser ──────────────────────────────────────────
|
||||
|
||||
private UserContext getUserContext() {
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (auth == null || !auth.isAuthenticated()) return null;
|
||||
|
||||
if (auth.getDetails() instanceof Claims claims) {
|
||||
Long userId;
|
||||
Object uid = claims.get("userId");
|
||||
if (uid instanceof Integer) {
|
||||
userId = ((Integer) uid).longValue();
|
||||
} else if (uid instanceof Long) {
|
||||
userId = (Long) uid;
|
||||
} else if (uid != null) {
|
||||
userId = Long.valueOf(uid.toString());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
String type = (String) claims.get("type");
|
||||
String userType = "customer".equals(type) ? "CUSTOMER" : "SYSTEM";
|
||||
String identifier = claims.getSubject();
|
||||
|
||||
return new UserContext(userId, userType, identifier);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class UserContext {
|
||||
final Long userId;
|
||||
final String userType;
|
||||
final String identifier;
|
||||
|
||||
UserContext(Long userId, String userType, String identifier) {
|
||||
this.userId = userId;
|
||||
this.userType = userType;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,9 @@ public class DeveloperApiKey {
|
||||
|
||||
private LocalDateTime lastUsedAt;
|
||||
|
||||
@Column(nullable = true)
|
||||
private Long appId;
|
||||
|
||||
public DeveloperApiKey() {}
|
||||
|
||||
@PrePersist
|
||||
@@ -134,4 +137,12 @@ public class DeveloperApiKey {
|
||||
public void setPermissions(String permissions) {
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public Long getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public void setAppId(Long appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.rit.canteen.sales.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "developer_api_logs")
|
||||
public class DeveloperApiLog {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String endpoint;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String method;
|
||||
|
||||
@Column(nullable = true)
|
||||
private String apiKey;
|
||||
|
||||
@Column(nullable = true)
|
||||
private Long appId;
|
||||
|
||||
@Column(nullable = true)
|
||||
private Long userId;
|
||||
|
||||
@Column(nullable = true)
|
||||
private String userType;
|
||||
|
||||
@Column(nullable = false)
|
||||
private int status;
|
||||
|
||||
@Column(nullable = true)
|
||||
private String clientIp;
|
||||
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime timestamp;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String responseBody;
|
||||
|
||||
public DeveloperApiLog() {}
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
timestamp = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
public void setEndpoint(String endpoint) {
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public String getApiKey() {
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
public void setApiKey(String apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
|
||||
public Long getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public void setAppId(Long appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUserType() {
|
||||
return userType;
|
||||
}
|
||||
|
||||
public void setUserType(String userType) {
|
||||
this.userType = userType;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getClientIp() {
|
||||
return clientIp;
|
||||
}
|
||||
|
||||
public void setClientIp(String clientIp) {
|
||||
this.clientIp = clientIp;
|
||||
}
|
||||
|
||||
public LocalDateTime getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(LocalDateTime timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public String getResponseBody() {
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
public void setResponseBody(String responseBody) {
|
||||
this.responseBody = responseBody;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.rit.canteen.sales.model;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "developer_apps")
|
||||
public class DeveloperApp {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(columnDefinition = "TEXT")
|
||||
private String description;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Long userId;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String userType; // "CUSTOMER"
|
||||
|
||||
@Column(nullable = false)
|
||||
private String ownerIdentifier; // Email or Mobile Number
|
||||
|
||||
@Column(nullable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
public DeveloperApp() {}
|
||||
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
createdAt = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getUserType() {
|
||||
return userType;
|
||||
}
|
||||
|
||||
public void setUserType(String userType) {
|
||||
this.userType = userType;
|
||||
}
|
||||
|
||||
public String getOwnerIdentifier() {
|
||||
return ownerIdentifier;
|
||||
}
|
||||
|
||||
public void setOwnerIdentifier(String ownerIdentifier) {
|
||||
this.ownerIdentifier = ownerIdentifier;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
}
|
||||
@@ -9,4 +9,6 @@ public interface DeveloperApiKeyRepository extends JpaRepository<DeveloperApiKey
|
||||
Optional<DeveloperApiKey> findByApiKey(String apiKey);
|
||||
List<DeveloperApiKey> findByUserIdAndUserType(Long userId, String userType);
|
||||
long countByUserIdAndUserType(Long userId, String userType);
|
||||
List<DeveloperApiKey> findByAppId(Long appId);
|
||||
void deleteByAppId(Long appId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.rit.canteen.sales.repository;
|
||||
|
||||
import com.rit.canteen.sales.model.DeveloperApiLog;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface DeveloperApiLogRepository extends JpaRepository<DeveloperApiLog, Long> {
|
||||
Page<DeveloperApiLog> findByUserIdAndUserType(Long userId, String userType, Pageable pageable);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.rit.canteen.sales.repository;
|
||||
|
||||
import com.rit.canteen.sales.model.DeveloperApp;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import java.util.List;
|
||||
|
||||
public interface DeveloperAppRepository extends JpaRepository<DeveloperApp, Long> {
|
||||
List<DeveloperApp> findByUserIdAndUserType(Long userId, String userType);
|
||||
}
|
||||
@@ -24,12 +24,20 @@ public class DeveloperApiKeyService {
|
||||
|
||||
@Transactional
|
||||
public DeveloperApiKey createKey(Long userId, String userType, String ownerIdentifier, String name, boolean writeAccess, String permissions) {
|
||||
return createKey(userId, userType, ownerIdentifier, name, writeAccess, permissions, null);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public DeveloperApiKey createKey(Long userId, String userType, String ownerIdentifier, String name, boolean writeAccess, String permissions, Long appId) {
|
||||
// Enforce the 3 key limit only for regular CUSTOMER users. SYSTEM users (admin/managers) get unlimited keys.
|
||||
if (!"SYSTEM".equalsIgnoreCase(userType)) {
|
||||
long count = repository.countByUserIdAndUserType(userId, userType);
|
||||
if (count >= 3) {
|
||||
throw new IllegalStateException("Maximum limit of 3 API keys reached");
|
||||
}
|
||||
if (appId == null) {
|
||||
throw new IllegalStateException("App ID is required for Customer keys");
|
||||
}
|
||||
}
|
||||
|
||||
DeveloperApiKey key = new DeveloperApiKey();
|
||||
@@ -39,6 +47,7 @@ public class DeveloperApiKeyService {
|
||||
key.setName(name);
|
||||
key.setWriteAccess(writeAccess);
|
||||
key.setPermissions(permissions);
|
||||
key.setAppId(appId);
|
||||
|
||||
// Generate a secure API key
|
||||
String prefix = writeAccess ? "DEV-W-" : "DEV-";
|
||||
|
||||
Reference in New Issue
Block a user