From e692b3642ee21075224e20bd79385418681852c9 Mon Sep 17 00:00:00 2001 From: muralibasani Date: Mon, 13 Nov 2023 10:39:11 +0100 Subject: [PATCH 1/5] Edit schema request Signed-off-by: muralibasani --- .../controller/SchemaRegistryController.java | 15 + .../controller/TemplateMapController.java | 9 + .../klaw/helpers/db/rdbms/InsertDataJdbc.java | 5 +- .../SchemaRegistryControllerService.java | 41 +- .../static/js/editAvroSchemaUpload.js | 507 +++++++++++++++ .../templates/editSchemaRequest.html | 595 ++++++++++++++++++ .../resources/templates/mySchemaRequests.html | 17 +- .../resources/templates/requestSchema.html | 2 +- 8 files changed, 1185 insertions(+), 6 deletions(-) create mode 100644 core/src/main/resources/static/js/editAvroSchemaUpload.js create mode 100644 core/src/main/resources/templates/editSchemaRequest.html diff --git a/core/src/main/java/io/aiven/klaw/controller/SchemaRegistryController.java b/core/src/main/java/io/aiven/klaw/controller/SchemaRegistryController.java index 03a154186e..fbc5912658 100644 --- a/core/src/main/java/io/aiven/klaw/controller/SchemaRegistryController.java +++ b/core/src/main/java/io/aiven/klaw/controller/SchemaRegistryController.java @@ -18,6 +18,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -203,4 +204,18 @@ public ResponseEntity validateSchema(@RequestBody SchemaRequestMode return ResponseEntity.ok(schemaRegistryControllerService.validateSchema(schemaRequest)); } + + /** + * @param schemaReqId requestId of schema + * @return Schema Request details + */ + @RequestMapping( + value = "/schema/request/{schemaReqId}", + method = RequestMethod.GET, + produces = {MediaType.APPLICATION_JSON_VALUE}) + public ResponseEntity getTopicRequest( + @PathVariable Integer schemaReqId) { + return new ResponseEntity<>( + schemaRegistryControllerService.getSchemaRequest(schemaReqId), HttpStatus.OK); + } } diff --git a/core/src/main/java/io/aiven/klaw/controller/TemplateMapController.java b/core/src/main/java/io/aiven/klaw/controller/TemplateMapController.java index 712a5ebb9a..ecc6284b51 100644 --- a/core/src/main/java/io/aiven/klaw/controller/TemplateMapController.java +++ b/core/src/main/java/io/aiven/klaw/controller/TemplateMapController.java @@ -376,6 +376,15 @@ public String editAclRequest( return checkAuth("editAclRequest.html", request, response, abstractAuthenticationToken); } + @RequestMapping(value = "/editSchemaRequest", method = RequestMethod.GET) + public String editSchemaRequest( + ModelMap model, + HttpServletRequest request, + HttpServletResponse response, + AbstractAuthenticationToken abstractAuthenticationToken) { + return checkAuth("editSchemaRequest.html", request, response, abstractAuthenticationToken); + } + @RequestMapping(value = "/requestConnector", method = RequestMethod.GET) public String requestConnector( ModelMap model, diff --git a/core/src/main/java/io/aiven/klaw/helpers/db/rdbms/InsertDataJdbc.java b/core/src/main/java/io/aiven/klaw/helpers/db/rdbms/InsertDataJdbc.java index 4484ebb9fa..34249c2d36 100644 --- a/core/src/main/java/io/aiven/klaw/helpers/db/rdbms/InsertDataJdbc.java +++ b/core/src/main/java/io/aiven/klaw/helpers/db/rdbms/InsertDataJdbc.java @@ -312,7 +312,10 @@ public synchronized String insertIntoAclsSOT(List acls, boolean isSyncAcls) public synchronized String insertIntoRequestSchema(SchemaRequest schemaRequest) { log.debug("insertIntoRequestSchema {}", schemaRequest.getTopicname()); - schemaRequest.setReq_no(getNextSchemaRequestId("SCHEMA_REQ_ID", schemaRequest.getTenantId())); + if (schemaRequest.getReq_no() == null) { + schemaRequest.setReq_no(getNextSchemaRequestId("SCHEMA_REQ_ID", schemaRequest.getTenantId())); + } + schemaRequest.setSchemafull(schemaRequest.getSchemafull().trim()); schemaRequest.setRequestStatus(RequestStatus.CREATED.value); schemaRequest.setRequesttime(new Timestamp(System.currentTimeMillis())); diff --git a/core/src/main/java/io/aiven/klaw/service/SchemaRegistryControllerService.java b/core/src/main/java/io/aiven/klaw/service/SchemaRegistryControllerService.java index b9ef3d06fd..c6777c3c25 100644 --- a/core/src/main/java/io/aiven/klaw/service/SchemaRegistryControllerService.java +++ b/core/src/main/java/io/aiven/klaw/service/SchemaRegistryControllerService.java @@ -508,7 +508,7 @@ public ApiResponse uploadSchema( .collect(Collectors.toList()); // request status filtering - if (schemaReqs != null) { + if (schemaReqs != null && schemaRequest.getRequestId() == null) { schemaReqs = schemaReqs.stream() .filter( @@ -525,6 +525,7 @@ public ApiResponse uploadSchema( schemaRequest.setRequestor(userName); SchemaRequest schemaRequestDao = new SchemaRequest(); copyProperties(schemaRequest, schemaRequestDao); + schemaRequestDao.setReq_no(schemaRequest.getRequestId()); schemaRequestDao.setRequestOperationType(requestOperationType.value); HandleDbRequests dbHandle = manageDatabase.getHandleDbRequests(); schemaRequestDao.setTenantId(tenantId); @@ -568,6 +569,44 @@ public ApiResponse validateSchema(SchemaRequestModel schemaRequest) throws KlawE } } + public SchemaRequestsResponseModel getSchemaRequest(Integer schemaReqId) { + String userName = getUserName(); + int tenantId = commonUtilsService.getTenantId(userName); + SchemaRequest schemaRequest = + manageDatabase.getHandleDbRequests().getSchemaRequest(schemaReqId, tenantId); + + if (schemaRequest == null) { + return null; + } else { + SchemaRequestsResponseModel schemaRequestsResponseModel = new SchemaRequestsResponseModel(); + copyProperties(schemaRequest, schemaRequestsResponseModel); + schemaRequestsResponseModel.setRequestStatus( + RequestStatus.of(schemaRequest.getRequestStatus())); + schemaRequestsResponseModel.setRequestOperationType( + RequestOperationType.of(schemaRequest.getRequestOperationType())); + // Set kafka env name, id + manageDatabase.getKafkaEnvList(tenantId).stream() + .filter( + kafkaEnv -> { + if (kafkaEnv.getAssociatedEnv() != null) { + return kafkaEnv.getAssociatedEnv().getId().equals(schemaRequest.getEnvironment()); + } + return false; + }) + .findFirst() + .ifPresent( + env -> { + schemaRequestsResponseModel.setEnvironmentName(env.getName()); + schemaRequestsResponseModel.setEnvironment(env.getId()); + }); + + schemaRequestsResponseModel.setTeamname( + manageDatabase.getTeamNameFromTeamId(tenantId, schemaRequest.getTeamId())); + + return schemaRequestsResponseModel; + } + } + private String prettyPrintUglyJsonString(String json) { ObjectMapper mapper = new ObjectMapper(); diff --git a/core/src/main/resources/static/js/editAvroSchemaUpload.js b/core/src/main/resources/static/js/editAvroSchemaUpload.js new file mode 100644 index 0000000000..fcaea185a5 --- /dev/null +++ b/core/src/main/resources/static/js/editAvroSchemaUpload.js @@ -0,0 +1,507 @@ +'use strict' + +// confirmation of delete +// edit +// solution for transaction +// message store / key / gui +var app = angular.module('editSchemaApp',[]); + +app.directive('onReadFile', function ($parse) { + return { + restrict: 'A', + scope: false, + link: function(scope, element, attrs) { + var fn = $parse(attrs.onReadFile); + + element.on('change', function(onChangeEvent) { + var reader = new FileReader(); + + reader.onload = function(onLoadEvent) { + scope.$apply(function() { + fn(scope, {$fileContent:onLoadEvent.target.result}); + }); + }; + + reader.readAsText((onChangeEvent.srcElement || onChangeEvent.target).files[0]); + }); + } + }; +}); + +app.controller("editSchemaCtrl", function($scope, $http, $location, $window) { + + // Set http service defaults + // We force the "Accept" header to be only "application/json" + // otherwise we risk the Accept header being set by default to: + // "application/json; text/plain" and this can result in us + // getting a "text/plain" response which is not able to be + // parsed. + $http.defaults.headers.common['Accept'] = 'application/json'; + + $scope.showSubmitFailed = function(title, text){ + swal({ + title: "", + text: "Request unsuccessful !!", + timer: 2000, + showConfirmButton: false + }); + } + + $scope.handleValidationErrors = function(error){ + if(error.errors != null && error.errors.length > 0){ + $scope.alert = error.errors[0].defaultMessage; + }else if(error.message != null){ + $scope.alert = error.message; + }else if(error.result != null){ + $scope.alert = error.result; + } + else + $scope.alert = "Unable to process the request. Please verify the request or contact our Administrator !!"; + + $scope.alertnote = $scope.alert; + $scope.showAlertToast(); + } + + $scope.showAlertToast = function() { + var x = document.getElementById("alertbar"); + x.className = "show"; + setTimeout(function(){ x.className = x.className.replace("show", ""); }, 2000); + } + + + $scope.loadParams = function() { + var schemaRequestId; + + var sPageURL = window.location.search.substring(1); + var sURLVariables = sPageURL.split('&'); + for (var i = 0; i < sURLVariables.length; i++) + { + var sParameterName = sURLVariables[i].split('='); + if (sParameterName[0] === "schemaRequestId") + { + schemaRequestId = sParameterName[1]; + } + } + + if(schemaRequestId){ + $scope.getMySchemaRequestDetail(schemaRequestId); + } + } + + $scope.getMySchemaRequestDetail = function(schemaRequestId) { + $http({ + method: "GET", + url: "schema/request/" + schemaRequestId, + headers : { 'Content-Type' : 'application/json' } + }).success(function(output) { + $scope.schemaRequestDetail = output; + if(output != null && output !== ''){ + $scope.addSchema = $scope.schemaRequestDetail; + $scope.addSchema.envId = $scope.schemaRequestDetail.environment; + }else{ + $scope.alertnote = "Request not found."; + $scope.showAlertToast(); + $window.location.href = $window.location.origin; + } + + }).error( + function(error) + { + $scope.alert = error; + } + ); + } + + $scope.getEnvDetails = function(envSelected) { + $http({ + method: "GET", + url: "getEnvDetails", + headers : { 'Content-Type' : 'application/json' }, + params: {'envSelected' : envSelected, 'envType' : 'kafka' }, + }).success(function(output) { + $scope.environmentDetails = output; + }).error( + function(error) + { + $scope.alert = error; + } + ); + } + + $scope.cancelRequest = function() { + $window.location.href = $window.location.origin + $scope.dashboardDetails.contextPath + "/browseTopics"; + } + + $scope.showContent = function($fileContent){ + $scope.addSchema.schemafull = $fileContent; + }; + + $scope.submitEditSchemaRequest = function() { + + if(!$scope.addSchema.envId) + { + $scope.alertnote = "Please select a valid environment"; + $scope.showAlertToast(); + return; + } + + if($scope.addSchema.topicname == null || $scope.addSchema.topicname.length === 0) + { + $scope.alertnote = "Please fill in topic name."; + $scope.showAlertToast(); + return; + }else + { + $scope.addSchema.topicname = $scope.addSchema.topicname.trim(); + if($scope.addSchema.topicname.length === 0){ + $scope.alertnote = "Please fill in topic name."; + $scope.showAlertToast(); + return; + } + } + + if(!$scope.addSchema.schemafull) + { + $scope.alertnote = "Please select a valid Avro schema file"; + $scope.showAlertToast(); + return; + } + + if($scope.addSchema.forceRegister === true) { + var forceRegisterString = " Force register for schema selected. This overrides standard schema compatibility."; + if($scope.addSchema.remarks == null) { + $scope.addSchema.remarks = forceRegisterString; + } else { + $scope.addSchema.remarks += forceRegisterString; + } + } + + var serviceInput = {}; + $scope.alert = null; + $scope.alertnote = null; + + serviceInput['environment'] = $scope.addSchema.envId; + serviceInput['topicname'] = $scope.addSchema.topicname; + serviceInput['appname'] = "App"; + serviceInput['remarks'] = $scope.addSchema.remarks; + serviceInput['schemafull'] = $scope.addSchema.schemafull; + serviceInput['schemaversion'] = "1.0"; + serviceInput['requestOperationType'] = $scope.addSchema.requestOperationType; + serviceInput['forceRegister'] = $scope.addSchema.forceRegister; + serviceInput['requestId'] = $scope.addSchema.req_no; + + $http({ + method: "POST", + url: "uploadSchema", + headers : { 'Content-Type' : 'application/json' }, + data: serviceInput + }).success(function(output) { + $scope.alert = "Schema Upload Request : "+output.message; + $scope.addSchema.topicname = ""; + if(output.success){ + swal({ + title: "Awesome !", + text: "Schema Request : " + output.message, + showConfirmButton: true + }).then(function(isConfirm){ + $window.location.href = $window.location.origin + $scope.dashboardDetails.contextPath +"/mySchemaRequests?reqsType=CREATED&schemaCreated=true"; + }); + }else + { + $scope.alert = "Schema Request : " + output.message; + $scope.showSubmitFailed('',''); + } + + }).error( + function(error) + { + if(!error){ + error = "Schema could not be uploaded. Please check schema."; + $scope.alert = error; + $scope.alertnote = error; + $scope.showAlertToast(); + } + else{ + $scope.handleValidationErrors(error); + } + } + ); + + }; + + + $scope.validateSchema = function() { + + if(!$scope.addSchema.envName) + { + $scope.alertnote = "Please select an environment"; + $scope.showAlertToast(); + return; + } + + if($scope.addSchema.topicname == null || $scope.addSchema.topicname.length==0) + { + $scope.alertnote = "Please fill in topic name."; + $scope.showAlertToast(); + return; + }else + { + $scope.addSchema.topicname = $scope.addSchema.topicname.trim(); + if($scope.addSchema.topicname.length==0){ + $scope.alertnote = "Please fill in topic name."; + $scope.showAlertToast(); + return; + } + } + + if(!$scope.addSchema.schemafull) + { + $scope.alertnote = "Please select a valid Avro schema file"; + $scope.showAlertToast(); + return; + } + + var serviceInput = {}; + $scope.alert = null; + $scope.alertnote = null; + + serviceInput['environment'] = $scope.addSchema.envName; + serviceInput['topicname'] = $scope.addSchema.topicname; + serviceInput['appname'] = "App"; + serviceInput['remarks'] = $scope.addSchema.remarks; + serviceInput['schemafull'] = $scope.addSchema.schemafull; + serviceInput['schemaversion'] = "1.0"; + serviceInput['requestOperationType'] = 'CREATE'; + + $http({ + method: "POST", + url: "validate/schema", + headers : { 'Content-Type' : 'application/json' }, + data: serviceInput + }).success(function(output) { + $scope.alert = "Schema Validation Request : "+output.message; + $scope.addSchema.topicname = ""; + if(output.success){ + $scope.validatedSchema = true; + }else + { + $scope.validatedSchema = false; + } + + }).error( + function(error) + { + if(!error){ + error = "Schema could not be Validated. Please check schema."; + $scope.alert = error; + $scope.alertnote = error; + $scope.showAlertToast(); + } + else{ + $scope.handleValidationErrors(error); + } + } + ); + + }; + + + $scope.refreshPage = function(){ + $window.location.reload(); + } + + $scope.getAuth = function() { + $http({ + method: "GET", + url: "getAuth", + headers : { 'Content-Type' : 'application/json' } + }).success(function(output) { + $scope.dashboardDetails = output; + $scope.userlogged = output.username; + $scope.teamname = output.teamname; + $scope.userrole = output.userrole; + $scope.notifications = output.notifications; + $scope.notificationsAcls = output.notificationsAcls; + $scope.notificationsSchemas = output.notificationsSchemas; + $scope.notificationsUsers = output.notificationsUsers; + + if(output.requestItems!='Authorized') + { + swal({ + title: "Not Authorized !", + text: "", + showConfirmButton: true + }).then(function(isConfirm){ + $scope.alertnote = "You are not authorized to request."; + $scope.showAlertToast(); + $window.location.href = $window.location.origin + $scope.dashboardDetails.contextPath + "/index"; + }); + } + + if(output.companyinfo == null){ + $scope.companyinfo = "Company not defined!!"; + } + else + $scope.companyinfo = output.companyinfo; + + if($scope.userlogged != null) + $scope.loggedinuser = "true"; + + $scope.checkSwitchTeams($scope.dashboardDetails.canSwitchTeams, $scope.dashboardDetails.teamId, $scope.userlogged); + $scope.checkPendingApprovals(); + }).error( + function(error) + { + $scope.alert = error; + } + ); + } + + $scope.onSwitchTeam = function() { + var serviceInput = {}; + serviceInput['username'] = $scope.userlogged; + serviceInput['teamId'] = $scope.teamId; + + swal({ + title: "Are you sure?", + text: "You would like to update your team ?", + type: "warning", + showCancelButton: true, + confirmButtonColor: "#DD6B55", + confirmButtonText: "Yes !", + cancelButtonText: "No, cancel please!", + closeOnConfirm: true, + closeOnCancel: true + }).then(function(isConfirm) { + if (isConfirm.value) { + $http({ + method: "POST", + url: "user/updateTeam", + headers : { 'Content-Type' : 'application/json' }, + data: serviceInput + }).success(function (output) { + $scope.alert = "User team update request : "+output.message; + if(output.success){ + swal({ + title: "", + text: "User team update request : "+output.message, + timer: 2000, + showConfirmButton: true + }).then(function(isConfirm){ + $scope.refreshPage(); + }); + }else $scope.showSubmitFailed('',''); + }).error( + function (error) { + $scope.handleValidationErrors(error); + } + ); + } else { + $scope.checkSwitchTeams($scope.dashboardDetails.canSwitchTeams, $scope.dashboardDetails.teamId, $scope.userlogged); + return; + } + }); + } + + $scope.checkSwitchTeams = function(canSwitchTeams, teamId, userId){ + if(canSwitchTeams === 'true'){ + $scope.teamId = parseInt(teamId); + $scope.getSwitchTeamsList(userId); + } + } + + $scope.getSwitchTeamsList = function(userId) { + $http({ + method: "GET", + url: "user/" + userId + "/switchTeamsList", + headers : { 'Content-Type' : 'application/json' } + }).success(function(output) { + $scope.switchTeamsListDashboard = output; + }).error( + function(error) + { + $scope.alert = error; + } + ); + } + + $scope.redirectToPendingReqs = function(redirectPage){ + swal({ + title: "Pending Requests", + text: "Would you like to look at them ?", + type: "info", + showCancelButton: true, + confirmButtonColor: "#DD6B55", + confirmButtonText: "Yes, show me!", + cancelButtonText: "No, later!", + closeOnConfirm: true, + closeOnCancel: true + }).then(function(isConfirm){ + if (isConfirm.value) { + $window.location.href = $window.location.origin + $scope.dashboardDetails.contextPath + "/"+redirectPage; + } else { + return; + } + }); + } + + $scope.checkPendingApprovals = function() { + if($scope.dashboardDetails.pendingApprovalsRedirectionPage === '') + return; + + if(sessionStorage.getItem("pending_reqs_shown") === null){ + $scope.redirectToPendingReqs($scope.dashboardDetails.pendingApprovalsRedirectionPage); + sessionStorage.setItem("pending_reqs_shown", "true"); + } + } + + $scope.logout = function() { + $http({ + method: "POST", + url: "logout", + headers : { 'Content-Type' : 'application/json' } + }).success(function(output) { + $window.location.href = $window.location.origin + $scope.dashboardDetails.contextPath + "/" + "login"; + }).error( + function(error) + { + $window.location.href = $window.location.origin + $scope.dashboardDetails.contextPath + "/" + "login"; + } + ); + } + + $scope.sendMessageToAdmin = function(){ + + if(!$scope.contactFormSubject) + return; + if(!$scope.contactFormMessage) + return; + if($scope.contactFormSubject.trim().length==0) + return; + if($scope.contactFormMessage.trim().length==0) + return; + + $http({ + method: "POST", + url: "sendMessageToAdmin", + headers : { 'Content-Type' : 'application/json' }, + params: {'contactFormSubject' : $scope.contactFormSubject,'contactFormMessage' : $scope.contactFormMessage }, + data: {'contactFormSubject' : $scope.contactFormSubject,'contactFormMessage' : $scope.contactFormMessage } + }).success(function(output) { + $scope.alert = "Message Sent."; + swal({ + title: "", + text: "Message sent.", + timer: 2000, + showConfirmButton: false + }); + }).error( + function(error) + { + $scope.alert = error; + } + ); + } + +} +); \ No newline at end of file diff --git a/core/src/main/resources/templates/editSchemaRequest.html b/core/src/main/resources/templates/editSchemaRequest.html new file mode 100644 index 0000000000..1acc98fe79 --- /dev/null +++ b/core/src/main/resources/templates/editSchemaRequest.html @@ -0,0 +1,595 @@ + + + + + + + + + + + + + + Request Avro Schema | Kafka Self-service Topic Management Portal + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + +
+ + + +
+ +
+ + + + + +
+ + + +
+
+
+ +
+
+
New user interface available
+

+ Check out the new interface for schema + requests. +

+
+
+ +
+
+
+
Notification
+
Notification
+

{{ alert }}

+
+
+
+ + + +
+
+
+ +
+
+
+ + + +

Edit Schema Request

+
+ + + + +
+ +
+ +
+
+
+ + +
+
+ +
+
+ + +
+
+ +
+ + +
+
+
+ + +
+
+
+
+ + +
+
+
+ + +
+
+ +
+ + +
+
+
+ + +
+
+ +
+
+ + + + + Force Register is for use when schema compatibility prevents schema promotion for a must have schema promotion. + + + +
+
+
+ + +
+ + +
+ +
+
{{ alert }}
+
{{ alertnote }}
+
+ + +
+
+
+
+
+
+ + +
+ + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/src/main/resources/templates/mySchemaRequests.html b/core/src/main/resources/templates/mySchemaRequests.html index 9d11f52d23..97153dc664 100644 --- a/core/src/main/resources/templates/mySchemaRequests.html +++ b/core/src/main/resources/templates/mySchemaRequests.html @@ -495,10 +495,17 @@

Shortcuts

Topic : {{ schemaRequest.topicname }}

- - + + + + + + + @@ -539,6 +546,10 @@
Date Requested
{{ schemaRequest.requesttimestrin
Approver
{{ schemaRequest.approver }} +
+
Force Register
+ {{ schemaRequest.forceRegister }} +
Approving Info
diff --git a/core/src/main/resources/templates/requestSchema.html b/core/src/main/resources/templates/requestSchema.html index fca037b468..56ae31d064 100644 --- a/core/src/main/resources/templates/requestSchema.html +++ b/core/src/main/resources/templates/requestSchema.html @@ -468,7 +468,7 @@

Shortcuts

- +
From e0ae672d48438147b55f84dd64fc1ae885e708e8 Mon Sep 17 00:00:00 2001 From: muralibasani Date: Mon, 13 Nov 2023 11:50:49 +0100 Subject: [PATCH 2/5] Add tests, update ts Signed-off-by: muralibasani --- coral/src/services/api.ts | 1 + coral/types/api.d.ts | 89 +++++--- .../controller/SchemaRegistryController.java | 2 +- .../main/resources/templates/execSchemas.html | 5 + .../io/aiven/klaw/TopicAclControllerIT.java | 73 +++++- openapi.yaml | 214 ++++++++++-------- 6 files changed, 247 insertions(+), 137 deletions(-) diff --git a/coral/src/services/api.ts b/coral/src/services/api.ts index 9ae666fec1..a38bbd9d7d 100644 --- a/coral/src/services/api.ts +++ b/coral/src/services/api.ts @@ -34,6 +34,7 @@ const CONTENT_TYPE_JSON = "application/json" as const; const API_BASE_URL = getHTTPBaseAPIUrl(); const API_PATHS = { + getSchemaRequest: "/schema/request/{schemaReqId}", getAclRequest: "/acl/request/{aclRequestId}", approveOperationalRequest: "/operationalRequest/reqId/{reqId}/approve", declineOperationalRequest: "/operationalRequest/reqId/{reqId}/decline", diff --git a/coral/types/api.d.ts b/coral/types/api.d.ts index 4f6f50c73a..5f0435d30e 100644 --- a/coral/types/api.d.ts +++ b/coral/types/api.d.ts @@ -255,6 +255,9 @@ export type paths = { "/schemas/source/{source}/kafkaEnv/{kafkaEnvId}/topic/{topicName}/schemaVersion/{schemaVersion}": { get: operations["getSchemaOfTopicFromSource"]; }; + "/schema/request/{schemaReqId}": { + get: operations["getSchemaRequest"]; + }; "/resetCache": { get: operations["resetCache"]; }; @@ -1067,6 +1070,39 @@ export type components = { schemaVersion?: string; envName?: string; }; + SchemaRequestsResponseModel: { + environment: string; + environmentName: string; + requestor: string; + /** Format: int32 */ + teamId: number; + teamname: string; + /** @enum {string} */ + requestOperationType: "CREATE" | "UPDATE" | "PROMOTE" | "CLAIM" | "DELETE" | "ALL"; + /** @enum {string} */ + requestStatus: "CREATED" | "DELETED" | "DECLINED" | "APPROVED" | "ALL"; + /** Format: date-time */ + requesttime: string; + requesttimestring: string; + currentPage: string; + totalNoPages: string; + allPageNos: string[]; + approvingTeamDetails: string; + approver?: string; + /** Format: date-time */ + approvingtime?: string; + remarks?: string; + appname?: string; + otherParams?: string; + topicname: string; + schemafull: string; + /** Format: int32 */ + req_no: number; + forceRegister: boolean; + schemaversion?: string; + deletable?: boolean; + editable?: boolean; + }; RequestEntityStatusCount: { /** @enum {string} */ requestEntityType?: "TOPIC" | "ACL" | "SCHEMA" | "CONNECTOR" | "OPERATIONAL" | "USER"; @@ -1245,8 +1281,8 @@ export type components = { hasSchema: boolean; /** Format: int32 */ clusterId: number; - highestEnv?: boolean; topicOwner?: boolean; + highestEnv?: boolean; }; TopicBaseConfig: { topicName: string; @@ -1323,6 +1359,7 @@ export type components = { allTopicsCount?: number; /** Format: int32 */ allTopicWarningsCount?: number; + topicsLoadingStatus?: boolean; }; TopicSyncResponseModel: { environment: string; @@ -1455,39 +1492,6 @@ export type components = { kafkaFlavorType?: "APACHE_KAFKA" | "AIVEN_FOR_APACHE_KAFKA" | "CONFLUENT" | "CONFLUENT_CLOUD" | "OTHERS"; remarks?: string; }; - SchemaRequestsResponseModel: { - environment: string; - environmentName: string; - requestor: string; - /** Format: int32 */ - teamId: number; - teamname: string; - /** @enum {string} */ - requestOperationType: "CREATE" | "UPDATE" | "PROMOTE" | "CLAIM" | "DELETE" | "ALL"; - /** @enum {string} */ - requestStatus: "CREATED" | "DELETED" | "DECLINED" | "APPROVED" | "ALL"; - /** Format: date-time */ - requesttime: string; - requesttimestring: string; - currentPage: string; - totalNoPages: string; - allPageNos: string[]; - approvingTeamDetails: string; - approver?: string; - /** Format: date-time */ - approvingtime?: string; - remarks?: string; - appname?: string; - otherParams?: string; - topicname: string; - schemafull: string; - /** Format: int32 */ - req_no: number; - forceRegister: boolean; - schemaversion?: string; - deletable?: boolean; - editable?: boolean; - }; SchemaDetailsPerEnv: { /** Format: int32 */ id: number; @@ -1678,6 +1682,7 @@ export type components = { addDeleteEditClusters: string; addDeleteEditEnvs: string; coralEnabled: string; + coralAvailableForUser: string; adAuthRoleEnabled: string; supportlink: string; myteamtopics: string; @@ -3066,6 +3071,21 @@ export type operations = { }; }; }; + getSchemaRequest: { + parameters: { + path: { + schemaReqId: number; + }; + }; + responses: { + /** @description OK */ + 200: { + content: { + "application/json": components["schemas"]["SchemaRequestsResponseModel"]; + }; + }; + }; + }; resetCache: { responses: { /** @description OK */ @@ -3421,6 +3441,7 @@ export type operations = { currentPage?: string; topicnamesearch?: string; showAllTopics?: string; + resetTopicsCache?: boolean; isBulkOption?: string; }; }; diff --git a/core/src/main/java/io/aiven/klaw/controller/SchemaRegistryController.java b/core/src/main/java/io/aiven/klaw/controller/SchemaRegistryController.java index fbc5912658..e342e715f3 100644 --- a/core/src/main/java/io/aiven/klaw/controller/SchemaRegistryController.java +++ b/core/src/main/java/io/aiven/klaw/controller/SchemaRegistryController.java @@ -213,7 +213,7 @@ public ResponseEntity validateSchema(@RequestBody SchemaRequestMode value = "/schema/request/{schemaReqId}", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE}) - public ResponseEntity getTopicRequest( + public ResponseEntity getSchemaRequest( @PathVariable Integer schemaReqId) { return new ResponseEntity<>( schemaRegistryControllerService.getSchemaRequest(schemaReqId), HttpStatus.OK); diff --git a/core/src/main/resources/templates/execSchemas.html b/core/src/main/resources/templates/execSchemas.html index 826b52e833..978385dec2 100644 --- a/core/src/main/resources/templates/execSchemas.html +++ b/core/src/main/resources/templates/execSchemas.html @@ -560,6 +560,11 @@
Approver
{{ schemaRequest.approver }}
+
+
Force Register
+ {{ schemaRequest.forceRegister }} +
+
Remarks
{{ schemaRequest.remarks }}
diff --git a/core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java b/core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java index 96357df65d..5251530dbb 100644 --- a/core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java +++ b/core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java @@ -43,6 +43,7 @@ import io.aiven.klaw.model.response.KwClustersModelResponse; import io.aiven.klaw.model.response.OperationalRequestsResponseModel; import io.aiven.klaw.model.response.SchemaOverview; +import io.aiven.klaw.model.response.SchemaRequestsResponseModel; import io.aiven.klaw.model.response.TeamModelResponse; import io.aiven.klaw.model.response.TopicOverview; import io.aiven.klaw.model.response.TopicRequestsResponseModel; @@ -1322,6 +1323,46 @@ public void createSchemaRequest() throws Exception { @Order(37) @Test + public void editSchemaRequest() throws Exception { + Integer schemaRequestId = 1001; + String response = getSchemaRequest(schemaRequestId); + + SchemaRequestsResponseModel schemaRequestsResponseModel = + OBJECT_MAPPER.readValue(response, new TypeReference<>() {}); + assertThat(schemaRequestsResponseModel.getForceRegister()).isNull(); + schemaRequestsResponseModel.setForceRegister(Boolean.TRUE); // Set force register to true + + SchemaRequestModel schemaRequest = new SchemaRequestModel(); + schemaRequest.setRequestId(schemaRequestId); + schemaRequest.setTopicname(schemaRequestsResponseModel.getTopicname()); + schemaRequest.setRequestor(schemaRequestsResponseModel.getRequestor()); + schemaRequest.setEnvironment(schemaRequestsResponseModel.getEnvironment()); + schemaRequest.setForceRegister(schemaRequestsResponseModel.getForceRegister()); + schemaRequest.setSchemafull(schemaRequestsResponseModel.getSchemafull()); + schemaRequest.setRequestOperationType(schemaRequestsResponseModel.getRequestOperationType()); + + String jsonReq = OBJECT_MAPPER.writer().writeValueAsString(schemaRequest); + ApiResponse apiResponse = ApiResponse.builder().success(true).build(); + ResponseEntity responseResponseEntity = + new ResponseEntity<>(apiResponse, HttpStatus.OK); + when(clusterApiService.validateSchema(anyString(), anyString(), anyString(), anyInt())) + .thenReturn(responseResponseEntity); + mvc.perform( + MockMvcRequestBuilders.post("/uploadSchema") + .with(user(user1).password(PASSWORD).roles("USER")) + .content(jsonReq) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message", is(ApiResultStatus.SUCCESS.value))); + + response = getSchemaRequest(schemaRequestId); + schemaRequestsResponseModel = OBJECT_MAPPER.readValue(response, new TypeReference<>() {}); + assertThat(schemaRequestsResponseModel.getForceRegister()).isTrue(); + } + + @Order(38) + @Test public void execSchemaRequests() throws Exception { Map registerSchemaCustomResponse = new HashMap<>(); registerSchemaCustomResponse.put("schemaRegistered", true); @@ -1345,7 +1386,7 @@ public void execSchemaRequests() throws Exception { .andExpect(jsonPath("$.message", is(ApiResultStatus.SUCCESS.value))); } - @Order(38) + @Order(39) @Test public void getSchemaOverview() throws Exception { List> aclInfo = new ArrayList<>(utilMethods.getClusterAcls2()); @@ -1370,7 +1411,7 @@ public void getSchemaOverview() throws Exception { assertThat(response.getAllSchemaVersions()).hasSize(1); } - @Order(39) + @Order(40) @Test public void getHistoriesOfTopicAclSchema() throws Exception { List> aclInfo = new ArrayList<>(utilMethods.getClusterAcls2()); @@ -1398,7 +1439,7 @@ public void getHistoriesOfTopicAclSchema() throws Exception { } @Test - @Order(40) + @Order(41) public void createOffsetResetRequestToDelete() throws Exception { String response = createOffsetRequest(); ApiResponse response1 = OBJECT_MAPPER.readValue(response, new TypeReference<>() {}); @@ -1406,7 +1447,7 @@ public void createOffsetResetRequestToDelete() throws Exception { } @Test - @Order(41) + @Order(42) public void getOffsetResetRequests() throws Exception { List operationalRequestList = getOperationalRequestsFromStatus(RequestStatus.CREATED.name()); @@ -1421,7 +1462,7 @@ public void getOffsetResetRequests() throws Exception { } @Test - @Order(42) + @Order(43) public void deleteOffsetRequest() throws Exception { String response = mvc.perform( @@ -1441,7 +1482,7 @@ public void deleteOffsetRequest() throws Exception { } @Test - @Order(43) + @Order(44) public void createOffsetResetRequestToDecline() throws Exception { String response = createOffsetRequest(); ApiResponse response1 = OBJECT_MAPPER.readValue(response, new TypeReference<>() {}); @@ -1452,7 +1493,7 @@ public void createOffsetResetRequestToDecline() throws Exception { } @Test - @Order(44) + @Order(45) public void declineOffsetRequest() throws Exception { String response = mvc.perform( @@ -1473,7 +1514,7 @@ public void declineOffsetRequest() throws Exception { } @Test - @Order(45) + @Order(46) public void createOffsetResetRequestToApprove() throws Exception { String response = createOffsetRequest(); ApiResponse response1 = OBJECT_MAPPER.readValue(response, new TypeReference<>() {}); @@ -1484,7 +1525,7 @@ public void createOffsetResetRequestToApprove() throws Exception { } @Test - @Order(46) + @Order(47) public void approveOffsetRequest() throws Exception { Map> offsetPositionsBeforeAndAfter = UtilMethods.getOffsetsTimingMapMap(); @@ -1511,7 +1552,7 @@ public void approveOffsetRequest() throws Exception { } @Test - @Order(47) + @Order(48) public void editTopicRequestFailureTopicDoesNotExist() throws Exception { TopicRequestModel updateTopicRequest = utilMethods.getTopicUpdateRequestModel(topicId1); updateTopicRequest.setRequestOperationType(RequestOperationType.UPDATE); @@ -1532,6 +1573,18 @@ public void editTopicRequestFailureTopicDoesNotExist() throws Exception { assertThat(str).contains(TOPICS_VLD_ERR_124); } + private String getSchemaRequest(Integer schemaRequestId) throws Exception { + return mvc.perform( + MockMvcRequestBuilders.get("/schema/request/" + schemaRequestId) + .with(user(user1).password(PASSWORD).roles("USER")) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + } + private String createOffsetRequest() throws Exception { ConsumerOffsetResetRequestModel consumerOffsetResetRequestModel = utilMethods.getConsumerOffsetResetRequest(topicId1); diff --git a/openapi.yaml b/openapi.yaml index 145e820ccd..8995e2bd3b 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -2473,6 +2473,33 @@ } } }, + "/schema/request/{schemaReqId}" : { + "get" : { + "tags" : [ "schema-registry-controller" ], + "operationId" : "getSchemaRequest", + "parameters" : [ { + "name" : "schemaReqId", + "in" : "path", + "required" : true, + "schema" : { + "type" : "integer", + "format" : "int32" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SchemaRequestsResponseModel" + } + } + } + } + } + } + }, "/resetCache" : { "get" : { "tags" : [ "server-config-controller" ], @@ -7410,6 +7437,95 @@ } } }, + "SchemaRequestsResponseModel" : { + "properties" : { + "environment" : { + "type" : "string" + }, + "environmentName" : { + "type" : "string" + }, + "requestor" : { + "type" : "string" + }, + "teamId" : { + "type" : "integer", + "format" : "int32" + }, + "teamname" : { + "type" : "string" + }, + "requestOperationType" : { + "type" : "string", + "enum" : [ "CREATE", "UPDATE", "PROMOTE", "CLAIM", "DELETE", "ALL" ] + }, + "requestStatus" : { + "type" : "string", + "enum" : [ "CREATED", "DELETED", "DECLINED", "APPROVED", "ALL" ] + }, + "requesttime" : { + "type" : "string", + "format" : "date-time" + }, + "requesttimestring" : { + "type" : "string" + }, + "currentPage" : { + "type" : "string" + }, + "totalNoPages" : { + "type" : "string" + }, + "allPageNos" : { + "type" : "array", + "items" : { + "type" : "string" + } + }, + "approvingTeamDetails" : { + "type" : "string" + }, + "approver" : { + "type" : "string" + }, + "approvingtime" : { + "type" : "string", + "format" : "date-time" + }, + "remarks" : { + "type" : "string" + }, + "appname" : { + "type" : "string" + }, + "otherParams" : { + "type" : "string" + }, + "topicname" : { + "type" : "string" + }, + "schemafull" : { + "type" : "string" + }, + "req_no" : { + "type" : "integer", + "format" : "int32" + }, + "forceRegister" : { + "type" : "boolean" + }, + "schemaversion" : { + "type" : "string" + }, + "deletable" : { + "type" : "boolean" + }, + "editable" : { + "type" : "boolean" + } + }, + "required" : [ "allPageNos", "approvingTeamDetails", "currentPage", "environment", "environmentName", "forceRegister", "req_no", "requestOperationType", "requestStatus", "requestor", "requesttime", "requesttimestring", "schemafull", "teamId", "teamname", "topicname", "totalNoPages" ] + }, "RequestEntityStatusCount" : { "properties" : { "requestEntityType" : { @@ -7916,10 +8032,10 @@ "type" : "integer", "format" : "int32" }, - "highestEnv" : { + "topicOwner" : { "type" : "boolean" }, - "topicOwner" : { + "highestEnv" : { "type" : "boolean" } }, @@ -8527,95 +8643,6 @@ } } }, - "SchemaRequestsResponseModel" : { - "properties" : { - "environment" : { - "type" : "string" - }, - "environmentName" : { - "type" : "string" - }, - "requestor" : { - "type" : "string" - }, - "teamId" : { - "type" : "integer", - "format" : "int32" - }, - "teamname" : { - "type" : "string" - }, - "requestOperationType" : { - "type" : "string", - "enum" : [ "CREATE", "UPDATE", "PROMOTE", "CLAIM", "DELETE", "ALL" ] - }, - "requestStatus" : { - "type" : "string", - "enum" : [ "CREATED", "DELETED", "DECLINED", "APPROVED", "ALL" ] - }, - "requesttime" : { - "type" : "string", - "format" : "date-time" - }, - "requesttimestring" : { - "type" : "string" - }, - "currentPage" : { - "type" : "string" - }, - "totalNoPages" : { - "type" : "string" - }, - "allPageNos" : { - "type" : "array", - "items" : { - "type" : "string" - } - }, - "approvingTeamDetails" : { - "type" : "string" - }, - "approver" : { - "type" : "string" - }, - "approvingtime" : { - "type" : "string", - "format" : "date-time" - }, - "remarks" : { - "type" : "string" - }, - "appname" : { - "type" : "string" - }, - "otherParams" : { - "type" : "string" - }, - "topicname" : { - "type" : "string" - }, - "schemafull" : { - "type" : "string" - }, - "req_no" : { - "type" : "integer", - "format" : "int32" - }, - "forceRegister" : { - "type" : "boolean" - }, - "schemaversion" : { - "type" : "string" - }, - "deletable" : { - "type" : "boolean" - }, - "editable" : { - "type" : "boolean" - } - }, - "required" : [ "allPageNos", "approvingTeamDetails", "currentPage", "environment", "environmentName", "forceRegister", "req_no", "requestOperationType", "requestStatus", "requestor", "requesttime", "requesttimestring", "schemafull", "teamId", "teamname", "topicname", "totalNoPages" ] - }, "SchemaDetailsPerEnv" : { "properties" : { "id" : { @@ -9147,6 +9174,9 @@ "coralEnabled" : { "type" : "string" }, + "coralAvailableForUser" : { + "type" : "string" + }, "adAuthRoleEnabled" : { "type" : "string" }, @@ -9157,7 +9187,7 @@ "type" : "string" } }, - "required" : [ "adAuthRoleEnabled", "addDeleteEditClusters", "addDeleteEditEnvs", "addEditRoles", "addTeams", "addUser", "approveAtleastOneRequest", "approveDeclineConnectors", "approveDeclineOperationalReqs", "approveDeclineSchemas", "approveDeclineSubscriptions", "approveDeclineTopics", "authenticationType", "broadcastText", "canShutdownKw", "canSwitchTeams", "canUpdatePermissions", "companyinfo", "contextPath", "coralEnabled", "kafka_clusters_count", "kafkaconnect_clusters_count", "klawversion", "manageConnectors", "myteamtopics", "notifications", "notificationsAcls", "notificationsConnectors", "notificationsSchemas", "notificationsUsers", "pendingApprovalsRedirectionPage", "requestItems", "saasEnabled", "schema_clusters_count", "showAddDeleteTenants", "showServerConfigEnvProperties", "supportlink", "syncBackAcls", "syncBackSchemas", "syncBackTopics", "syncConnectors", "syncSchemas", "syncTopicsAcls", "teamId", "teamname", "teamsize", "tenantActiveStatus", "tenantName", "updateServerConfig", "username", "userrole", "viewKafkaConnect", "viewTopics" ] + "required" : [ "adAuthRoleEnabled", "addDeleteEditClusters", "addDeleteEditEnvs", "addEditRoles", "addTeams", "addUser", "approveAtleastOneRequest", "approveDeclineConnectors", "approveDeclineOperationalReqs", "approveDeclineSchemas", "approveDeclineSubscriptions", "approveDeclineTopics", "authenticationType", "broadcastText", "canShutdownKw", "canSwitchTeams", "canUpdatePermissions", "companyinfo", "contextPath", "coralAvailableForUser", "coralEnabled", "kafka_clusters_count", "kafkaconnect_clusters_count", "klawversion", "manageConnectors", "myteamtopics", "notifications", "notificationsAcls", "notificationsConnectors", "notificationsSchemas", "notificationsUsers", "pendingApprovalsRedirectionPage", "requestItems", "saasEnabled", "schema_clusters_count", "showAddDeleteTenants", "showServerConfigEnvProperties", "supportlink", "syncBackAcls", "syncBackSchemas", "syncBackTopics", "syncConnectors", "syncSchemas", "syncTopicsAcls", "teamId", "teamname", "teamsize", "tenantActiveStatus", "tenantName", "updateServerConfig", "username", "userrole", "viewKafkaConnect", "viewTopics" ] }, "KwPropertiesResponse" : { "properties" : { From d02ae365d00be98a5719860bed1d391f6e51fa41 Mon Sep 17 00:00:00 2001 From: muralibasani Date: Mon, 13 Nov 2023 12:34:05 +0100 Subject: [PATCH 3/5] Add validations Signed-off-by: muralibasani --- .../aiven/klaw/error/KlawErrorMessages.java | 4 ++ .../SchemaRegistryControllerService.java | 22 ++++++- .../io/aiven/klaw/TopicAclControllerIT.java | 61 +++++++++++++++---- 3 files changed, 74 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/io/aiven/klaw/error/KlawErrorMessages.java b/core/src/main/java/io/aiven/klaw/error/KlawErrorMessages.java index 4ced502d47..0d9ffec4b8 100644 --- a/core/src/main/java/io/aiven/klaw/error/KlawErrorMessages.java +++ b/core/src/main/java/io/aiven/klaw/error/KlawErrorMessages.java @@ -286,6 +286,10 @@ public class KlawErrorMessages { public static final String SCHEMA_ERR_109 = "Failure. Request Schema environments not configured Settings - tenant config"; + public static final String SCHEMA_ERR_110 = "Failure. Schema request is not in CREATED state"; + + public static final String SCHEMA_ERR_111 = "Failure. Schema request is not owned by you."; + public static final String SERVER_CONFIG_ERR_101 = "Failure. Invalid json / incorrect name values. Check tenant and env details."; diff --git a/core/src/main/java/io/aiven/klaw/service/SchemaRegistryControllerService.java b/core/src/main/java/io/aiven/klaw/service/SchemaRegistryControllerService.java index c6777c3c25..afe8d12d86 100644 --- a/core/src/main/java/io/aiven/klaw/service/SchemaRegistryControllerService.java +++ b/core/src/main/java/io/aiven/klaw/service/SchemaRegistryControllerService.java @@ -9,6 +9,8 @@ import static io.aiven.klaw.error.KlawErrorMessages.SCHEMA_ERR_107; import static io.aiven.klaw.error.KlawErrorMessages.SCHEMA_ERR_108; import static io.aiven.klaw.error.KlawErrorMessages.SCHEMA_ERR_109; +import static io.aiven.klaw.error.KlawErrorMessages.SCHEMA_ERR_110; +import static io.aiven.klaw.error.KlawErrorMessages.SCHEMA_ERR_111; import static io.aiven.klaw.helpers.UtilMethods.updateEnvStatus; import static io.aiven.klaw.model.enums.MailType.*; import static org.springframework.beans.BeanUtils.copyProperties; @@ -513,13 +515,31 @@ public ApiResponse uploadSchema( schemaReqs.stream() .filter( schemaRequest1 -> - "created".equals(schemaRequest1.getRequestStatus()) + RequestStatus.CREATED.value.equals(schemaRequest1.getRequestStatus()) && Objects.equals( schemaRequest1.getTopicname(), schemaRequest.getTopicname())) .collect(Collectors.toList()); if (schemaReqs.size() > 0) { return ApiResponse.notOk(SCHEMA_ERR_107); } + } else if (schemaReqs != null && schemaRequest.getRequestId() != null) { + // edit schema request + Optional optionalSchemaRequest = + schemaReqs.stream() + .filter(schemaReq -> schemaReq.getReq_no().equals(schemaRequest.getRequestId())) + .findFirst(); + + if (optionalSchemaRequest.isPresent()) { + // verify if request is in CREATED state + if (!optionalSchemaRequest.get().getRequestStatus().equals(RequestStatus.CREATED.value)) { + return ApiResponse.notOk(SCHEMA_ERR_110); + } + + // verify if the edit request is being submitted by request owner + if (!optionalSchemaRequest.get().getRequestor().equals(schemaRequest.getRequestor())) { + return ApiResponse.notOk(SCHEMA_ERR_111); + } + } } schemaRequest.setRequestor(userName); diff --git a/core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java b/core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java index 5251530dbb..07dd4997f7 100644 --- a/core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java +++ b/core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java @@ -1,5 +1,6 @@ package io.aiven.klaw; +import static io.aiven.klaw.error.KlawErrorMessages.SCHEMA_ERR_111; import static io.aiven.klaw.error.KlawErrorMessages.TOPICS_VLD_ERR_124; import static io.aiven.klaw.helpers.KwConstants.TENANT_CONFIG_PROPERTY; import static org.assertj.core.api.Assertions.assertThat; @@ -1323,7 +1324,43 @@ public void createSchemaRequest() throws Exception { @Order(37) @Test - public void editSchemaRequest() throws Exception { + public void editSchemaRequestFailureNotOwnerOfRequest() throws Exception { + Integer schemaRequestId = 1001; + String response = getSchemaRequest(schemaRequestId); + + SchemaRequestsResponseModel schemaRequestsResponseModel = + OBJECT_MAPPER.readValue(response, new TypeReference<>() {}); + assertThat(schemaRequestsResponseModel.getForceRegister()).isNull(); + schemaRequestsResponseModel.setForceRegister(Boolean.TRUE); // Set force register to true + + SchemaRequestModel schemaRequest = new SchemaRequestModel(); + schemaRequest.setRequestId(schemaRequestId); + schemaRequest.setTopicname(schemaRequestsResponseModel.getTopicname()); + schemaRequest.setRequestor(user3); + schemaRequest.setEnvironment(schemaRequestsResponseModel.getEnvironment()); + schemaRequest.setForceRegister(schemaRequestsResponseModel.getForceRegister()); + schemaRequest.setSchemafull(schemaRequestsResponseModel.getSchemafull()); + schemaRequest.setRequestOperationType(schemaRequestsResponseModel.getRequestOperationType()); + + String jsonReq = OBJECT_MAPPER.writer().writeValueAsString(schemaRequest); + ApiResponse apiResponse = ApiResponse.builder().success(true).build(); + ResponseEntity responseResponseEntity = + new ResponseEntity<>(apiResponse, HttpStatus.OK); + when(clusterApiService.validateSchema(anyString(), anyString(), anyString(), anyInt())) + .thenReturn(responseResponseEntity); + mvc.perform( + MockMvcRequestBuilders.post("/uploadSchema") + .with(user(user1).password(PASSWORD).roles("USER")) + .content(jsonReq) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message", is(SCHEMA_ERR_111))); + } + + @Order(38) + @Test + public void editSchemaRequestSuccess() throws Exception { Integer schemaRequestId = 1001; String response = getSchemaRequest(schemaRequestId); @@ -1361,7 +1398,7 @@ public void editSchemaRequest() throws Exception { assertThat(schemaRequestsResponseModel.getForceRegister()).isTrue(); } - @Order(38) + @Order(39) @Test public void execSchemaRequests() throws Exception { Map registerSchemaCustomResponse = new HashMap<>(); @@ -1386,7 +1423,7 @@ public void execSchemaRequests() throws Exception { .andExpect(jsonPath("$.message", is(ApiResultStatus.SUCCESS.value))); } - @Order(39) + @Order(40) @Test public void getSchemaOverview() throws Exception { List> aclInfo = new ArrayList<>(utilMethods.getClusterAcls2()); @@ -1411,7 +1448,7 @@ public void getSchemaOverview() throws Exception { assertThat(response.getAllSchemaVersions()).hasSize(1); } - @Order(40) + @Order(41) @Test public void getHistoriesOfTopicAclSchema() throws Exception { List> aclInfo = new ArrayList<>(utilMethods.getClusterAcls2()); @@ -1439,7 +1476,7 @@ public void getHistoriesOfTopicAclSchema() throws Exception { } @Test - @Order(41) + @Order(42) public void createOffsetResetRequestToDelete() throws Exception { String response = createOffsetRequest(); ApiResponse response1 = OBJECT_MAPPER.readValue(response, new TypeReference<>() {}); @@ -1447,7 +1484,7 @@ public void createOffsetResetRequestToDelete() throws Exception { } @Test - @Order(42) + @Order(43) public void getOffsetResetRequests() throws Exception { List operationalRequestList = getOperationalRequestsFromStatus(RequestStatus.CREATED.name()); @@ -1462,7 +1499,7 @@ public void getOffsetResetRequests() throws Exception { } @Test - @Order(43) + @Order(44) public void deleteOffsetRequest() throws Exception { String response = mvc.perform( @@ -1482,7 +1519,7 @@ public void deleteOffsetRequest() throws Exception { } @Test - @Order(44) + @Order(45) public void createOffsetResetRequestToDecline() throws Exception { String response = createOffsetRequest(); ApiResponse response1 = OBJECT_MAPPER.readValue(response, new TypeReference<>() {}); @@ -1493,7 +1530,7 @@ public void createOffsetResetRequestToDecline() throws Exception { } @Test - @Order(45) + @Order(46) public void declineOffsetRequest() throws Exception { String response = mvc.perform( @@ -1514,7 +1551,7 @@ public void declineOffsetRequest() throws Exception { } @Test - @Order(46) + @Order(47) public void createOffsetResetRequestToApprove() throws Exception { String response = createOffsetRequest(); ApiResponse response1 = OBJECT_MAPPER.readValue(response, new TypeReference<>() {}); @@ -1525,7 +1562,7 @@ public void createOffsetResetRequestToApprove() throws Exception { } @Test - @Order(47) + @Order(48) public void approveOffsetRequest() throws Exception { Map> offsetPositionsBeforeAndAfter = UtilMethods.getOffsetsTimingMapMap(); @@ -1552,7 +1589,7 @@ public void approveOffsetRequest() throws Exception { } @Test - @Order(48) + @Order(49) public void editTopicRequestFailureTopicDoesNotExist() throws Exception { TopicRequestModel updateTopicRequest = utilMethods.getTopicUpdateRequestModel(topicId1); updateTopicRequest.setRequestOperationType(RequestOperationType.UPDATE); From 71426b07981e62e14b1e2a1b4362ba092fb9f4fa Mon Sep 17 00:00:00 2001 From: muralibasani Date: Mon, 13 Nov 2023 14:54:04 +0100 Subject: [PATCH 4/5] Fix owner Signed-off-by: muralibasani --- .../aiven/klaw/service/SchemaRegistryControllerService.java | 2 +- core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/io/aiven/klaw/service/SchemaRegistryControllerService.java b/core/src/main/java/io/aiven/klaw/service/SchemaRegistryControllerService.java index afe8d12d86..398741ae8a 100644 --- a/core/src/main/java/io/aiven/klaw/service/SchemaRegistryControllerService.java +++ b/core/src/main/java/io/aiven/klaw/service/SchemaRegistryControllerService.java @@ -453,6 +453,7 @@ public ApiResponse uploadSchema( getPrincipal(), PermissionType.REQUEST_CREATE_SCHEMAS)) { return ApiResponse.NOT_AUTHORIZED; } + schemaRequest.setRequestor(userName); int tenantId = commonUtilsService.getTenantId(getUserName()); Optional schemaEnv = getSchemaEnvFromKafkaEnvId(schemaRequest.getEnvironment()); @@ -542,7 +543,6 @@ public ApiResponse uploadSchema( } } - schemaRequest.setRequestor(userName); SchemaRequest schemaRequestDao = new SchemaRequest(); copyProperties(schemaRequest, schemaRequestDao); schemaRequestDao.setReq_no(schemaRequest.getRequestId()); diff --git a/core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java b/core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java index 07dd4997f7..58ec689661 100644 --- a/core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java +++ b/core/src/test/java/io/aiven/klaw/TopicAclControllerIT.java @@ -1336,7 +1336,7 @@ public void editSchemaRequestFailureNotOwnerOfRequest() throws Exception { SchemaRequestModel schemaRequest = new SchemaRequestModel(); schemaRequest.setRequestId(schemaRequestId); schemaRequest.setTopicname(schemaRequestsResponseModel.getTopicname()); - schemaRequest.setRequestor(user3); + schemaRequest.setRequestor(user2); schemaRequest.setEnvironment(schemaRequestsResponseModel.getEnvironment()); schemaRequest.setForceRegister(schemaRequestsResponseModel.getForceRegister()); schemaRequest.setSchemafull(schemaRequestsResponseModel.getSchemafull()); @@ -1350,7 +1350,7 @@ public void editSchemaRequestFailureNotOwnerOfRequest() throws Exception { .thenReturn(responseResponseEntity); mvc.perform( MockMvcRequestBuilders.post("/uploadSchema") - .with(user(user1).password(PASSWORD).roles("USER")) + .with(user(user2).password(PASSWORD).roles("USER")) .content(jsonReq) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)) From 0646fc8f3453c80d5928c7388dd5339e9ca6b234 Mon Sep 17 00:00:00 2001 From: muralibasani Date: Mon, 13 Nov 2023 15:29:10 +0100 Subject: [PATCH 5/5] Updated remarks Signed-off-by: muralibasani --- .../resources/static/js/editAvroSchemaUpload.js | 15 +++++++++++---- .../static/js/requestAvroSchemaUpload.js | 11 +++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/core/src/main/resources/static/js/editAvroSchemaUpload.js b/core/src/main/resources/static/js/editAvroSchemaUpload.js index fcaea185a5..90ca3568d7 100644 --- a/core/src/main/resources/static/js/editAvroSchemaUpload.js +++ b/core/src/main/resources/static/js/editAvroSchemaUpload.js @@ -167,13 +167,20 @@ app.controller("editSchemaCtrl", function($scope, $http, $location, $window) { return; } + let updatedRemarks; if($scope.addSchema.forceRegister === true) { - var forceRegisterString = " Force register for schema selected. This overrides standard schema compatibility."; + var forceRegisterString = "Force register for schema selected. This overrides standard schema compatibility."; if($scope.addSchema.remarks == null) { - $scope.addSchema.remarks = forceRegisterString; + updatedRemarks = forceRegisterString; } else { - $scope.addSchema.remarks += forceRegisterString; + if(!$scope.addSchema.remarks.includes(forceRegisterString)){ + updatedRemarks = $scope.addSchema.remarks + forceRegisterString; + }else{ + updatedRemarks = $scope.addSchema.remarks; + } } + }else{ + updatedRemarks = $scope.addSchema.remarks; } var serviceInput = {}; @@ -183,7 +190,7 @@ app.controller("editSchemaCtrl", function($scope, $http, $location, $window) { serviceInput['environment'] = $scope.addSchema.envId; serviceInput['topicname'] = $scope.addSchema.topicname; serviceInput['appname'] = "App"; - serviceInput['remarks'] = $scope.addSchema.remarks; + serviceInput['remarks'] = updatedRemarks; serviceInput['schemafull'] = $scope.addSchema.schemafull; serviceInput['schemaversion'] = "1.0"; serviceInput['requestOperationType'] = $scope.addSchema.requestOperationType; diff --git a/core/src/main/resources/static/js/requestAvroSchemaUpload.js b/core/src/main/resources/static/js/requestAvroSchemaUpload.js index 36a30df53b..225a5122ac 100644 --- a/core/src/main/resources/static/js/requestAvroSchemaUpload.js +++ b/core/src/main/resources/static/js/requestAvroSchemaUpload.js @@ -144,13 +144,16 @@ app.controller("requestSchemaCtrl", function($scope, $http, $location, $window) return; } + let updatedRemarks; if($scope.addSchema.forceRegister === true) { - var forceRegisterString = " Force register for schema selected. This overrides standard schema compatibility."; + var forceRegisterString = " Force register for schema selected. This overrides standard schema compatibility."; if($scope.addSchema.remarks == null) { - $scope.addSchema.remarks = forceRegisterString; + updatedRemarks = forceRegisterString; } else { - $scope.addSchema.remarks += forceRegisterString; + updatedRemarks = $scope.addSchema.remarks + forceRegisterString; } + }else{ + updatedRemarks = $scope.addSchema.remarks; } var serviceInput = {}; @@ -160,7 +163,7 @@ app.controller("requestSchemaCtrl", function($scope, $http, $location, $window) serviceInput['environment'] = $scope.addSchema.envId; serviceInput['topicname'] = $scope.addSchema.topicname; serviceInput['appname'] = "App"; - serviceInput['remarks'] = $scope.addSchema.remarks; + serviceInput['remarks'] = updatedRemarks; serviceInput['schemafull'] = $scope.addSchema.schemafull; serviceInput['schemaversion'] = "1.0"; serviceInput['requestOperationType'] = 'CREATE';