66import java .util .HashMap ;
77import java .util .List ;
88import java .util .Map ;
9+ import java .util .Objects ;
910import com .fasterxml .jackson .core .JsonProcessingException ;
1011import com .fasterxml .jackson .databind .JsonNode ;
1112import com .fasterxml .jackson .databind .node .BooleanNode ;
1516import io .sentrius .sso .core .annotations .LimitAccess ;
1617import io .sentrius .sso .core .config .SystemOptions ;
1718import io .sentrius .sso .core .controllers .BaseController ;
19+ import io .sentrius .sso .core .dto .HostGroupDTO ;
20+ import io .sentrius .sso .core .dto .UserPublicKeyDTO ;
1821import io .sentrius .sso .core .exceptions .ZtatException ;
22+ import io .sentrius .sso .core .model .hostgroup .HostGroup ;
1923import io .sentrius .sso .core .model .security .UserType ;
2024import io .sentrius .sso .core .model .security .enums .UserAccessEnum ;
2125import io .sentrius .sso .core .model .users .User ;
2226import io .sentrius .sso .core .dto .UserDTO ;
2327import io .sentrius .sso .core .dto .UserTypeDTO ;
2428import io .sentrius .sso .core .model .users .UserConfig ;
29+ import io .sentrius .sso .core .model .users .UserPublicKey ;
2530import io .sentrius .sso .core .model .users .UserSettings ;
31+ import io .sentrius .sso .core .services .ConfigurationService ;
2632import io .sentrius .sso .core .services .ErrorOutputService ;
2733import io .sentrius .sso .core .services .HostGroupService ;
2834import io .sentrius .sso .core .services .SessionService ;
2935import io .sentrius .sso .core .services .UserCustomizationService ;
36+ import io .sentrius .sso .core .services .UserPublicKeyService ;
3037import io .sentrius .sso .core .services .UserService ;
3138import io .sentrius .sso .core .services .agents .AgentService ;
3239import io .sentrius .sso .core .services .agents .ZeroTrustClientService ;
4552import org .springframework .http .ResponseEntity ;
4653import org .springframework .stereotype .Controller ;
4754import org .springframework .ui .Model ;
55+ import org .springframework .web .bind .annotation .DeleteMapping ;
4856import org .springframework .web .bind .annotation .GetMapping ;
4957import org .springframework .web .bind .annotation .ModelAttribute ;
58+ import org .springframework .web .bind .annotation .PathVariable ;
5059import org .springframework .web .bind .annotation .PostMapping ;
5160import org .springframework .web .bind .annotation .RequestBody ;
5261import org .springframework .web .bind .annotation .RequestMapping ;
@@ -63,6 +72,7 @@ public class UserApiController extends BaseController {
6372 final CryptoService cryptoService ;
6473 private final MessagingUtil messagingUtil ;
6574 final UserCustomizationService userThemeService ;
75+ final UserPublicKeyService userPublicKeyService ;
6676 final ZeroTrustRequestService ztatRequestService ;
6777 final ZeroTrustAccessTokenService ztatService ;
6878 final AgentService agentService ;
@@ -87,6 +97,7 @@ protected UserApiController(
8797 HostGroupService hostGroupService , CryptoService cryptoService ,
8898 MessagingUtil messagingUtil ,
8999 UserCustomizationService userThemeService ,
100+ UserPublicKeyService userPublicKeyService ,
90101 SessionService sessionService ,
91102 ZeroTrustRequestService ztatRequestService ,
92103 ZeroTrustAccessTokenService ztatService , AgentService agentService ,
@@ -97,6 +108,7 @@ protected UserApiController(
97108 this .cryptoService = cryptoService ;
98109 this .messagingUtil = messagingUtil ;
99110 this .userThemeService = userThemeService ;
111+ this .userPublicKeyService = userPublicKeyService ;
100112 this .sessionService = sessionService ;
101113 this .ztatRequestService = ztatRequestService ;
102114 this .ztatService = ztatService ;
@@ -428,5 +440,131 @@ private List<Map<String, Object>> getAgentSessionDurations() {
428440 return agentSessions ;
429441 }
430442
443+ // Public Key Management Endpoints
444+
445+ @ GetMapping ("/publickeys" )
446+ public ResponseEntity <List <UserPublicKeyDTO >> getUserPublicKeys (HttpServletRequest request ,
447+ HttpServletResponse response ) {
448+ var user = userService .getOperatingUser (request , response , null );
449+ var publicKeys = userPublicKeyService .getPublicKeysForUser (user .getId ());
450+ List <UserPublicKeyDTO > publicKeyDTOs = new ArrayList <>();
451+ for (UserPublicKey key : publicKeys ) {
452+ UserPublicKeyDTO dto = UserPublicKeyDTO .builder ().build ();
453+ //dto.setId(key.getId());
454+ dto .setKeyName (key .getKeyName ());
455+ dto .setKeyType (key .getKeyType ());
456+ dto .setPublicKey (key .getPublicKey ());
457+ dto .setIsEnabled (key .getIsEnabled ());
458+ if (key .getHostGroup () != null ) {
459+ dto .setHostGroup ( HostGroupDTO .builder ().groupId (key .getHostGroup ().getId ()).build ());
460+ //dto.setHostGroupName(key.getHostGroup().getName());
461+ }
462+ publicKeyDTOs .add (dto );
463+ }
464+ return ResponseEntity .ok (publicKeyDTOs );
465+ }
466+
467+ @ PostMapping ("/publickeys" )
468+ public ResponseEntity <ObjectNode > addPublicKey (HttpServletRequest request , HttpServletResponse response , @ RequestBody
469+ UserPublicKeyDTO publicKey ) {
470+ ObjectNode node = JsonUtil .MAPPER .createObjectNode ();
471+ try {
472+
473+ HostGroup hostGroup = hostGroupService .getHostGroup (publicKey .getHostGroup ().getGroupId ());
474+
475+
476+ UserPublicKey key = new UserPublicKey ();
477+ key .setKeyName (publicKey .getKeyName ());
478+ key .setKeyType (publicKey .getKeyType ());
479+ key .setPublicKey (publicKey .getPublicKey ());
480+ key .setIsEnabled (publicKey .getIsEnabled ());
481+ if (null != hostGroup ) {
482+ key .setHostGroup (hostGroup );
483+ }
484+ var user = userService .getOperatingUser (request , response , null );
485+ key .setUser (user );
486+
487+ if (key .getCreatedAt () == null ) {
488+ key .setCreatedAt (new java .sql .Timestamp (System .currentTimeMillis ()));
489+ }
490+
491+ var savedKey = userPublicKeyService .addPublicKey (key );
492+ node .put ("status" , "Public key successfully added" );
493+ node .put ("id" , savedKey .getId ());
494+ return ResponseEntity .ok (node );
495+ } catch (Exception e ) {
496+ log .error ("Error adding public key" , e );
497+ node .put ("status" , "Error adding public key" );
498+ return ResponseEntity .internalServerError ().body (node );
499+ }
500+ }
501+
502+ @ PostMapping ("/publickeys/{keyId}/assign" )
503+ public ResponseEntity <ObjectNode > assignPublicKeyToHostGroup (
504+ HttpServletRequest request , HttpServletResponse response ,
505+ @ PathVariable Long keyId , @ RequestParam Long hostGroupId ) {
506+ ObjectNode node = JsonUtil .MAPPER .createObjectNode ();
507+ try {
508+ var user = userService .getOperatingUser (request , response , null );
509+ var publicKeyOpt = userPublicKeyService .getPublicKeyById (keyId );
510+
511+ if (publicKeyOpt .isEmpty ()) {
512+ node .put ("status" , "Public key not found" );
513+ return ResponseEntity .status (HttpStatus .NOT_FOUND ).body (node );
514+ }
515+
516+ var publicKey = publicKeyOpt .get ();
517+
518+ // Verify the key belongs to the current user
519+ if (!publicKey .getUser ().getId ().equals (user .getId ())) {
520+ node .put ("status" , "Unauthorized" );
521+ return ResponseEntity .status (HttpStatus .FORBIDDEN ).body (node );
522+ }
523+
524+ var hostGroup = hostGroupService .getHostGroup (hostGroupId );
525+ publicKey .setHostGroup (hostGroup );
526+ userPublicKeyService .addPublicKey (publicKey );
527+
528+ node .put ("status" , "Public key successfully assigned to host group" );
529+ return ResponseEntity .ok (node );
530+ } catch (Exception e ) {
531+ log .error ("Error assigning public key to host group" , e );
532+ node .put ("status" , "Error assigning public key to host group" );
533+ return ResponseEntity .internalServerError ().body (node );
534+ }
535+ }
536+
537+ @ DeleteMapping ("/publickeys/{keyId}" )
538+ public ResponseEntity <ObjectNode > deletePublicKey (
539+ HttpServletRequest request , HttpServletResponse response ,
540+ @ PathVariable Long keyId ) {
541+ ObjectNode node = JsonUtil .MAPPER .createObjectNode ();
542+ try {
543+ var user = userService .getOperatingUser (request , response , null );
544+ var publicKeyOpt = userPublicKeyService .getPublicKeyById (keyId );
545+
546+ if (publicKeyOpt .isEmpty ()) {
547+ node .put ("status" , "Public key not found" );
548+ return ResponseEntity .status (HttpStatus .NOT_FOUND ).body (node );
549+ }
550+
551+ var publicKey = publicKeyOpt .get ();
552+
553+ // Verify the key belongs to the current user
554+ if (!publicKey .getUser ().getId ().equals (user .getId ())) {
555+ node .put ("status" , "Unauthorized" );
556+ return ResponseEntity .status (HttpStatus .FORBIDDEN ).body (node );
557+ }
558+
559+ userPublicKeyService .deletePublicKey (keyId );
560+ node .put ("status" , "Public key successfully deleted" );
561+ return ResponseEntity .ok (node );
562+ } catch (Exception e ) {
563+ log .error ("Error deleting public key" , e );
564+ node .put ("status" , "Error deleting public key" );
565+ return ResponseEntity .internalServerError ().body (node );
566+ }
567+ }
568+
431569}
432570
0 commit comments