From 8f3165fdbbb20ae6c50682aaffd76927f023d27f Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 13 Apr 2022 14:29:24 +0530 Subject: [PATCH 001/105] Issue #SB-28950 feat: Elasticsearch 6.8.22 upgrade for microservices --- search-api/search-core/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/search-api/search-core/pom.xml b/search-api/search-core/pom.xml index a68a641e4..f33636eb5 100644 --- a/search-api/search-core/pom.xml +++ b/search-api/search-core/pom.xml @@ -67,12 +67,12 @@ org.elasticsearch elasticsearch - 6.2.4 + 6.8.22 org.elasticsearch.client elasticsearch-rest-high-level-client - 6.2.4 + 6.8.22 junit From d7037be2c6d3cfffe11edcf722183fd36cdecbda Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 13 Apr 2022 14:36:58 +0530 Subject: [PATCH 002/105] Issue #SB-28950 feat: Elasticsearch 6.8.22 upgrade for microservices --- .../java/org/sunbird/search/client/ElasticSearchUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java index cc031b378..a43ab09b9 100644 --- a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java +++ b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java @@ -11,14 +11,14 @@ import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.apache.http.util.EntityUtils; +import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.indices.CreateIndexResponse; import org.sunbird.search.util.SearchConstants; import org.sunbird.telemetry.logger.TelemetryManager; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; -import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; -import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.delete.DeleteRequest; @@ -229,7 +229,7 @@ public static void deleteDocumentsByQuery(QueryBuilder query, String indexName, } public static void deleteIndex(String indexName) throws InterruptedException, ExecutionException, IOException { - DeleteIndexResponse response = getClient(indexName).indices().delete(new DeleteIndexRequest(indexName)); + AcknowledgedResponse response = getClient(indexName).indices().delete(new DeleteIndexRequest(indexName)); esClient.remove(indexName); TelemetryManager.log("Deleted Index" + indexName + " : " + response.isAcknowledged()); } From 26bd671e0b3f93638f7fee051053e320177ff26f Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 13 Apr 2022 15:00:32 +0530 Subject: [PATCH 003/105] Issue #SB-28950 feat: Elasticsearch 6.8.22 upgrade for microservices --- vmsetup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vmsetup.sh b/vmsetup.sh index ef8a0094c..83b01344c 100644 --- a/vmsetup.sh +++ b/vmsetup.sh @@ -1,8 +1,8 @@ #!/bin/bash sudo apt update sudo apt install redis-server -y -curl -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.2.deb -sudo dpkg -i elasticsearch-6.3.2.deb +curl -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.8.22.deb +sudo dpkg -i elasticsearch-6.8.22.deb sudo service elasticsearch start sudo service elasticsearch status # This should go to the test cases - Start From ee96056459edbcbb9fe5bd5f56d63bd6c856da33 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 21 Apr 2022 10:47:30 +0530 Subject: [PATCH 004/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- .../org/sunbird/content/dial/DIALErrors.scala | 2 + .../sunbird/content/dial/DIALManager.scala | 132 +++++++++++++++--- .../src/test/resources/application.conf | 1 + .../content-service/conf/application.conf | 1 + 4 files changed, 120 insertions(+), 16 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala index 8d70cfc7c..53fa49388 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala @@ -5,6 +5,7 @@ object DIALErrors { //Error Codes val ERR_DIALCODE_LINK_REQUEST: String = "ERR_DIALCODE_LINK_REQUEST" val ERR_DIALCODE_LINK: String = "ERR_DIALCODE_LINK" + val ERR_DUPLICATE_DIAL_CODES: String = "ERR_DUPLICATE_DIAL_CODES" //Error Messages val ERR_INVALID_REQ_MSG: String = "Invalid Request! Please Provide Valid Request." @@ -13,4 +14,5 @@ object DIALErrors { val ERR_DIAL_NOT_FOUND_MSG: String = "DIAL Code Not Found With Id(s): " val ERR_CONTENT_NOT_FOUND_MSG: String = "Content Not Found With Id(s): " val ERR_SERVER_ERROR_MSG: String = "Something Went Wrong While Processing Your Request. Please Try Again After Sometime!" + val ERR_DUPLICATE_DIAL_CODES_MSG: String = "QR Code should not be linked to multiple contents. Please validate: " } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 487ac475c..06d047c25 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -3,21 +3,25 @@ package org.sunbird.content.dial import org.apache.commons.lang3.StringUtils import org.sunbird.common.Platform import org.sunbird.common.dto.{Request, Response, ResponseHandler} -import org.sunbird.common.exception.{ClientException, ErrorCodes, ResourceNotFoundException, ResponseCode, ServerException} +import org.sunbird.common.exception._ +import org.sunbird.content.util.ContentConstants import org.sunbird.graph.OntologyEngineContext import org.sunbird.graph.dac.model.Node import org.sunbird.graph.nodes.DataNode +import org.sunbird.graph.utils.ScalaJsonUtils +import org.sunbird.managers.HierarchyManager + import java.util -import scala.collection.immutable.HashMap import scala.collection.JavaConverters._ +import scala.collection.immutable.{HashMap, Map} import scala.concurrent.{ExecutionContext, Future} object DIALManager { - val DIAL_SEARCH_API_URL = Platform.config.getString("dial_service.api.base_url") + "/dialcode/v3/search" - val DIAL_API_AUTH_KEY = "Bearer " + Platform.config.getString("dial_service.api.auth_key") - val PASSPORT_KEY = Platform.config.getString("graph.passport.key.base") + val DIAL_SEARCH_API_URL: String = Platform.config.getString("dial_service.api.base_url") + Platform.config.getString("dial_service.api.search") + val DIAL_API_AUTH_KEY: String = "Bearer " + Platform.config.getString("dial_service.api.auth_key") + val PASSPORT_KEY: String = Platform.config.getString("graph.passport.key.base") def link(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { val linkType: String = request.getContext.getOrDefault(DIALConstants.LINK_TYPE, DIALConstants.CONTENT).asInstanceOf[String] @@ -52,13 +56,13 @@ object DIALManager { def validateAndGetRequestMap(channelId: String, requestList: List[Map[String, List[String]]])(implicit oec:OntologyEngineContext): Map[String, List[String]] = { var reqMap = HashMap[String, List[String]]() requestList.foreach(req => { - val contents: List[String] = req.get(DIALConstants.IDENTIFIER).get - val dialcodes: List[String] = req.get(DIALConstants.DIALCODE).get + val contents: List[String] = req(DIALConstants.IDENTIFIER) + val dialcodes: List[String] = req(DIALConstants.DIALCODE) validateReqStructure(dialcodes, contents) contents.foreach(id => reqMap += (id -> dialcodes)) }) if (Platform.getBoolean("content.link_dialcode.validation", true)) { - val dials = requestList.collect { case m if m.get(DIALConstants.DIALCODE).nonEmpty => m.get(DIALConstants.DIALCODE).get }.flatten + val dials = requestList.collect { case m if m.contains(DIALConstants.DIALCODE) => m(DIALConstants.DIALCODE) }.flatten validateDialCodes(channelId, dials) } reqMap @@ -73,7 +77,7 @@ object DIALManager { } def validateDialCodes(channelId: String, dialcodes: List[String])(implicit oec: OntologyEngineContext): Boolean = { - if (!dialcodes.isEmpty) { + if (dialcodes.nonEmpty) { val reqMap = new util.HashMap[String, AnyRef]() {{ put(DIALConstants.REQUEST, new util.HashMap[String, AnyRef]() {{ put(DIALConstants.SEARCH, new util.HashMap[String, AnyRef]() {{ @@ -81,7 +85,8 @@ object DIALManager { }}) }}) }} - val headerParam = HashMap[String, String](DIALConstants.X_CHANNEL_ID -> channelId, DIALConstants.AUTHORIZATION -> DIAL_API_AUTH_KEY).asJava + val headerParam = new util.HashMap[String, String]{put(DIALConstants.X_CHANNEL_ID, channelId); put(DIALConstants.AUTHORIZATION, DIAL_API_AUTH_KEY);} + val searchResponse = oec.httpUtil.post(DIAL_SEARCH_API_URL, reqMap, headerParam) if (searchResponse.getResponseCode.toString == "OK") { val result = searchResponse.getResult @@ -101,7 +106,7 @@ object DIALManager { validateContents(requestMap, reqContext).map(result => { val futureList: List[Future[Node]] = requestMap.filter(x => !result.contains(x._1)).map(map => { val updateReqMap = new util.HashMap[String, AnyRef]() {{ - val dials: util.List[String] = if (!map._2.isEmpty) map._2.asJava else new util.ArrayList[String]() + val dials: util.List[String] = if (map._2.nonEmpty) map._2.asJava else new util.ArrayList[String]() put(DIALConstants.DIALCODES, dials) put(DIALConstants.VERSION_KEY, PASSPORT_KEY) }} @@ -116,11 +121,62 @@ object DIALManager { }).flatMap(f => f) } - //TODO: Complete the implementation - def linkCollection(objectId: String, requestMap: Map[String, List[String]], getContext: util.Map[String, AnyRef])(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - Future { - ResponseHandler.OK() - } + def linkCollection(objectId: String, requestMap: Map[String, List[String]], reqContext: util.Map[String, AnyRef])(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { + val request = new Request() + request.setContext(reqContext) + request.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) + request.getContext.put(ContentConstants.VERSION, ContentConstants.SCHEMA_VERSION) + request.put(ContentConstants.ROOT_ID, objectId) + request.put(ContentConstants.MODE, "edit") + + val req = new Request(request) + req.put("identifier", request.get("rootId").asInstanceOf[String]) + req.put("mode", request.get("mode").asInstanceOf[String]) + DataNode.read(req).flatMap(rootNode => { + HierarchyManager.getHierarchy(request).flatMap(getHierarchyResponse => { + val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] + val childrenHierarchy = collectionHierarchy.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]] + val updatedChildrenHierarchy = updateChildrenHierarchy(childrenHierarchy, requestMap) + val childrenDIALMap = getChildrenDIALMap(updatedChildrenHierarchy, requestMap) + val consolidatedUnitDIALMap = if (!requestMap.contains(objectId)) childrenDIALMap else childrenDIALMap ++ Map(objectId -> requestMap(objectId)) + + val duplicateDIALCodes: Map[String, Set[String]] = validateDuplicateDIALCodes(consolidatedUnitDIALMap.filter(rec => rec._2.asInstanceOf[List[String]].nonEmpty)) + if (duplicateDIALCodes.nonEmpty) + throw new ClientException(DIALErrors.ERR_DUPLICATE_DIAL_CODES, DIALErrors.ERR_DUPLICATE_DIAL_CODES_MSG + duplicateDIALCodes) + + val updatedHierarchy = new java.util.HashMap[String, AnyRef]() + updatedHierarchy.put("identifier", objectId) + updatedHierarchy.put("children", updatedChildrenHierarchy.asJava) + + val hierarchyReq = new Request(request) + hierarchyReq.put("hierarchy", ScalaJsonUtils.serialize(updatedHierarchy)) + hierarchyReq.put("identifier", rootNode.getIdentifier) + oec.graphService.saveExternalProps(hierarchyReq).flatMap(rec => if(requestMap.contains(objectId)) { + val updateReq = new Request(request) + updateReq.put("identifier", rootNode.getIdentifier) + val rootNodeMetadata = rootNode.getMetadata + rootNodeMetadata.remove("discussionForum") + rootNodeMetadata.remove("credentials") + rootNodeMetadata.remove("trackable") + + if(rootNodeMetadata.containsKey("dialcodes")) + rootNodeMetadata.remove("dialcodes") + + if(requestMap(objectId).isEmpty) + updateReq.put(DIALConstants.DIALCODES, null) + else + updateReq.put(DIALConstants.DIALCODES, requestMap(objectId).toArray[String]) + + updateReq.getRequest.putAll(rootNodeMetadata) + + DataNode.update(updateReq).flatMap(response => { + getResponseCollectionLink(requestMap, consolidatedUnitDIALMap.keySet.toList, requestMap.keySet.diff(consolidatedUnitDIALMap.keySet).toList) + }) + } else { + getResponseCollectionLink(requestMap, consolidatedUnitDIALMap.keySet.toList, requestMap.keySet.diff(consolidatedUnitDIALMap.keySet).toList) + }) + }) + }) } def validateContents(requestMap: Map[String, List[String]], reqContext: util.Map[String, AnyRef])(implicit ec: ExecutionContext, oec:OntologyEngineContext): Future[List[String]] = { @@ -149,4 +205,48 @@ object DIALManager { }) } + def getResponseCollectionLink(requestMap: Map[String, List[String]], updatedUnits: List[String], invalidIds: List[String])(implicit ec: ExecutionContext): Future[Response] = { + val response = if (requestMap.keySet.size == updatedUnits.size) + ResponseHandler.OK + else if (invalidIds.nonEmpty && updatedUnits.isEmpty) + ResponseHandler.ERROR(ResponseCode.RESOURCE_NOT_FOUND, DIALErrors.ERR_DIALCODE_LINK, DIALErrors.ERR_CONTENT_NOT_FOUND_MSG + invalidIds.asJava) + else + ResponseHandler.ERROR(ResponseCode.PARTIAL_SUCCESS, DIALErrors.ERR_DIALCODE_LINK, DIALErrors.ERR_CONTENT_NOT_FOUND_MSG + invalidIds.asJava) + + Future(response) + } + + def updateChildrenHierarchy(childrenHierarchy: util.List[util.Map[String, AnyRef]], requestMap: Map[String, List[String]]): List[util.Map[String, AnyRef]] = { + childrenHierarchy.asScala.toList.map(child => { + if (requestMap.contains(child.get("identifier").toString) && StringUtils.equalsIgnoreCase("Parent", child.get("visibility").toString)) { + if (requestMap.getOrElse(child.get("identifier").toString, List.empty).nonEmpty && requestMap(child.get("identifier").toString).exists(rec => rec.trim.nonEmpty)) + child.put("dialcodes", requestMap(child.get("identifier").toString)) + else + child.remove("dialcodes") + } + if(child.get("children")!=null) + updateChildrenHierarchy(child.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]], requestMap) + child + }) + } + + def getChildrenDIALMap(childrenHierarchy: List[util.Map[String, AnyRef]], requestMap: Map[String, List[String]]): Map[String, AnyRef] = { + childrenHierarchy.map(child => { + val subChildrenDIALMap = if(child.get("children")!=null) + getChildrenDIALMap(child.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList, requestMap) + else Map.empty[String, String] + + val childDIALMap = if(requestMap.contains(child.get("identifier").toString) && child.get("dialcodes")!=null) + Map(child.get("identifier").toString -> child.get("dialcodes")) + else if(requestMap.contains(child.get("identifier").toString)) + Map(child.get("identifier").toString -> List.empty) + else Map.empty + + subChildrenDIALMap ++ childDIALMap + }).filter(msg => msg.nonEmpty).flatten.toMap[String, AnyRef] + } + + def validateDuplicateDIALCodes(unitDIALCodesMap: Map[String, AnyRef]): Map[String, Set[String]] = { + unitDIALCodesMap.groupBy(_._2).collect { case (key, group: Map[String, AnyRef]) if group.size > 1 => (key.asInstanceOf[List[String]].head, group.keySet) } + } } diff --git a/content-api/content-actors/src/test/resources/application.conf b/content-api/content-actors/src/test/resources/application.conf index 06d8e8d15..aa9400e59 100644 --- a/content-api/content-actors/src/test/resources/application.conf +++ b/content-api/content-actors/src/test/resources/application.conf @@ -495,6 +495,7 @@ dial_service { api { base_url = "https://qa.ekstep.in/api" auth_key = "auth_key" + search = "/dialcode/v1/search" } } content.link_dialcode.validation=true diff --git a/content-api/content-service/conf/application.conf b/content-api/content-service/conf/application.conf index 0e0c9a150..b1c49e9c4 100644 --- a/content-api/content-service/conf/application.conf +++ b/content-api/content-service/conf/application.conf @@ -603,6 +603,7 @@ dial_service { api { base_url = "https://qa.ekstep.in/api" auth_key = "auth_key" + search = "/dialcode/v1/search" } } content.link_dialcode.validation=true From 97ebd097f5d5d3b2f37ba87a15177bc367c9750a Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 21 Apr 2022 11:30:46 +0530 Subject: [PATCH 005/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- search-api/search-core/pom.xml | 5 ----- .../java/org/sunbird/search/client/ElasticSearchUtil.java | 6 +++--- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/search-api/search-core/pom.xml b/search-api/search-core/pom.xml index f33636eb5..fbdf374ff 100644 --- a/search-api/search-core/pom.xml +++ b/search-api/search-core/pom.xml @@ -64,11 +64,6 @@ 2.4 jdk15 - - org.elasticsearch - elasticsearch - 6.8.22 - org.elasticsearch.client elasticsearch-rest-high-level-client diff --git a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java index a43ab09b9..cef61b0a6 100644 --- a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java +++ b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java @@ -12,7 +12,7 @@ import org.apache.http.client.config.RequestConfig; import org.apache.http.util.EntityUtils; import org.elasticsearch.action.support.master.AcknowledgedResponse; -import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.*; import org.elasticsearch.client.indices.CreateIndexResponse; import org.sunbird.search.util.SearchConstants; import org.sunbird.telemetry.logger.TelemetryManager; @@ -228,8 +228,8 @@ public static void deleteDocumentsByQuery(QueryBuilder query, String indexName, TelemetryManager.log("Deleted Documents by Query" + EntityUtils.toString(response.getEntity())); } - public static void deleteIndex(String indexName) throws InterruptedException, ExecutionException, IOException { - AcknowledgedResponse response = getClient(indexName).indices().delete(new DeleteIndexRequest(indexName)); + public static void deleteIndex(String indexName) throws IOException { + AcknowledgedResponse response = getClient(indexName).indices().delete(new DeleteIndexRequest(indexName), RequestOptions.DEFAULT); esClient.remove(indexName); TelemetryManager.log("Deleted Index" + indexName + " : " + response.isAcknowledged()); } From 1808b920d55306ea42bd5cf24023400bdf961090 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 21 Apr 2022 11:32:58 +0530 Subject: [PATCH 006/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- .../content/dial/DIALManagerTest.scala | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index 6cfa80930..675577eee 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -107,20 +107,19 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory val input = new util.ArrayList[String]() val result:List[String] = DIALManager.getList(input) assert(result.isEmpty) - assert(result.size==0) } "validateAndGetRequestMap with valid input" should "return the request map" in { (oec.httpUtil _).expects().returns(httpUtil) - (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse) + (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse()) val input = getRequestData() val result = DIALManager.validateAndGetRequestMap("test", input) assert(result.nonEmpty) assert(result.size==5) - assert(result.get("do_88888").get.contains("L4A6W8")) - assert(result.get("do_88888").get.contains("D2E1J9")) - assert(result.get("do_2222").get.size==1) - assert(result.get("do_2222").get.contains("R4X2P2")) + assert(result("do_88888").contains("L4A6W8")) + assert(result("do_88888").contains("D2E1J9")) + assert(result("do_2222").size==1) + assert(result("do_2222").contains("R4X2P2")) } "validateReqStructure with valid request" should "not throw any exception" in { @@ -175,7 +174,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory "link DIAL with valid request for content" should "update the contents successfully" in { (oec.httpUtil _).expects().returns(httpUtil) (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse) + (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getLinkDIALSearchResponse) (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(getNodes())).noMoreThanOnce() val nodes: util.List[Node] = getCategoryNode() @@ -185,8 +184,10 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode("do_1111"))) (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) val request = getContentDIALRequest() - val resFuture = DIALManager.link(request) - resFuture.map(result => { + + println("DIALManagerTest:: link content:: request:: " + request) + + DIALManager.link(request).map(result => { assert(result.getResponseCode.toString=="OK") }) } @@ -195,6 +196,9 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory (oec.httpUtil _).expects().returns(httpUtil) (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse) val request = getCollectionDIALRequest() + + println("DIALManagerTest:: link collection:: request:: " + request) + val response = DIALManager.link(request) response.map(result => { assert(result.getResponseCode.toString=="OK") @@ -206,6 +210,11 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory JsonUtils.deserialize(resString, classOf[Response]) } + def getLinkDIALSearchResponse():Response = { + val resString = "{\n \"id\": \"sunbird.dialcode.search\",\n \"ver\": \"3.0\",\n \"ts\": \"2020-04-21T19:39:14ZZ\",\n \"params\": {\n \"resmsgid\": \"1dfcc25b-6c37-49f8-a6c3-7185063e8752\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"dialcodes\": [\n {\n \"dialcode_index\": 7609876,\n \"identifier\": \"N4Z7D5\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.603+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n } ],\n \"count\": 1\n }\n}"; + JsonUtils.deserialize(resString, classOf[Response]) + } + def getRequestData(): List[Map[String, List[String]]] = { val reqMap : java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ put("content", new util.ArrayList[util.Map[String, AnyRef]](){{ @@ -251,10 +260,10 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory put("identifier","do_1111") put("dialcode", new util.ArrayList[String](){{ add("N4Z7D5") - add("E8B7Z6") - add("R4X2P2") - add("L4A6W8") - add("D2E1J9") +// add("E8B7Z6") +// add("R4X2P2") +// add("L4A6W8") +// add("D2E1J9") }}) }}) }}) From bb3f724c3cccc1288843df8abc850e9f396293dd Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 21 Apr 2022 11:36:00 +0530 Subject: [PATCH 007/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- .../search/client/ElasticSearchUtil.java | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java index be9964049..0e7b323f2 100644 --- a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java +++ b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java @@ -1,6 +1,3 @@ -/** - * - */ package org.sunbird.search.client; import akka.dispatch.Futures; @@ -11,9 +8,9 @@ import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.apache.http.util.EntityUtils; +import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse; -import org.elasticsearch.client.RestClientBuilder; -import org.elasticsearch.client.indices.CreateIndexResponse; +import org.elasticsearch.client.*; import org.sunbird.search.util.SearchConstants; import org.sunbird.telemetry.logger.TelemetryManager; import org.elasticsearch.action.ActionListener; @@ -225,9 +222,8 @@ public static void deleteDocumentsByQuery(QueryBuilder query, String indexName, TelemetryManager.log("Deleted Documents by Query" + EntityUtils.toString(response.getEntity())); } - - public static void deleteIndex(String indexName) throws InterruptedException, ExecutionException, IOException { - AcknowledgedResponse response = getClient(indexName).indices().delete(new DeleteIndexRequest(indexName)); + public static void deleteIndex(String indexName) throws IOException { + AcknowledgedResponse response = getClient(indexName).indices().delete(new DeleteIndexRequest(indexName), RequestOptions.DEFAULT); esClient.remove(indexName); TelemetryManager.log("Deleted Index" + indexName + " : " + response.isAcknowledged()); } @@ -239,7 +235,7 @@ public static String getDocumentAsStringById(String indexName, String documentTy } public static List getMultiDocumentAsStringByIdList(String indexName, String documentType, - List documentIdList) throws IOException { + List documentIdList) throws IOException { List finalResult = new ArrayList(); MultiGetRequest request = new MultiGetRequest(); documentIdList.forEach(docId -> request.add(indexName, documentType, docId)); @@ -280,7 +276,7 @@ public static void bulkIndexWithIndexId(String indexName, String documentType, M } public static void bulkIndexWithAutoGenerateIndexId(String indexName, String documentType, - List> jsonObjects) + List> jsonObjects) throws Exception { if (isIndexExists(indexName)) { RestHighLevelClient client = getClient(indexName); @@ -306,7 +302,7 @@ public static void bulkIndexWithAutoGenerateIndexId(String indexName, String doc @SuppressWarnings("rawtypes") public static List textSearch(Class objectClass, Map matchCriterias, String indexName, - String indexType, int limit) throws Exception { + String indexType, int limit) throws Exception { SearchResponse result = search(matchCriterias, null, indexName, indexType, null, false, limit); return getDocumentsFromSearchResult(result, objectClass); } @@ -344,7 +340,7 @@ public static List getDocumentsFromHitsWithScore(SearchHits hits) { @SuppressWarnings({ "rawtypes" }) public static List textSearchReturningId(Map matchCriterias, String indexName, - String indexType) + String indexType) throws Exception { SearchResponse result = search(matchCriterias, null, indexName, indexType, null, false, 100); return getDocumentsFromSearchResultWithId(result); @@ -369,7 +365,7 @@ public static List getDocumentsFromHitsWithId(SearchHits hits) { @SuppressWarnings({ "rawtypes" }) public static List wildCardSearch(Class objectClass, String textKeyWord, String wordWildCard, - String indexName, String indexType, int limit) throws Exception { + String indexName, String indexType, int limit) throws Exception { SearchResponse result = wildCardSearch(textKeyWord, wordWildCard, indexName, indexType, limit); return getDocumentsFromSearchResult(result, objectClass); } From 7948db1ef852247264568397db553cf6eb911ea2 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 21 Apr 2022 11:42:56 +0530 Subject: [PATCH 008/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- .../search/client/ElasticSearchUtil.java | 51 +++++++++---------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java index 0e7b323f2..8d725f96c 100644 --- a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java +++ b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java @@ -1,3 +1,6 @@ +/** + * + */ package org.sunbird.search.client; import akka.dispatch.Futures; @@ -235,7 +238,7 @@ public static String getDocumentAsStringById(String indexName, String documentTy } public static List getMultiDocumentAsStringByIdList(String indexName, String documentType, - List documentIdList) throws IOException { + List documentIdList) throws IOException { List finalResult = new ArrayList(); MultiGetRequest request = new MultiGetRequest(); documentIdList.forEach(docId -> request.add(indexName, documentType, docId)); @@ -276,7 +279,7 @@ public static void bulkIndexWithIndexId(String indexName, String documentType, M } public static void bulkIndexWithAutoGenerateIndexId(String indexName, String documentType, - List> jsonObjects) + List> jsonObjects) throws Exception { if (isIndexExists(indexName)) { RestHighLevelClient client = getClient(indexName); @@ -302,7 +305,7 @@ public static void bulkIndexWithAutoGenerateIndexId(String indexName, String doc @SuppressWarnings("rawtypes") public static List textSearch(Class objectClass, Map matchCriterias, String indexName, - String indexType, int limit) throws Exception { + String indexType, int limit) throws Exception { SearchResponse result = search(matchCriterias, null, indexName, indexType, null, false, limit); return getDocumentsFromSearchResult(result, objectClass); } @@ -339,9 +342,7 @@ public static List getDocumentsFromHitsWithScore(SearchHits hits) { } @SuppressWarnings({ "rawtypes" }) - public static List textSearchReturningId(Map matchCriterias, String indexName, - String indexType) - throws Exception { + public static List textSearchReturningId(Map matchCriterias, String indexName, String indexType) throws Exception { SearchResponse result = search(matchCriterias, null, indexName, indexType, null, false, 100); return getDocumentsFromSearchResultWithId(result); } @@ -365,14 +366,13 @@ public static List getDocumentsFromHitsWithId(SearchHits hits) { @SuppressWarnings({ "rawtypes" }) public static List wildCardSearch(Class objectClass, String textKeyWord, String wordWildCard, - String indexName, String indexType, int limit) throws Exception { + String indexName, String indexType, int limit) throws Exception { SearchResponse result = wildCardSearch(textKeyWord, wordWildCard, indexName, indexType, limit); return getDocumentsFromSearchResult(result, objectClass); } public static SearchResponse wildCardSearch(String textKeyWord, String wordWildCard, String indexName, - String indexType, int limit) - throws Exception { + String indexType, int limit) throws Exception { SearchSourceBuilder query = buildJsonForWildCardQuery(textKeyWord, wordWildCard, indexName); query.size(limit); return search(indexName, indexType, query); @@ -380,16 +380,15 @@ public static SearchResponse wildCardSearch(String textKeyWord, String wordWildC @SuppressWarnings({ "rawtypes" }) public static List textFiltersSearch(Class objectClass, Map searchCriteria, - Map textFiltersMap, String indexName, String indexType, int limit) - throws Exception { + Map textFiltersMap, String indexName, String indexType, int limit) throws Exception { SearchResponse result = search(searchCriteria, textFiltersMap, indexName, indexType, null, false, limit); return getDocumentsFromSearchResult(result, objectClass); } @SuppressWarnings("rawtypes") public static Map textFiltersGroupBySearch(Class objectClass, Map searchCriteria, - Map textFiltersMap, List> groupByList, String indexName, - String indexType) throws Exception { + Map textFiltersMap, List> groupByList, String indexName, + String indexType) throws Exception { SearchResponse result = search(searchCriteria, textFiltersMap, indexName, indexType, groupByList, false, resultLimit); List documents = getDocumentsFromSearchResult(result, objectClass); @@ -405,30 +404,28 @@ public static Map textFiltersGroupBySearch(Class objectClass, Ma @SuppressWarnings("rawtypes") public static List textSearch(Class objectClass, Map matchCriterias, - Map textFiltersMap, String indexName, String indexType) throws Exception { + Map textFiltersMap, String indexName, String indexType) throws Exception { SearchResponse result = search(matchCriterias, textFiltersMap, indexName, indexType, null, false, resultLimit); return getDocumentsFromSearchResult(result, objectClass); } @SuppressWarnings("rawtypes") public static List textSearch(Class objectClass, Map matchCriterias, - Map textFiltersMap, String indexName, String indexType, - List> groupByList, int limit) throws Exception { - SearchResponse result = search(matchCriterias, textFiltersMap, indexName, indexType, groupByList, false, - limit); + Map textFiltersMap, String indexName, String indexType, + List> groupByList, int limit) throws Exception { + SearchResponse result = search(matchCriterias, textFiltersMap, indexName, indexType, groupByList, false, limit); return getDocumentsFromSearchResult(result, objectClass); } public static SearchResponse search(Map matchCriterias, Map textFiltersMap, - String indexName, String indexType, List> groupBy, boolean isDistinct, int limit) + String indexName, String indexType, List> groupBy, boolean isDistinct, int limit) throws Exception { SearchSourceBuilder query = buildJsonForQuery(matchCriterias, textFiltersMap, groupBy, isDistinct, indexName); query.size(limit); return search(indexName, indexType, query); } - public static SearchResponse search(String indexName, String indexType, SearchSourceBuilder query) - throws Exception { + public static SearchResponse search(String indexName, String indexType, SearchSourceBuilder query) throws Exception { return getClient(indexName).search(new SearchRequest(indexName).source(query), RequestOptions.DEFAULT); } @@ -502,8 +499,7 @@ public static Map getCountFromAggregation(Aggregations aggregati @SuppressWarnings("rawtypes") public static Map getCountOfSearch(Class objectClass, Map matchCriterias, - String indexName, String indexType, List> groupByList, int limit) - throws Exception { + String indexName, String indexType, List> groupByList, int limit) throws Exception { SearchResponse result = search(matchCriterias, null, indexName, indexType, groupByList, false, limit); Aggregations aggregations = result.getAggregations(); return getCountFromAggregation(aggregations, groupByList); @@ -511,7 +507,7 @@ public static Map getCountOfSearch(Class objectClass, Map getDistinctCountOfSearch(Map matchCriterias, String IndexName, - String IndexType, List> groupByList) throws Exception { + String IndexType, List> groupByList) throws Exception { Map countMap = new HashMap(); SearchResponse result = search(matchCriterias, null, IndexName, IndexType, groupByList, true, 0); Aggregations aggregations = result.getAggregations(); @@ -540,8 +536,8 @@ public static Map getDistinctCountOfSearch(Map m @SuppressWarnings("unchecked") public static SearchSourceBuilder buildJsonForQuery(Map matchCriterias, - Map textFiltersMap, List> groupByList, boolean isDistinct, - String indexName) { + Map textFiltersMap, List> groupByList, boolean isDistinct, + String indexName) { SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); @@ -598,8 +594,7 @@ public static SearchSourceBuilder buildJsonForQuery(Map matchCri return searchSourceBuilder; } - private static SearchSourceBuilder buildJsonForWildCardQuery(String textKeyWord, String wordWildCard, - String indexName) { + private static SearchSourceBuilder buildJsonForWildCardQuery(String textKeyWord, String wordWildCard, String indexName) { return new SearchSourceBuilder().query(QueryBuilders.wildcardQuery(textKeyWord, wordWildCard)); } From 8f698061af7c5352c3c58ad66db6442bedfbde2b Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 21 Apr 2022 11:45:07 +0530 Subject: [PATCH 009/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- .../main/scala/org/sunbird/content/dial/DIALManager.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 06d047c25..100e688b1 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -232,9 +232,9 @@ object DIALManager { def getChildrenDIALMap(childrenHierarchy: List[util.Map[String, AnyRef]], requestMap: Map[String, List[String]]): Map[String, AnyRef] = { childrenHierarchy.map(child => { - val subChildrenDIALMap = if(child.get("children")!=null) - getChildrenDIALMap(child.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList, requestMap) - else Map.empty[String, String] + val subChildrenDIALMap = if(child.get("children")!=null) + getChildrenDIALMap(child.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList, requestMap) + else Map.empty[String, String] val childDIALMap = if(requestMap.contains(child.get("identifier").toString) && child.get("dialcodes")!=null) Map(child.get("identifier").toString -> child.get("dialcodes")) From 9dd45231d50a4818ccd11273207d9f1c276f2271 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 21 Apr 2022 15:29:10 +0530 Subject: [PATCH 010/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KPe --- .../org/sunbird/content/dial/DIALManagerTest.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index 675577eee..683500f10 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -174,7 +174,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory "link DIAL with valid request for content" should "update the contents successfully" in { (oec.httpUtil _).expects().returns(httpUtil) (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() - (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getLinkDIALSearchResponse) + (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse) (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(getNodes())).noMoreThanOnce() val nodes: util.List[Node] = getCategoryNode() @@ -260,10 +260,10 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory put("identifier","do_1111") put("dialcode", new util.ArrayList[String](){{ add("N4Z7D5") -// add("E8B7Z6") -// add("R4X2P2") -// add("L4A6W8") -// add("D2E1J9") + add("E8B7Z6") + add("R4X2P2") + add("L4A6W8") + add("D2E1J9") }}) }}) }}) From 67224383beb85c60a98122d09c91a2803f83e95a Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 21 Apr 2022 16:14:39 +0530 Subject: [PATCH 011/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KPe --- .../content/dial/DIALManagerTest.scala | 60 ++++++++++++------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index 683500f10..9a1b442e8 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -192,18 +192,30 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory }) } - "link DIAL with valid request for collections" should "update the collection content successfully" in { - (oec.httpUtil _).expects().returns(httpUtil) - (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse) - val request = getCollectionDIALRequest() - - println("DIALManagerTest:: link collection:: request:: " + request) - - val response = DIALManager.link(request) - response.map(result => { - assert(result.getResponseCode.toString=="OK") - }) - } +// "link DIAL with valid request for collections" should "update the collection content successfully" in { +// (oec.httpUtil _).expects().returns(httpUtil) +// (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() +// (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse) +// +// (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(getNodes())).noMoreThanOnce() +// val nodes: util.List[Node] = getCategoryNode() +// (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).noMoreThanOnce() +// +// (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())) +// (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode("do_1111"))) +// (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) +// (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())) +// +// +// val request = getCollectionDIALRequest() +// +// println("DIALManagerTest:: link collection:: request:: " + request) +// +// val response = DIALManager.link(request) +// response.map(result => { +// assert(result.getResponseCode.toString=="OK") +// }) +// } def getDIALSearchResponse():Response = { val resString = "{\n \"id\": \"sunbird.dialcode.search\",\n \"ver\": \"3.0\",\n \"ts\": \"2020-04-21T19:39:14ZZ\",\n \"params\": {\n \"resmsgid\": \"1dfcc25b-6c37-49f8-a6c3-7185063e8752\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"dialcodes\": [\n {\n \"dialcode_index\": 7609876,\n \"identifier\": \"N4Z7D5\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.603+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610113,\n \"identifier\": \"E8B7Z6\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.635+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610117,\n \"identifier\": \"R4X2P2\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.637+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610961,\n \"identifier\": \"L4A6W8\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.734+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7611164,\n \"identifier\": \"D2E1J9\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.759+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n }\n ],\n \"count\": 5\n }\n}"; @@ -301,25 +313,27 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory put("dialcode", new util.ArrayList[String](){{ add("N4Z7D5") add("E8B7Z6") + add("L4A6W8") + add("D2E1J9") }}) }}) add(new util.HashMap[String, AnyRef](){{ put("identifier",new util.ArrayList[String](){{ add("do_2222") - add("do_3333") +// add("do_3333") }}) put("dialcode", "R4X2P2") }}) - add(new util.HashMap[String, AnyRef](){{ - put("identifier",new util.ArrayList[String](){{ - add("do_4444") - add("do_5555") - }}) - put("dialcode", new util.ArrayList[String](){{ - add("L4A6W8") - add("D2E1J9") - }}) - }}) +// add(new util.HashMap[String, AnyRef](){{ +// put("identifier",new util.ArrayList[String](){{ +// add("do_4444") +// add("do_5555") +// }}) +// put("dialcode", new util.ArrayList[String](){{ +// add("L4A6W8") +// add("D2E1J9") +// }}) +// }}) }}) }} reqMap From 9494b5ea53e7a804f822e351435b1132db80569d Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Mon, 25 Apr 2022 17:12:54 +0530 Subject: [PATCH 012/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KPe --- .../content/dial/DIALManagerTest.scala | 109 +++++++++++------- 1 file changed, 66 insertions(+), 43 deletions(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index 9a1b442e8..86fef60ff 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -1,24 +1,23 @@ package org.sunbird.content.dial -import java.util - import org.scalamock.matchers.Matchers import org.scalamock.scalatest.AsyncMockFactory import org.scalatest.AsyncFlatSpec -import org.sunbird.common.{HttpUtil, JsonUtils} -import org.sunbird.common.dto.{Request, Response} +import org.sunbird.common.dto.{Property, Request, Response} import org.sunbird.common.exception.{ClientException, ResourceNotFoundException, ResponseCode, ServerException} +import org.sunbird.common.{HttpUtil, JsonUtils} import org.sunbird.graph.dac.model.{Node, SearchCriteria} import org.sunbird.graph.{GraphService, OntologyEngineContext} +import java.util import scala.concurrent.Future class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory { implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] - val graphDB = mock[GraphService] - val httpUtil = mock[HttpUtil] - + val graphDB: GraphService = mock[GraphService] + val httpUtil: HttpUtil = mock[HttpUtil] + "getRequestData with list input" should "return request data as list with scala types" in { val reqMap : java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ put("content", new util.ArrayList[util.Map[String, AnyRef]](){{ @@ -52,8 +51,8 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory assert(result.isInstanceOf[List[AnyRef]]) assert(result.size==3) assert(result(1).nonEmpty) - assert(result(1).get("identifier").get.isInstanceOf[List[String]]) - assert(result(1).get("dialcode").get.isInstanceOf[List[String]]) + assert(result(1)("identifier").isInstanceOf[List[String]]) + assert(result(1)("dialcode").isInstanceOf[List[String]]) } "getRequestData with map input" should "return request data as list with scala types" in { @@ -72,9 +71,9 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory assert(null!=result && result.nonEmpty) assert(result.isInstanceOf[List[AnyRef]]) assert(result.size==1) - assert(result(0).nonEmpty) - assert(result(0).get("identifier").get.isInstanceOf[List[String]]) - assert(result(0).get("dialcode").get.isInstanceOf[List[String]]) + assert(result.head.nonEmpty) + assert(result.head("identifier").isInstanceOf[List[String]]) + assert(result.head("dialcode").isInstanceOf[List[String]]) } "getRequestData with invalid input" should "throw client exception" in { @@ -111,7 +110,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory "validateAndGetRequestMap with valid input" should "return the request map" in { (oec.httpUtil _).expects().returns(httpUtil) - (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse()) + (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse) val input = getRequestData() val result = DIALManager.validateAndGetRequestMap("test", input) assert(result.nonEmpty) @@ -192,38 +191,33 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory }) } -// "link DIAL with valid request for collections" should "update the collection content successfully" in { -// (oec.httpUtil _).expects().returns(httpUtil) -// (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() -// (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse) -// -// (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(getNodes())).noMoreThanOnce() -// val nodes: util.List[Node] = getCategoryNode() -// (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).noMoreThanOnce() -// -// (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())) -// (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode("do_1111"))) -// (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) -// (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())) -// -// -// val request = getCollectionDIALRequest() -// -// println("DIALManagerTest:: link collection:: request:: " + request) -// -// val response = DIALManager.link(request) -// response.map(result => { -// assert(result.getResponseCode.toString=="OK") -// }) -// } - - def getDIALSearchResponse():Response = { - val resString = "{\n \"id\": \"sunbird.dialcode.search\",\n \"ver\": \"3.0\",\n \"ts\": \"2020-04-21T19:39:14ZZ\",\n \"params\": {\n \"resmsgid\": \"1dfcc25b-6c37-49f8-a6c3-7185063e8752\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"dialcodes\": [\n {\n \"dialcode_index\": 7609876,\n \"identifier\": \"N4Z7D5\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.603+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610113,\n \"identifier\": \"E8B7Z6\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.635+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610117,\n \"identifier\": \"R4X2P2\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.637+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610961,\n \"identifier\": \"L4A6W8\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.734+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7611164,\n \"identifier\": \"D2E1J9\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.759+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n }\n ],\n \"count\": 5\n }\n}"; - JsonUtils.deserialize(resString, classOf[Response]) + "link DIAL with valid request for collections" should "update the collection content successfully" in { + + (oec.httpUtil _).expects().returns(httpUtil) + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse) + + val nodes: util.List[Node] = getCategoryNode() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes() + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode("do_1111"))).anyNumberOfTimes() + (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) + (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())) + (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) + + val request = getCollectionDIALRequest() + + println("DIALManagerTest:: link collection:: request:: " + request) + + val response = DIALManager.link(request) + response.map(result => { + assert(result.getResponseCode.toString=="OK") + }) } - def getLinkDIALSearchResponse():Response = { - val resString = "{\n \"id\": \"sunbird.dialcode.search\",\n \"ver\": \"3.0\",\n \"ts\": \"2020-04-21T19:39:14ZZ\",\n \"params\": {\n \"resmsgid\": \"1dfcc25b-6c37-49f8-a6c3-7185063e8752\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"dialcodes\": [\n {\n \"dialcode_index\": 7609876,\n \"identifier\": \"N4Z7D5\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.603+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n } ],\n \"count\": 1\n }\n}"; + def getDIALSearchResponse:Response = { + val resString = "{\n \"id\": \"sunbird.dialcode.search\",\n \"ver\": \"3.0\",\n \"ts\": \"2020-04-21T19:39:14ZZ\",\n \"params\": {\n \"resmsgid\": \"1dfcc25b-6c37-49f8-a6c3-7185063e8752\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"dialcodes\": [\n {\n \"dialcode_index\": 7609876,\n \"identifier\": \"N4Z7D5\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.603+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610113,\n \"identifier\": \"E8B7Z6\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.635+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610117,\n \"identifier\": \"R4X2P2\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.637+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610961,\n \"identifier\": \"L4A6W8\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.734+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7611164,\n \"identifier\": \"D2E1J9\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.759+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n }\n ],\n \"count\": 5\n }\n}"; JsonUtils.deserialize(resString, classOf[Response]) } @@ -406,4 +400,33 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory util.Arrays.asList(node) } + def getCassandraHierarchy(): Response = { + val hierarchyString: String = + """{"ownershipType": ["createdBy"],"subject": ["Mathematics"],"channel": "0126825293972439041","organisation": ["Sunbird"], + |"language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","objectType": "Content","gradeLevel": ["Class 4"], + |"primaryCategory": "Digital Textbook","children": [{"ownershipType": ["createdBy"],"parent": "do_1111","code": "do_1132828084877148161531", + |"keywords": [],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "This chapter describes about human body", + |"language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.470+0000", + |"objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_2222", + |"code": "do_1132828084876574721523","keywords": [],"credentials": {"enabled": "No"},"channel": "0126825293972439041", + |"description": "This section describes about various part of the body such as head, hands, legs etc.","language": ["English"], + |"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.466+0000", + |"objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_1132833371215134721712", + |"code": "do_1132828084876738561525","keywords": ["legs etc."],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "xyz", + |"language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.475+0000", + |"objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_1132833371215872001720", + |"previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132339274094346241120/test-874-kb.mp4", + |"channel": "b00bc992ef25f1a9a8d63291e20efc8d", + |"downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132339274094346241120/untitled-content_1616331971279_do_1132339274094346241120_14.0.ecar", + |"organisation": ["Sunbird"],"language": ["English"],"mimeType": "video/mp4","variants": {"spine": + |{"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132339274094346241120/untitled-content_1616331975047_do_1132339274094346241120_14.0_spine.ecar","size": 1381.0}},"objectType": "Content","primaryCategory": "Learning Resource","appId": "local.sunbird.portal","contentEncoding": "identity","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132339274094346241120/test-874-kb.mp4", + |"lockKey": "34a029c4-ac81-4934-9792-11b7a57d6c13","sYS_INTERNAL_LAST_UPDATED_ON": "2021-03-21T13:20:24.579+0000","contentType": "Resource", + |"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132339274094346241120","audience": ["Student"],"visibility": "Default", + |"consumerId": "273f3b18-5dda-4a27-984a-060c7cd398d3","index": 1,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"], + |"lastPublishedBy": "8454cb21-3ce9-4e30-85b5-fade097880d8","version": 2,"license": "CC BY 4.0","prevState": "Live","size": 849897.0, + |"lastPublishedOn": "2021-03-21T13:06:11.272+0000","name": "Untitled Content","status": "Live","code": "a88b0257-670b-455b-98b8-6e359ebac009","credentials": {"enabled": "No"},"prevStatus": "Processing","description": "updated","streamingUrl": "https://sunbirddevmedia-inct.streaming.media.azure.net/9c0ebb33-af08-403f-afb4-eb24749f40a1/test-874-kb.ism/manifest(format=m3u8-aapl-v3)","idealScreenSize": "normal","createdOn": "2021-03-11T13:34:14.475+0000","contentDisposition": "inline","lastUpdatedOn": "2021-03-21T13:06:09.526+0000","dialcodeRequired": "No","lastStatusChangedOn": "2021-03-21T18:36:15.799+0530","createdFor": ["ORG_001"],"creator": "Reviewer User","os": ["All"],"se_FWIds": ["NCFCOPY"],"pkgVersion": 14.0,"versionKey": "1616331969523","idealScreenDensity": "hdpi","framework": "NCFCOPY","depth": 4,"s3Key": "ecar_files/do_1132339274094346241120/untitled-content_1616331971279_do_1132339274094346241120_14.0.ecar","createdBy": "95e4942d-cbe8-477d-aebd-ad8e6de4bfc8","compatibilityLevel": 1,"resourceType": "Learn"},{"ownershipType": ["createdBy"],"parent": "do_1132833371215872001720","unitIdentifiers": ["do_1132239562839900161634"],"copyright": "2021 MIT","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_113223967141863424174-latest","plugins": [{"identifier": "org.sunbird.questionunit.quml","semanticVersion": "1.1"}],"subject": ["Hindi"],"channel": "01309282781705830427","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_113223967141863424174/esa_1614253812772_do_113223967141863424174_1.0.ecar","language": ["English"],"source": "https://dock.sunbirded.org/api/content/v1/read/do_1132239617341767681638","mimeType": "application/vnd.ekstep.ecml-archive","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_113223967141863424174/esa_1614253813394_do_113223967141863424174_1.0_spine.ecar","size": 24293.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Class 10"],"primaryCategory": "Exam Question","appId": "dev.dock.portal","contentEncoding": "gzip","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_113223967141863424174/artifact/1614253223147_do_1132239617341767681638.zip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-02-25T11:50:16.032+0000","contentType": "Resource","se_gradeLevels": ["Class 10"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_113223967141863424174","audience": ["Student"],"visibility": "Default","author": "anusha","maxQuestions": 1,"consumerId": "b7054510-3ca4-49fd-b373-b100b3f65e18","index": 2,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "5a587cc1-e018-4859-a0a8-e842650b9d64","version": 2,"se_subjects": ["Hindi"],"license": "CC BY 4.0","prevState": "Review","size": 384798.0,"lastPublishedOn": "2021-02-25T11:50:12.771+0000","name": "esa","topic": ["तोप"],"status": "Live","code": "d19f43ce-753d-2c70-a9fd-70302af424a0","credentials": {"enabled": "No"},"prevStatus": "Processing","origin": "do_1132239617341767681638","streamingUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_113223967141863424174-latest","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-02-25T11:50:01.500+0000","se_boards": ["CBSE"],"processId": "2b00cca7-42d5-4e35-aa03-1c22dfe03de8","contentDisposition": "inline","lastUpdatedOn": "2021-02-25T11:50:12.678+0000","originData": {"identifier": "do_1132239617341767681638","repository": "https://dock.sunbirded.org/api/content/v1/read/do_1132239617341767681638"},"collectionId": "do_1132239562836049921627","dialcodeRequired": "No","editorVersion": 3,"lastStatusChangedOn": "2021-02-25T11:50:16.017+0000","creator": "anusha","os": ["All"],"questionCategories": ["SA"],"cloudStorageKey": "content/do_113223967141863424174/artifact/1614253223147_do_1132239617341767681638.zip","se_FWIds": ["ekstep_ncert_k-12"],"marks": "12","bloomsLevel": ["Apply"],"pkgVersion": 1.0,"versionKey": "1614253812678","idealScreenDensity": "hdpi","framework": "ekstep_ncert_k-12","depth": 4,"s3Key": "ecar_files/do_113223967141863424174/esa_1614253812772_do_113223967141863424174_1.0.ecar","lastSubmittedOn": "2021-02-25T11:50:11.539+0000","createdBy": "19ba0e4e-9285-4335-8dd0-f674bf03fa4d","se_topics": ["तोप"],"compatibilityLevel": 1,"itemSetPreviewUrl": "https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/do_1132239617341767681638/artifact/do_1132239617341767681638_1614253222002.pdf","board": "CBSE","programId": "463cfa30-775c-11eb-8c56-93946e419809"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.475+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "Yes","identifier": "do_1132833371215872001720","lastStatusChangedOn": "2021-05-20T08:58:33.475+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113475","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 3,"compatibilityLevel": 1,"name": "5.1.1 Key parts in the head","topic": [],"status": "Draft"},{"ownershipType": ["createdBy"],"parent": "do_1132833371215134721712","code": "do_1132828084876165121519","keywords": [],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "","language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.473+0000","objectType": "Content","primaryCategory": "Textbook Unit","contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.473+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "No","identifier": "do_1132833371215708161718","lastStatusChangedOn": "2021-05-20T08:58:33.473+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 2,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113473","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 3,"compatibilityLevel": 1,"name": "5.1.2 Other parts","topic": [],"status": "Draft"},{"ownershipType": ["createdBy"],"parent": "do_1132833371215134721712","unitIdentifiers": ["do_11323721176414617611924"],"copyright": "2021 MIT","organisationId": "e7328d77-42a7-44c8-84f4-8cfea235f07d","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1132372524622561281279-latest","plugins": [{"identifier": "org.sunbird.questionunit.quml","semanticVersion": "1.1"}],"subject": ["Mathematics"],"channel": "01309282781705830427","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132372524622561281279/untitled_1615875562931_do_1132372524622561281279_1.0.ecar","language": ["English"],"source": "https://dock.sunbirded.org/api/content/v1/read/do_11323724954450329611930","mimeType": "application/vnd.ekstep.ecml-archive","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132372524622561281279/untitled_1615875563539_do_1132372524622561281279_1.0_spine.ecar","size": 19563.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Class 5"],"primaryCategory": "Exam Question","appId": "dev.dock.portal","contentEncoding": "gzip","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_1132372524622561281279/artifact/1615875430184_do_11323724954450329611930.zip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-03-16T06:19:26.162+0000","contentType": "Resource","se_gradeLevels": ["Class 5"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132372524622561281279","audience": ["Student"],"visibility": "Default","author": "N18","maxQuestions": 1,"consumerId": "f73cfcc5-4d43-4fa0-8b81-46166c81bc2b","learningOutcome": ["identify the need to find area and perimeter of rectangle and square."],"index": 3,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "5a587cc1-e018-4859-a0a8-e842650b9d64","version": 2,"se_subjects": ["Mathematics"],"license": "CC BY 4.0","prevState": "Review","size": 374996.0,"lastPublishedOn": "2021-03-16T06:19:22.931+0000","name": "Untitled","topic": ["Speed, Distance and Time"],"status": "Live","code": "2544c8b8-7946-b6c0-e1c7-ced4aee4ea8c","credentials": {"enabled": "No"},"prevStatus": "Processing","origin": "do_11323724954450329611930","streamingUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1132372524622561281279-latest","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-03-16T06:19:04.712+0000","se_boards": ["CBSE"],"processId": "9995e013-a7c9-4da1-b2c9-2f59da33414a","contentDisposition": "inline","lastUpdatedOn": "2021-03-16T06:19:20.817+0000","originData": {"identifier": "do_11323724954450329611930","repository": "https://dock.sunbirded.org/api/content/v1/read/do_11323724954450329611930"},"collectionId": "do_11323721176353996811921","dialcodeRequired": "No","editorVersion": 3,"lastStatusChangedOn": "2021-03-16T06:19:26.147+0000","creator": "N18","os": ["All"],"questionCategories": ["MTF"],"cloudStorageKey": "content/do_1132372524622561281279/artifact/1615875430184_do_11323724954450329611930.zip","se_FWIds": ["ekstep_ncert_k-12"],"marks": "2","bloomsLevel": ["Apply"],"pkgVersion": 1.0,"versionKey": "1615875560817","idealScreenDensity": "hdpi","framework": "ekstep_ncert_k-12","depth": 3,"s3Key": "ecar_files/do_1132372524622561281279/untitled_1615875562931_do_1132372524622561281279_1.0.ecar","lastSubmittedOn": "2021-03-16T06:19:17.005+0000","createdBy": "60f91e9e-34ee-4f9f-a907-d312d0e8063e","se_topics": ["Speed, Distance and Time"],"compatibilityLevel": 1,"itemSetPreviewUrl": "https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/do_11323724954450329611930/artifact/do_11323724954450329611930_1615875429226.pdf","board": "CBSE","programId": "800eb440-8613-11eb-a663-4f63bbe94184"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.466+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "Yes","identifier": "do_1132833371215134721712","lastStatusChangedOn": "2021-05-20T08:58:33.466+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113466","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 2,"compatibilityLevel": 1,"name": "5.1 Parts of Body","topic": ["Role Of The Sense Organs"],"status": "Draft"},{"ownershipType": ["createdBy"],"parent": "do_2222","code": "do_1132828084877066241529","keywords": [],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "","language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.476+0000","objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_1132833371215953921722","code": "do_1132828084876492801521","keywords": ["test key","check"],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "","language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.468+0000","objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_1132833371215298561714","code": "do_1132828084876820481527","keywords": ["abcd","cgf"],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "labeled new","language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.464+0000","objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_1132833371214970881710","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132338069147811841118/test-874-kb.mp4","channel": "b00bc992ef25f1a9a8d63291e20efc8d","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132338069147811841118/untitled-content_1615468830522_do_1132338069147811841118_2.0.ecar","organisation": ["Sunbird"],"language": ["English"],"mimeType": "video/mp4","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132338069147811841118/untitled-content_1615468834470_do_1132338069147811841118_2.0_spine.ecar","size": 1361.0}},"objectType": "Content","primaryCategory": "Learning Resource","appId": "dev.sunbird.portal","contentEncoding": "identity","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132338069147811841118/test-874-kb.mp4","lockKey": "d73707c8-9999-4fc9-9b34-0207f74faf43","sYS_INTERNAL_LAST_UPDATED_ON": "2021-03-12T08:10:31.335+0000","contentType": "Resource","trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132338069147811841118","audience": ["Student"],"visibility": "Default","consumerId": "273f3b18-5dda-4a27-984a-060c7cd398d3","index": 1,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "8454cb21-3ce9-4e30-85b5-fade097880d8","version": 2,"license": "CC BY 4.0","prevState": "Live","size": 849876.0,"lastPublishedOn": "2021-03-11T13:20:30.514+0000","name": "Untitled Content","status": "Live","code": "9deb2c69-7240-472a-98e7-ed438e76262b","credentials": {"enabled": "No"},"prevStatus": "Processing","streamingUrl": "https://sunbirddevmedia-inct.streaming.media.azure.net/f17bccc5-cab3-4da8-a5eb-11d7211f1507/test-874-kb.ism/manifest(format=m3u8-aapl-v3)","idealScreenSize": "normal","createdOn": "2021-03-11T09:29:05.654+0000","contentDisposition": "inline","lastUpdatedOn": "2021-03-11T13:20:28.256+0000","dialcodeRequired": "No","lastStatusChangedOn": "2021-03-11T18:50:28.256+0530","createdFor": ["ORG_001"],"creator": "Reviewer User","os": ["All"],"se_FWIds": ["NCFCOPY"],"pkgVersion": 2.0,"versionKey": "1615455090358","idealScreenDensity": "hdpi","framework": "NCFCOPY","depth": 5,"s3Key": "ecar_files/do_1132338069147811841118/untitled-content_1615468830522_do_1132338069147811841118_2.0.ecar","createdBy": "95e4942d-cbe8-477d-aebd-ad8e6de4bfc8","compatibilityLevel": 1,"resourceType": "Learn"},{"ownershipType": ["createdBy"],"parent": "do_1132833371214970881710","unitIdentifiers": ["do_1132238266042040321422"],"copyright": "2021 MIT","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_11322383952751820816-latest","plugins": [{"identifier": "org.sunbird.questionunit.quml","semanticVersion": "1.1"}],"subject": ["Hindi"],"channel": "01309282781705830427","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_11322383952751820816/sapractice_1614238238045_do_11322383952751820816_1.0.ecar","language": ["English"],"source": "https://dock.sunbirded.org/api/content/v1/read/do_1132238287156183041424","mimeType": "application/vnd.ekstep.ecml-archive","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_11322383952751820816/sapractice_1614238238800_do_11322383952751820816_1.0_spine.ecar","size": 13171.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Class 10"],"primaryCategory": "Exam Question","appId": "dev.dock.portal","contentEncoding": "gzip","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11322383952751820816/artifact/1614237122171_do_1132238287156183041424.zip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-02-25T07:30:44.916+0000","contentType": "Resource","se_gradeLevels": ["Class 10"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_11322383952751820816","audience": ["Student"],"visibility": "Default","author": "anusha","maxQuestions": 1,"consumerId": "273f3b18-5dda-4a27-984a-060c7cd398d3","index": 2,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "5a587cc1-e018-4859-a0a8-e842650b9d64","version": 2,"se_subjects": ["Hindi"],"license": "CC BY 4.0","prevState": "Review","size": 362236.0,"lastPublishedOn": "2021-02-25T07:30:38.043+0000","name": "sa:practice","status": "Live","code": "f239c77e-ed71-9133-0145-7468a92bce79","credentials": {"enabled": "No"},"prevStatus": "Processing","origin": "do_1132238287156183041424","streamingUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_11322383952751820816-latest","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-02-25T07:30:23.577+0000","se_boards": ["CBSE"],"processId": "04d5aec9-ed09-4a57-963d-9fa654fecf8d","contentDisposition": "inline","lastUpdatedOn": "2021-02-25T07:30:37.956+0000","originData": {"identifier": "do_1132238287156183041424","repository": "https://dock.sunbirded.org/api/content/v1/read/do_1132238287156183041424"},"collectionId": "do_1132238266036551681415","dialcodeRequired": "No","editorVersion": 3,"lastStatusChangedOn": "2021-02-25T07:30:44.908+0000","creator": "anusha","os": ["All"],"questionCategories": ["SA"],"cloudStorageKey": "content/do_11322383952751820816/artifact/1614237122171_do_1132238287156183041424.zip","se_FWIds": ["ekstep_ncert_k-12"],"marks": "12","pkgVersion": 1.0,"versionKey": "1614238237956","idealScreenDensity": "hdpi","framework": "ekstep_ncert_k-12","depth": 5,"s3Key": "ecar_files/do_11322383952751820816/sapractice_1614238238045_do_11322383952751820816_1.0.ecar","lastSubmittedOn": "2021-02-25T07:30:36.709+0000","createdBy": "19ba0e4e-9285-4335-8dd0-f674bf03fa4d","compatibilityLevel": 1,"itemSetPreviewUrl": "https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/do_1132238287156183041424/artifact/do_1132238287156183041424_1614237121022.pdf","board": "CBSE","programId": "94564340-7737-11eb-96e0-29a9f8ed81cf"},{"ownershipType": ["createdBy"],"parent": "do_1132833371214970881710","unitIdentifiers": ["do_11322165488232038412588"],"copyright": "2021 MIT","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1132216902566133761410-latest","plugins": [{"identifier": "org.sunbird.questionunit.quml","semanticVersion": "1.1"}],"subject": ["Environmental Studies"],"channel": "01309282781705830427","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132216902566133761410/mcqmcq_1613975872529_do_1132216902566133761410_1.0.ecar","language": ["English"],"source": "https://dock.sunbirded.org/api/content/v1/read/do_11322168163282944012605","mimeType": "application/vnd.ekstep.ecml-archive","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132216902566133761410/mcqmcq_1613975873161_do_1132216902566133761410_1.0_spine.ecar","size": 17182.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Class 10"],"primaryCategory": "Exam Question","appId": "dev.dock.portal","contentEncoding": "gzip","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_1132216902566133761410/artifact/1613975740738_do_11322168163282944012605.zip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-02-22T06:37:55.328+0000","contentType": "Resource","se_gradeLevels": ["Class 10"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132216902566133761410","audience": ["Student"],"visibility": "Default","author": "color4","maxQuestions": 1,"consumerId": "7411b6bd-89f3-40ec-98d1-229dc64ce77d","learningOutcome": ["Understand the importance of values in life"],"index": 3,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "ae94b68c-a535-4dce-8e7a-fb9662b0ad68","version": 2,"se_subjects": ["Environmental Studies"],"license": "CC BY 4.0","prevState": "Review","size": 370363.0,"lastPublishedOn": "2021-02-22T06:37:52.529+0000","name": "MCQMCQ","topic": ["Animals"],"status": "Live","code": "0cbae0f8-e3eb-1d31-e2e5-0337dc7d697d","credentials": {"enabled": "No"},"prevStatus": "Processing","origin": "do_11322168163282944012605","streamingUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1132216902566133761410-latest","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-02-22T06:37:41.405+0000","se_boards": ["CBSE"],"processId": "fbcec2af-cb7a-4ed1-8683-ff04b475947e","contentDisposition": "inline","lastUpdatedOn": "2021-02-22T06:37:52.447+0000","originData": {"identifier": "do_11322168163282944012605","repository": "https://dock.sunbirded.org/api/content/v1/read/do_11322168163282944012605"},"collectionId": "do_11322165488181248012584","dialcodeRequired": "No","editorVersion": 3,"lastStatusChangedOn": "2021-02-22T06:37:55.314+0000","creator": "color4","os": ["All"],"questionCategories": ["MCQ"],"cloudStorageKey": "content/do_1132216902566133761410/artifact/1613975740738_do_11322168163282944012605.zip","se_FWIds": ["ekstep_ncert_k-12"],"marks": "1","bloomsLevel": ["Understand"],"pkgVersion": 1.0,"versionKey": "1613975872447","idealScreenDensity": "hdpi","framework": "ekstep_ncert_k-12","depth": 5,"s3Key": "ecar_files/do_1132216902566133761410/mcqmcq_1613975872529_do_1132216902566133761410_1.0.ecar","lastSubmittedOn": "2021-02-22T06:37:51.179+0000","createdBy": "0ce5b67e-b48e-489b-a818-e938e8bfc14b","se_topics": ["Animals"],"compatibilityLevel": 1,"itemSetPreviewUrl": "https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/do_11322168163282944012605/artifact/do_11322168163282944012605_1613975739805.pdf","board": "CBSE","programId": "b2433a00-74cd-11eb-9f3c-f39a9ab9f5ce"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.464+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "Yes","identifier": "do_1132833371214970881710","lastStatusChangedOn": "2021-05-20T08:58:33.464+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113464","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 4,"compatibilityLevel": 1,"name": "dsffgdg","topic": [],"status": "Draft"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.468+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "No","identifier": "do_1132833371215298561714","lastStatusChangedOn": "2021-05-20T08:58:33.468+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113468","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 3,"compatibilityLevel": 1,"name": "5.2.1 Respiratory System","topic": ["Look and say","Role Of The Sense Organs"],"status": "Draft"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.476+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "No","identifier": "do_1132833371215953921722","lastStatusChangedOn": "2021-05-20T08:58:33.476+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 2,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113476","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 2,"compatibilityLevel": 1,"name": "5.2 Organ Systems","topic": [],"status": "Draft"},{"ownershipType": ["createdBy"],"parent": "do_2222","copyright": "Sunbird","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132344630588948481134/test-874-kb.mp4","subject": ["Math"],"channel": "b00bc992ef25f1a9a8d63291e20efc8d","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132344630588948481134/untitled-content_1615535618825_do_1132344630588948481134_2.0.ecar","organisation": ["Sunbird"],"showNotification": true,"language": ["English"],"mimeType": "video/mp4","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132344630588948481134/untitled-content_1615535619590_do_1132344630588948481134_2.0_spine.ecar","size": 35301.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Grade 1"],"appIcon": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_1132344630588948481134/artifact/2a4b8abd789184932399d222d03d9b5c.thumb.jpg","primaryCategory": "Learning Resource","appId": "dev.sunbird.portal","contentEncoding": "identity","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132344630588948481134/test-874-kb.mp4","lockKey": "1d28d983-2704-44bd-803e-5feb4e62da62","sYS_INTERNAL_LAST_UPDATED_ON": "2021-03-12T08:10:34.367+0000","contentType": "Resource","se_gradeLevels": ["Grade 1"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132344630588948481134","lastUpdatedBy": "95e4942d-cbe8-477d-aebd-ad8e6de4bfc8","audience": ["Student"],"visibility": "Default","consumerId": "273f3b18-5dda-4a27-984a-060c7cd398d3","index": 3,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "8454cb21-3ce9-4e30-85b5-fade097880d8","version": 2,"se_subjects": ["Math"],"license": "CC BY 4.0","prevState": "Review","size": 883817.0,"lastPublishedOn": "2021-03-12T07:53:38.825+0000","name": "Untitled Content","status": "Live","code": "8851e754-6e20-44d4-9070-e1a9664163ad","credentials": {"enabled": "No"},"prevStatus": "Review","description": "updated desrciption","streamingUrl": "https://sunbirddevmedia-inct.streaming.media.azure.net/40ae07aa-069e-4056-8f2b-014bc9a2d21b/test-874-kb.ism/manifest(format=m3u8-aapl-v3)","medium": ["English"],"posterImage": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11299104587967692816/artifact/2a4b8abd789184932399d222d03d9b5c.jpg","idealScreenSize": "normal","createdOn": "2021-03-12T07:44:01.371+0000","se_boards": ["NCERT"],"copyrightYear": 2020,"contentDisposition": "inline","licenseterms": "By creating any type of content (resources, books, courses etc.) on DIKSHA, you consent to publish it under the Creative Commons License Framework. Please choose the applicable creative commons license you wish to apply to your content.","lastUpdatedOn": "2021-03-12T07:53:38.505+0000","dialcodeRequired": "No","lastStatusChangedOn": "2021-03-12T07:53:38.494+0000","createdFor": ["ORG_001"],"creator": "Reviewer User","os": ["All"],"se_FWIds": ["NCFCOPY"],"pkgVersion": 2.0,"versionKey": "1615535618583","idealScreenDensity": "hdpi","framework": "NCFCOPY","depth": 2,"s3Key": "ecar_files/do_1132344630588948481134/untitled-content_1615535618825_do_1132344630588948481134_2.0.ecar","lastSubmittedOn": "2021-03-12T07:53:10.005+0000","createdBy": "95e4942d-cbe8-477d-aebd-ad8e6de4bfc8","compatibilityLevel": 1,"board": "NCERT","resourceType": "Learn"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.470+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "No","identifier": "do_2222","lastStatusChangedOn": "2021-05-20T08:58:33.470+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113470","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 1,"compatibilityLevel": 1,"name": "5. Human Body","topic": [],"status": "Draft"}],"appId": "dev.sunbird.portal","contentEncoding": "gzip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-05-20T09:12:06.988+0000","contentType": "TextBook","trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1111","audience": ["Student"],"visibility": "Default","consumerId": "01814e02-fc27-4165-ae53-3d1816e55817","childNodes": ["do_1132339274094346241120","do_1132833371215872001720","do_1132833371215134721712","do_2222","do_113223967141863424174","do_1132833371214970881710","do_1132833371215708161718","do_1132372524622561281279","do_1132338069147811841118","do_1132833371215298561714","do_1132833371215953921722","do_11322383952751820816","do_1132216902566133761410","do_1132344630588948481134"],"discussionForum": {"enabled": "Yes"},"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"version": 2,"license": "CC BY 4.0","name": "TestCSVUpload","status": "Draft","code": "org.sunbird.yhqB6L","credentials": {"enabled": "No"},"description": "Enter description for TextBook","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-05-19T15:00:44.279+0000","contentDisposition": "inline","additionalCategories": ["Textbook"],"lastUpdatedOn": "2021-05-20T07:10:32.805+0000","dialcodeRequired": "No","lastStatusChangedOn": "2021-05-19T15:00:44.279+0000","createdFor": ["0126825293972439041"],"creator": "Book Creator","os": ["All"],"versionKey": "1621501113536","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 0,"createdBy": "8454cb21-3ce9-4e30-85b5-fade097880d8","compatibilityLevel": 1,"userConsent": "Yes","board": "State (Tamil Nadu)","resourceType": "Book"}""".stripMargin + val response = new Response + response.put("hierarchy", hierarchyString) + } + } \ No newline at end of file From b0734f2daab7af50e8eb95e1a0c308fd1fe963b7 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Mon, 25 Apr 2022 21:35:20 +0530 Subject: [PATCH 013/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- .../sunbird/content/dial/DIALManager.scala | 16 +++++--- .../content/dial/DIALManagerTest.scala | 41 +++++++++++++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 100e688b1..9365e136e 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -140,9 +140,7 @@ object DIALManager { val childrenDIALMap = getChildrenDIALMap(updatedChildrenHierarchy, requestMap) val consolidatedUnitDIALMap = if (!requestMap.contains(objectId)) childrenDIALMap else childrenDIALMap ++ Map(objectId -> requestMap(objectId)) - val duplicateDIALCodes: Map[String, Set[String]] = validateDuplicateDIALCodes(consolidatedUnitDIALMap.filter(rec => rec._2.asInstanceOf[List[String]].nonEmpty)) - if (duplicateDIALCodes.nonEmpty) - throw new ClientException(DIALErrors.ERR_DUPLICATE_DIAL_CODES, DIALErrors.ERR_DUPLICATE_DIAL_CODES_MSG + duplicateDIALCodes) + validateDuplicateDIALCodes(consolidatedUnitDIALMap.filter(rec => rec._2.asInstanceOf[List[String]].nonEmpty)) val updatedHierarchy = new java.util.HashMap[String, AnyRef]() updatedHierarchy.put("identifier", objectId) @@ -246,7 +244,15 @@ object DIALManager { }).filter(msg => msg.nonEmpty).flatten.toMap[String, AnyRef] } - def validateDuplicateDIALCodes(unitDIALCodesMap: Map[String, AnyRef]): Map[String, Set[String]] = { - unitDIALCodesMap.groupBy(_._2).collect { case (key, group: Map[String, AnyRef]) if group.size > 1 => (key.asInstanceOf[List[String]].head, group.keySet) } + def validateDuplicateDIALCodes(unitDIALCodesMap: Map[String, AnyRef]): Unit = { + val duplicateDIALCodes = unitDIALCodesMap.flatMap(mapRec => mapRec._2.asInstanceOf[List[String]].flatMap(listRec => { + val dupUnitsList: List[String] = unitDIALCodesMap.flatMap(loopMapRec => if(loopMapRec._1 != mapRec._1 && loopMapRec._2.asInstanceOf[List[String]].contains(listRec)) { + List(loopMapRec._1, mapRec._1) + } else List.empty[String]).filter(unitRec => unitRec.nonEmpty).toList + Map(listRec -> dupUnitsList) + })).filter(unitRec => unitRec._2.nonEmpty) + + if (duplicateDIALCodes.nonEmpty) + throw new ClientException(DIALErrors.ERR_DUPLICATE_DIAL_CODES, DIALErrors.ERR_DUPLICATE_DIAL_CODES_MSG + duplicateDIALCodes) } } diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index 86fef60ff..8895136f7 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -216,6 +216,14 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory }) } + "validateDuplicateDIALCodes with duplicate dial codes" should "throw client exception" in { + val exception = intercept[ClientException] { + DIALManager.validateDuplicateDIALCodes(Map("do_2222" -> List("E8B7Z6", "R4X2P2"), "do_1111" -> List("N4Z7D5", "E8B7Z6", "L4A6W8", "D2E1J9", "R4X2P2"))) + } + println("validateDuplicateDIALCodes:: exception:: " + exception.getMessage) + assert(exception.getErrCode == "ERR_DUPLICATE_DIAL_CODES") + } + def getDIALSearchResponse:Response = { val resString = "{\n \"id\": \"sunbird.dialcode.search\",\n \"ver\": \"3.0\",\n \"ts\": \"2020-04-21T19:39:14ZZ\",\n \"params\": {\n \"resmsgid\": \"1dfcc25b-6c37-49f8-a6c3-7185063e8752\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"dialcodes\": [\n {\n \"dialcode_index\": 7609876,\n \"identifier\": \"N4Z7D5\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.603+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610113,\n \"identifier\": \"E8B7Z6\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.635+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610117,\n \"identifier\": \"R4X2P2\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.637+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610961,\n \"identifier\": \"L4A6W8\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.734+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7611164,\n \"identifier\": \"D2E1J9\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.759+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n }\n ],\n \"count\": 5\n }\n}"; JsonUtils.deserialize(resString, classOf[Response]) @@ -365,6 +373,39 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory node } + def getCollectionDuplicateDIALRequest(): Request = { + val request = new Request() + request.setObjectType("Content") + request.setContext(getContext()) + request.getContext.put("linkType","collection") + request.getContext.put("identifier","do_1111") + + val reqMap : java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ + put("content", new util.ArrayList[util.Map[String, AnyRef]](){{ + add(new util.HashMap[String, AnyRef](){{ + put("identifier","do_1111") + put("dialcode", new util.ArrayList[String](){{ + add("N4Z7D5") + add("E8B7Z6") + add("L4A6W8") + add("D2E1J9") + add("R4X2P2") + }}) + }}) + add(new util.HashMap[String, AnyRef](){{ + put("identifier",new util.ArrayList[String](){{ + add("do_2222") + }}) + put("dialcode", "R4X2P2") + }}) + + }}) + }} + + request.putAll(reqMap) + request + } + private def getCategoryDefinitionNode(identifier: String): Node = { val node = new Node() node.setIdentifier(identifier) From f06382be4ef4a09caad67df52403a0b168830946 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Mon, 25 Apr 2022 21:54:50 +0530 Subject: [PATCH 014/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- .../content/dial/DIALManagerTest.scala | 84 ++++++++++++++++--- 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index 8895136f7..0ddc60dac 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -184,15 +184,12 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) val request = getContentDIALRequest() - println("DIALManagerTest:: link content:: request:: " + request) - DIALManager.link(request).map(result => { assert(result.getResponseCode.toString=="OK") }) } - "link DIAL with valid request for collections" should "update the collection content successfully" in { - + "link DIAL with valid request for collections" should "update the collection successfully" in { (oec.httpUtil _).expects().returns(httpUtil) (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse) @@ -208,8 +205,6 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory val request = getCollectionDIALRequest() - println("DIALManagerTest:: link collection:: request:: " + request) - val response = DIALManager.link(request) response.map(result => { assert(result.getResponseCode.toString=="OK") @@ -220,10 +215,51 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory val exception = intercept[ClientException] { DIALManager.validateDuplicateDIALCodes(Map("do_2222" -> List("E8B7Z6", "R4X2P2"), "do_1111" -> List("N4Z7D5", "E8B7Z6", "L4A6W8", "D2E1J9", "R4X2P2"))) } - println("validateDuplicateDIALCodes:: exception:: " + exception.getMessage) assert(exception.getErrCode == "ERR_DUPLICATE_DIAL_CODES") } + "link DIAL with valid node invalid unit Id for collections" should "update the collection partially" in { + (oec.httpUtil _).expects().returns(httpUtil) + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse) + + val nodes: util.List[Node] = getCategoryNode() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes() + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode("do_1111"))).anyNumberOfTimes() + (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) + (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())) + (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) + + val request = getCollectionPartialSuccessRequest() + + val response = DIALManager.link(request) + response.map(result => { + assert(result.getResponseCode.toString=="PARTIAL_SUCCESS") + }) + } + + "link DIAL with invalid unit Id request for collection" should "respond with Resource not found message" in { + (oec.httpUtil _).expects().returns(httpUtil) + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getDIALSearchResponse) + + val nodes: util.List[Node] = getCategoryNode() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes() + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode("do_1111"))).anyNumberOfTimes() + (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())) + + val request = getCollectionRNFRequest() + + val response = DIALManager.link(request) + response.map(result => { + assert(result.getResponseCode.toString=="RESOURCE_NOT_FOUND") + }) + } + def getDIALSearchResponse:Response = { val resString = "{\n \"id\": \"sunbird.dialcode.search\",\n \"ver\": \"3.0\",\n \"ts\": \"2020-04-21T19:39:14ZZ\",\n \"params\": {\n \"resmsgid\": \"1dfcc25b-6c37-49f8-a6c3-7185063e8752\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"dialcodes\": [\n {\n \"dialcode_index\": 7609876,\n \"identifier\": \"N4Z7D5\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.603+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610113,\n \"identifier\": \"E8B7Z6\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.635+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610117,\n \"identifier\": \"R4X2P2\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.637+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610961,\n \"identifier\": \"L4A6W8\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.734+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7611164,\n \"identifier\": \"D2E1J9\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.759+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n }\n ],\n \"count\": 5\n }\n}"; JsonUtils.deserialize(resString, classOf[Response]) @@ -373,7 +409,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory node } - def getCollectionDuplicateDIALRequest(): Request = { + def getCollectionPartialSuccessRequest(): Request = { val request = new Request() request.setObjectType("Content") request.setContext(getContext()) @@ -389,12 +425,11 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory add("E8B7Z6") add("L4A6W8") add("D2E1J9") - add("R4X2P2") }}) }}) add(new util.HashMap[String, AnyRef](){{ put("identifier",new util.ArrayList[String](){{ - add("do_2222") + add("do_22223") }}) put("dialcode", "R4X2P2") }}) @@ -406,6 +441,35 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory request } + def getCollectionRNFRequest(): Request = { + val request = new Request() + request.setObjectType("Content") + request.setContext(getContext()) + request.getContext.put("linkType","collection") + request.getContext.put("identifier","do_1111") + + val reqMap : java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ + put("content", new util.ArrayList[util.Map[String, AnyRef]](){{ + add(new util.HashMap[String, AnyRef](){{ + put("identifier",new util.ArrayList[String](){{ + add("do_22223") + }}) + put("dialcode", new util.ArrayList[String](){{ + add("N4Z7D5") + add("E8B7Z6") + add("L4A6W8") + add("D2E1J9") + add("R4X2P2") + }}) + }}) + + }}) + }} + + request.putAll(reqMap) + request + } + private def getCategoryDefinitionNode(identifier: String): Node = { val node = new Node() node.setIdentifier(identifier) From 72e467fcd471278d95a1cf2e5f0a744002e1c621 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 26 Apr 2022 10:35:08 +0530 Subject: [PATCH 015/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- .../search/client/ElasticSearchUtil.java | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java index 8d725f96c..ac54818bd 100644 --- a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java +++ b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java @@ -238,7 +238,7 @@ public static String getDocumentAsStringById(String indexName, String documentTy } public static List getMultiDocumentAsStringByIdList(String indexName, String documentType, - List documentIdList) throws IOException { + List documentIdList) throws IOException { List finalResult = new ArrayList(); MultiGetRequest request = new MultiGetRequest(); documentIdList.forEach(docId -> request.add(indexName, documentType, docId)); @@ -279,7 +279,7 @@ public static void bulkIndexWithIndexId(String indexName, String documentType, M } public static void bulkIndexWithAutoGenerateIndexId(String indexName, String documentType, - List> jsonObjects) + List> jsonObjects) throws Exception { if (isIndexExists(indexName)) { RestHighLevelClient client = getClient(indexName); @@ -305,7 +305,7 @@ public static void bulkIndexWithAutoGenerateIndexId(String indexName, String doc @SuppressWarnings("rawtypes") public static List textSearch(Class objectClass, Map matchCriterias, String indexName, - String indexType, int limit) throws Exception { + String indexType, int limit) throws Exception { SearchResponse result = search(matchCriterias, null, indexName, indexType, null, false, limit); return getDocumentsFromSearchResult(result, objectClass); } @@ -342,7 +342,9 @@ public static List getDocumentsFromHitsWithScore(SearchHits hits) { } @SuppressWarnings({ "rawtypes" }) - public static List textSearchReturningId(Map matchCriterias, String indexName, String indexType) throws Exception { + public static List textSearchReturningId(Map matchCriterias, String indexName, + String indexType) + throws Exception { SearchResponse result = search(matchCriterias, null, indexName, indexType, null, false, 100); return getDocumentsFromSearchResultWithId(result); } @@ -366,13 +368,14 @@ public static List getDocumentsFromHitsWithId(SearchHits hits) { @SuppressWarnings({ "rawtypes" }) public static List wildCardSearch(Class objectClass, String textKeyWord, String wordWildCard, - String indexName, String indexType, int limit) throws Exception { + String indexName, String indexType, int limit) throws Exception { SearchResponse result = wildCardSearch(textKeyWord, wordWildCard, indexName, indexType, limit); return getDocumentsFromSearchResult(result, objectClass); } public static SearchResponse wildCardSearch(String textKeyWord, String wordWildCard, String indexName, - String indexType, int limit) throws Exception { + String indexType, int limit) + throws Exception { SearchSourceBuilder query = buildJsonForWildCardQuery(textKeyWord, wordWildCard, indexName); query.size(limit); return search(indexName, indexType, query); @@ -380,15 +383,16 @@ public static SearchResponse wildCardSearch(String textKeyWord, String wordWildC @SuppressWarnings({ "rawtypes" }) public static List textFiltersSearch(Class objectClass, Map searchCriteria, - Map textFiltersMap, String indexName, String indexType, int limit) throws Exception { + Map textFiltersMap, String indexName, String indexType, int limit) + throws Exception { SearchResponse result = search(searchCriteria, textFiltersMap, indexName, indexType, null, false, limit); return getDocumentsFromSearchResult(result, objectClass); } @SuppressWarnings("rawtypes") public static Map textFiltersGroupBySearch(Class objectClass, Map searchCriteria, - Map textFiltersMap, List> groupByList, String indexName, - String indexType) throws Exception { + Map textFiltersMap, List> groupByList, String indexName, + String indexType) throws Exception { SearchResponse result = search(searchCriteria, textFiltersMap, indexName, indexType, groupByList, false, resultLimit); List documents = getDocumentsFromSearchResult(result, objectClass); @@ -404,28 +408,30 @@ public static Map textFiltersGroupBySearch(Class objectClass, Ma @SuppressWarnings("rawtypes") public static List textSearch(Class objectClass, Map matchCriterias, - Map textFiltersMap, String indexName, String indexType) throws Exception { + Map textFiltersMap, String indexName, String indexType) throws Exception { SearchResponse result = search(matchCriterias, textFiltersMap, indexName, indexType, null, false, resultLimit); return getDocumentsFromSearchResult(result, objectClass); } @SuppressWarnings("rawtypes") public static List textSearch(Class objectClass, Map matchCriterias, - Map textFiltersMap, String indexName, String indexType, - List> groupByList, int limit) throws Exception { - SearchResponse result = search(matchCriterias, textFiltersMap, indexName, indexType, groupByList, false, limit); + Map textFiltersMap, String indexName, String indexType, + List> groupByList, int limit) throws Exception { + SearchResponse result = search(matchCriterias, textFiltersMap, indexName, indexType, groupByList, false, + limit); return getDocumentsFromSearchResult(result, objectClass); } public static SearchResponse search(Map matchCriterias, Map textFiltersMap, - String indexName, String indexType, List> groupBy, boolean isDistinct, int limit) + String indexName, String indexType, List> groupBy, boolean isDistinct, int limit) throws Exception { SearchSourceBuilder query = buildJsonForQuery(matchCriterias, textFiltersMap, groupBy, isDistinct, indexName); query.size(limit); return search(indexName, indexType, query); } - public static SearchResponse search(String indexName, String indexType, SearchSourceBuilder query) throws Exception { + public static SearchResponse search(String indexName, String indexType, SearchSourceBuilder query) + throws Exception { return getClient(indexName).search(new SearchRequest(indexName).source(query), RequestOptions.DEFAULT); } @@ -499,7 +505,8 @@ public static Map getCountFromAggregation(Aggregations aggregati @SuppressWarnings("rawtypes") public static Map getCountOfSearch(Class objectClass, Map matchCriterias, - String indexName, String indexType, List> groupByList, int limit) throws Exception { + String indexName, String indexType, List> groupByList, int limit) + throws Exception { SearchResponse result = search(matchCriterias, null, indexName, indexType, groupByList, false, limit); Aggregations aggregations = result.getAggregations(); return getCountFromAggregation(aggregations, groupByList); @@ -507,7 +514,7 @@ public static Map getCountOfSearch(Class objectClass, Map getDistinctCountOfSearch(Map matchCriterias, String IndexName, - String IndexType, List> groupByList) throws Exception { + String IndexType, List> groupByList) throws Exception { Map countMap = new HashMap(); SearchResponse result = search(matchCriterias, null, IndexName, IndexType, groupByList, true, 0); Aggregations aggregations = result.getAggregations(); @@ -536,8 +543,8 @@ public static Map getDistinctCountOfSearch(Map m @SuppressWarnings("unchecked") public static SearchSourceBuilder buildJsonForQuery(Map matchCriterias, - Map textFiltersMap, List> groupByList, boolean isDistinct, - String indexName) { + Map textFiltersMap, List> groupByList, boolean isDistinct, + String indexName) { SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); @@ -594,7 +601,8 @@ public static SearchSourceBuilder buildJsonForQuery(Map matchCri return searchSourceBuilder; } - private static SearchSourceBuilder buildJsonForWildCardQuery(String textKeyWord, String wordWildCard, String indexName) { + private static SearchSourceBuilder buildJsonForWildCardQuery(String textKeyWord, String wordWildCard, + String indexName) { return new SearchSourceBuilder().query(QueryBuilders.wildcardQuery(textKeyWord, wordWildCard)); } From 0bf890492e1ab752f38f715e5cfd81a76db895d9 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 26 Apr 2022 10:37:14 +0530 Subject: [PATCH 016/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- .../org/sunbird/search/client/ElasticSearchUtil.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java index ac54818bd..eb87683f8 100644 --- a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java +++ b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java @@ -238,7 +238,7 @@ public static String getDocumentAsStringById(String indexName, String documentTy } public static List getMultiDocumentAsStringByIdList(String indexName, String documentType, - List documentIdList) throws IOException { + List documentIdList) throws IOException { List finalResult = new ArrayList(); MultiGetRequest request = new MultiGetRequest(); documentIdList.forEach(docId -> request.add(indexName, documentType, docId)); @@ -279,7 +279,7 @@ public static void bulkIndexWithIndexId(String indexName, String documentType, M } public static void bulkIndexWithAutoGenerateIndexId(String indexName, String documentType, - List> jsonObjects) + List> jsonObjects) throws Exception { if (isIndexExists(indexName)) { RestHighLevelClient client = getClient(indexName); @@ -305,7 +305,7 @@ public static void bulkIndexWithAutoGenerateIndexId(String indexName, String doc @SuppressWarnings("rawtypes") public static List textSearch(Class objectClass, Map matchCriterias, String indexName, - String indexType, int limit) throws Exception { + String indexType, int limit) throws Exception { SearchResponse result = search(matchCriterias, null, indexName, indexType, null, false, limit); return getDocumentsFromSearchResult(result, objectClass); } @@ -343,7 +343,7 @@ public static List getDocumentsFromHitsWithScore(SearchHits hits) { @SuppressWarnings({ "rawtypes" }) public static List textSearchReturningId(Map matchCriterias, String indexName, - String indexType) + String indexType) throws Exception { SearchResponse result = search(matchCriterias, null, indexName, indexType, null, false, 100); return getDocumentsFromSearchResultWithId(result); @@ -368,7 +368,7 @@ public static List getDocumentsFromHitsWithId(SearchHits hits) { @SuppressWarnings({ "rawtypes" }) public static List wildCardSearch(Class objectClass, String textKeyWord, String wordWildCard, - String indexName, String indexType, int limit) throws Exception { + String indexName, String indexType, int limit) throws Exception { SearchResponse result = wildCardSearch(textKeyWord, wordWildCard, indexName, indexType, limit); return getDocumentsFromSearchResult(result, objectClass); } From 173a091c6ab93f629f286a11779b0a61a23ceca8 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 26 Apr 2022 10:39:12 +0530 Subject: [PATCH 017/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- .../main/java/org/sunbird/search/client/ElasticSearchUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java index eb87683f8..2f51c7cc9 100644 --- a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java +++ b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java @@ -238,7 +238,7 @@ public static String getDocumentAsStringById(String indexName, String documentTy } public static List getMultiDocumentAsStringByIdList(String indexName, String documentType, - List documentIdList) throws IOException { + List documentIdList) throws IOException { List finalResult = new ArrayList(); MultiGetRequest request = new MultiGetRequest(); documentIdList.forEach(docId -> request.add(indexName, documentType, docId)); From d6cc670de32767169243f78aa561e2311850f2e7 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 26 Apr 2022 10:41:13 +0530 Subject: [PATCH 018/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- .../java/org/sunbird/search/client/ElasticSearchUtil.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java index 2f51c7cc9..cb9c4c086 100644 --- a/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java +++ b/search-api/search-core/src/main/java/org/sunbird/search/client/ElasticSearchUtil.java @@ -279,7 +279,7 @@ public static void bulkIndexWithIndexId(String indexName, String documentType, M } public static void bulkIndexWithAutoGenerateIndexId(String indexName, String documentType, - List> jsonObjects) + List> jsonObjects) throws Exception { if (isIndexExists(indexName)) { RestHighLevelClient client = getClient(indexName); @@ -305,7 +305,7 @@ public static void bulkIndexWithAutoGenerateIndexId(String indexName, String doc @SuppressWarnings("rawtypes") public static List textSearch(Class objectClass, Map matchCriterias, String indexName, - String indexType, int limit) throws Exception { + String indexType, int limit) throws Exception { SearchResponse result = search(matchCriterias, null, indexName, indexType, null, false, limit); return getDocumentsFromSearchResult(result, objectClass); } @@ -343,7 +343,7 @@ public static List getDocumentsFromHitsWithScore(SearchHits hits) { @SuppressWarnings({ "rawtypes" }) public static List textSearchReturningId(Map matchCriterias, String indexName, - String indexType) + String indexType) throws Exception { SearchResponse result = search(matchCriterias, null, indexName, indexType, null, false, 100); return getDocumentsFromSearchResultWithId(result); @@ -368,7 +368,7 @@ public static List getDocumentsFromHitsWithId(SearchHits hits) { @SuppressWarnings({ "rawtypes" }) public static List wildCardSearch(Class objectClass, String textKeyWord, String wordWildCard, - String indexName, String indexType, int limit) throws Exception { + String indexName, String indexType, int limit) throws Exception { SearchResponse result = wildCardSearch(textKeyWord, wordWildCard, indexName, indexType, limit); return getDocumentsFromSearchResult(result, objectClass); } From 1a80b02668d8dd8214d373e61961b7ffb1489fe9 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 26 Apr 2022 10:42:34 +0530 Subject: [PATCH 019/105] Issue #SB-19655 feat: Collection DIAL link API refactor from LP to KP --- .../org/sunbird/content/dial/DIALManagerTest.scala | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index 0ddc60dac..eac0e8686 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -358,20 +358,9 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory add(new util.HashMap[String, AnyRef](){{ put("identifier",new util.ArrayList[String](){{ add("do_2222") -// add("do_3333") }}) put("dialcode", "R4X2P2") }}) -// add(new util.HashMap[String, AnyRef](){{ -// put("identifier",new util.ArrayList[String](){{ -// add("do_4444") -// add("do_5555") -// }}) -// put("dialcode", new util.ArrayList[String](){{ -// add("L4A6W8") -// add("D2E1J9") -// }}) -// }}) }}) }} reqMap From c702e4a34eb6413fa5ac16c9bff5cead887cddc2 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 27 Apr 2022 11:55:26 +0530 Subject: [PATCH 020/105] Issue #SB-19655 feat: Collection DIAL link API refactoring from LP to KP --- .../sunbird/content/dial/DIALConstants.scala | 3 ++ .../sunbird/content/dial/DIALManager.scala | 52 +++++++++---------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALConstants.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALConstants.scala index be127079b..70d8f74da 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALConstants.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALConstants.scala @@ -16,5 +16,8 @@ object DIALConstants { val AUTHORIZATION: String = "Authorization" val X_CHANNEL_ID: String = "X-Channel-Id" val VERSION_KEY: String = "versionKey" + val DISCUSSION_FORUM: String = "discussionForum" + val CREDENTIALS: String = "credentials" + val TRACKABLE: String = "trackable" } \ No newline at end of file diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 9365e136e..08ecb4f24 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -127,15 +127,15 @@ object DIALManager { request.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) request.getContext.put(ContentConstants.VERSION, ContentConstants.SCHEMA_VERSION) request.put(ContentConstants.ROOT_ID, objectId) - request.put(ContentConstants.MODE, "edit") + request.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) val req = new Request(request) - req.put("identifier", request.get("rootId").asInstanceOf[String]) - req.put("mode", request.get("mode").asInstanceOf[String]) + req.put(ContentConstants.IDENTIFIER, objectId) + req.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) DataNode.read(req).flatMap(rootNode => { HierarchyManager.getHierarchy(request).flatMap(getHierarchyResponse => { val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - val childrenHierarchy = collectionHierarchy.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]] + val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]] val updatedChildrenHierarchy = updateChildrenHierarchy(childrenHierarchy, requestMap) val childrenDIALMap = getChildrenDIALMap(updatedChildrenHierarchy, requestMap) val consolidatedUnitDIALMap = if (!requestMap.contains(objectId)) childrenDIALMap else childrenDIALMap ++ Map(objectId -> requestMap(objectId)) @@ -143,22 +143,22 @@ object DIALManager { validateDuplicateDIALCodes(consolidatedUnitDIALMap.filter(rec => rec._2.asInstanceOf[List[String]].nonEmpty)) val updatedHierarchy = new java.util.HashMap[String, AnyRef]() - updatedHierarchy.put("identifier", objectId) - updatedHierarchy.put("children", updatedChildrenHierarchy.asJava) + updatedHierarchy.put(ContentConstants.IDENTIFIER, objectId) + updatedHierarchy.put(ContentConstants.CHILDREN, updatedChildrenHierarchy.asJava) val hierarchyReq = new Request(request) - hierarchyReq.put("hierarchy", ScalaJsonUtils.serialize(updatedHierarchy)) - hierarchyReq.put("identifier", rootNode.getIdentifier) + hierarchyReq.put(ContentConstants.HIERARCHY, ScalaJsonUtils.serialize(updatedHierarchy)) + hierarchyReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) oec.graphService.saveExternalProps(hierarchyReq).flatMap(rec => if(requestMap.contains(objectId)) { val updateReq = new Request(request) - updateReq.put("identifier", rootNode.getIdentifier) + updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) val rootNodeMetadata = rootNode.getMetadata - rootNodeMetadata.remove("discussionForum") - rootNodeMetadata.remove("credentials") - rootNodeMetadata.remove("trackable") + rootNodeMetadata.remove(DIALConstants.DISCUSSION_FORUM) + rootNodeMetadata.remove(DIALConstants.CREDENTIALS) + rootNodeMetadata.remove(DIALConstants.TRACKABLE) - if(rootNodeMetadata.containsKey("dialcodes")) - rootNodeMetadata.remove("dialcodes") + if(rootNodeMetadata.containsKey(DIALConstants.DIALCODES)) + rootNodeMetadata.remove(DIALConstants.DIALCODES) if(requestMap(objectId).isEmpty) updateReq.put(DIALConstants.DIALCODES, null) @@ -216,28 +216,28 @@ object DIALManager { def updateChildrenHierarchy(childrenHierarchy: util.List[util.Map[String, AnyRef]], requestMap: Map[String, List[String]]): List[util.Map[String, AnyRef]] = { childrenHierarchy.asScala.toList.map(child => { - if (requestMap.contains(child.get("identifier").toString) && StringUtils.equalsIgnoreCase("Parent", child.get("visibility").toString)) { - if (requestMap.getOrElse(child.get("identifier").toString, List.empty).nonEmpty && requestMap(child.get("identifier").toString).exists(rec => rec.trim.nonEmpty)) - child.put("dialcodes", requestMap(child.get("identifier").toString)) + if (requestMap.contains(child.get(ContentConstants.IDENTIFIER).toString) && StringUtils.equalsIgnoreCase("Parent", child.get(ContentConstants.VISIBILITY).toString)) { + if (requestMap.getOrElse(child.get(ContentConstants.IDENTIFIER).toString, List.empty).nonEmpty && requestMap(child.get(ContentConstants.IDENTIFIER).toString).exists(rec => rec.trim.nonEmpty)) + child.put(DIALConstants.DIALCODES, requestMap(child.get(ContentConstants.IDENTIFIER).toString)) else - child.remove("dialcodes") + child.remove(DIALConstants.DIALCODES) } - if(child.get("children")!=null) - updateChildrenHierarchy(child.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]], requestMap) + if(child.get(ContentConstants.CHILDREN)!=null) + updateChildrenHierarchy(child.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]], requestMap) child }) } def getChildrenDIALMap(childrenHierarchy: List[util.Map[String, AnyRef]], requestMap: Map[String, List[String]]): Map[String, AnyRef] = { childrenHierarchy.map(child => { - val subChildrenDIALMap = if(child.get("children")!=null) - getChildrenDIALMap(child.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList, requestMap) + val subChildrenDIALMap = if(child.get(ContentConstants.CHILDREN)!=null) + getChildrenDIALMap(child.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList, requestMap) else Map.empty[String, String] - val childDIALMap = if(requestMap.contains(child.get("identifier").toString) && child.get("dialcodes")!=null) - Map(child.get("identifier").toString -> child.get("dialcodes")) - else if(requestMap.contains(child.get("identifier").toString)) - Map(child.get("identifier").toString -> List.empty) + val childDIALMap = if(requestMap.contains(child.get(ContentConstants.IDENTIFIER).toString) && child.get(DIALConstants.DIALCODES)!=null) + Map(child.get(ContentConstants.IDENTIFIER).toString -> child.get(DIALConstants.DIALCODES)) + else if(requestMap.contains(child.get(ContentConstants.IDENTIFIER).toString)) + Map(child.get(ContentConstants.IDENTIFIER).toString -> List.empty) else Map.empty subChildrenDIALMap ++ childDIALMap From e3ceaf5a39195d1d9b48154052c5414c4418c0dc Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 27 Apr 2022 12:09:41 +0530 Subject: [PATCH 021/105] Issue #SB-19655 feat: Collection DIAL link API refactoring from LP to KP --- .../sunbird/content/dial/DIALManager.scala | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 08ecb4f24..a62dcfe28 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -122,18 +122,15 @@ object DIALManager { } def linkCollection(objectId: String, requestMap: Map[String, List[String]], reqContext: util.Map[String, AnyRef])(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - val request = new Request() - request.setContext(reqContext) - request.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) - request.getContext.put(ContentConstants.VERSION, ContentConstants.SCHEMA_VERSION) - request.put(ContentConstants.ROOT_ID, objectId) - request.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) - - val req = new Request(request) + val req = new Request() + req.setContext(reqContext) req.put(ContentConstants.IDENTIFIER, objectId) req.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) DataNode.read(req).flatMap(rootNode => { - HierarchyManager.getHierarchy(request).flatMap(getHierarchyResponse => { + req.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) + req.getContext.put(ContentConstants.VERSION, ContentConstants.SCHEMA_VERSION) + req.put(ContentConstants.ROOT_ID, objectId) + HierarchyManager.getHierarchy(req).flatMap(getHierarchyResponse => { val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]] val updatedChildrenHierarchy = updateChildrenHierarchy(childrenHierarchy, requestMap) @@ -146,11 +143,11 @@ object DIALManager { updatedHierarchy.put(ContentConstants.IDENTIFIER, objectId) updatedHierarchy.put(ContentConstants.CHILDREN, updatedChildrenHierarchy.asJava) - val hierarchyReq = new Request(request) + val hierarchyReq = new Request(req) hierarchyReq.put(ContentConstants.HIERARCHY, ScalaJsonUtils.serialize(updatedHierarchy)) hierarchyReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) oec.graphService.saveExternalProps(hierarchyReq).flatMap(rec => if(requestMap.contains(objectId)) { - val updateReq = new Request(request) + val updateReq = new Request(req) updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) val rootNodeMetadata = rootNode.getMetadata rootNodeMetadata.remove(DIALConstants.DISCUSSION_FORUM) From 696d0d3a7c0aa906e404173e051e4a176390f988 Mon Sep 17 00:00:00 2001 From: karthik-tarento Date: Fri, 6 May 2022 14:55:06 +0530 Subject: [PATCH 022/105] SB-29856 | Fix for hierarchy update --- .../managers/UpdateHierarchyManager.scala | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/content-api/hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala b/content-api/hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala index 01c245c6a..fbb73934a 100644 --- a/content-api/hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala +++ b/content-api/hierarchy-manager/src/main/scala/org/sunbird/managers/UpdateHierarchyManager.scala @@ -345,7 +345,7 @@ object UpdateHierarchyManager { if (MapUtils.isNotEmpty(childrenIdentifiersMap)) { val updatedNodeList = getTempNode(nodeList, rootId) :: List() updateHierarchyRelatedData(childrenIdentifiersMap.getOrElse(rootId, Map[String, Int]()), 1, - rootId, nodeList, childrenIdentifiersMap, updatedNodeList, request).map(finalEnrichedNodeList => { + rootId, nodeList, childrenIdentifiersMap, updatedNodeList, request, rootId).map(finalEnrichedNodeList => { TelemetryManager.info("Final enriched list size: " + finalEnrichedNodeList.size) val childNodeIds = finalEnrichedNodeList.map(node => node.getIdentifier.replaceAll(".img", "")).filterNot(id => StringUtils.containsIgnoreCase(rootId, id)).distinct TelemetryManager.info("Final enriched ids (childNodes): " + childNodeIds + " :: size: " + childNodeIds.size) @@ -368,7 +368,8 @@ object UpdateHierarchyManager { } @throws[Exception] - private def updateHierarchyRelatedData(childrenIds: Map[String, Int], depth: Int, parent: String, nodeList: List[Node], hierarchyStructure: Map[String, Map[String, Int]], enrichedNodeList: scala.collection.immutable.List[Node], request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[List[Node]] = { + private def updateHierarchyRelatedData(childrenIds: Map[String, Int], depth: Int, parent: String, nodeList: List[Node], hierarchyStructure: Map[String, Map[String, Int]], enrichedNodeList: scala.collection.immutable.List[Node], request: Request, rootId: String)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[List[Node]] = { + val rootResourceChange: Boolean = if (Platform.config.hasPath("hierarchyUpdate.allow.resource.at.root.level")) Platform.config.getBoolean("hierarchyUpdate.allow.resource.at.root.level") else false val futures = childrenIds.map(child => { val id = child._1 val index = child._2 + 1 @@ -378,13 +379,19 @@ object UpdateHierarchyManager { val nxtEnrichedNodeList = tempNode :: enrichedNodeList if (MapUtils.isNotEmpty(hierarchyStructure.getOrDefault(child._1, Map[String, Int]()))) updateHierarchyRelatedData(hierarchyStructure.getOrDefault(child._1, Map[String, Int]()), - tempNode.getMetadata.get(HierarchyConstants.DEPTH).asInstanceOf[Int] + 1, id, nodeList, hierarchyStructure, nxtEnrichedNodeList, request) + tempNode.getMetadata.get(HierarchyConstants.DEPTH).asInstanceOf[Int] + 1, id, nodeList, hierarchyStructure, nxtEnrichedNodeList, request, rootId) else Future(nxtEnrichedNodeList) } else { // TelemetryManager.info("Get ContentNode as TempNode is null for ID: " + id) getContentNode(id, HierarchyConstants.TAXONOMY_ID).map(node => { - val parentNode: Node = nodeList.find(p => p.getIdentifier.equals(parent)).orNull + val parentNode: Node = if (rootResourceChange && nodeList.find(p => p.getIdentifier.equals(parent)).orNull == null) { + if (nodeList.find(p => p.getIdentifier.equals(rootId)).orNull == null) + nodeList.find(p => p.getIdentifier.equals(rootId + ".img")).orNull + else + nodeList.find(p => p.getIdentifier.equals(rootId)).orNull + } else + nodeList.find(p => p.getIdentifier.equals(parent)).orNull val nxtEnrichedNodeList = if (null != parentNode) { TelemetryManager.info(s"ObjectType for $parent is ${parentNode.getObjectType}...") val parentMetadata: java.util.Map[String, AnyRef] = NodeUtil.serialize(parentNode, new java.util.ArrayList[String](), parentNode.getObjectType.toLowerCase, "1.0") @@ -401,7 +408,7 @@ object UpdateHierarchyManager { enrichedNodeList } if (MapUtils.isNotEmpty(hierarchyStructure.getOrDefault(id, Map[String, Int]()))) { - updateHierarchyRelatedData(hierarchyStructure.getOrDefault(id, Map[String, Int]()), node.getMetadata.get(HierarchyConstants.DEPTH).asInstanceOf[Int] + 1, id, nodeList, hierarchyStructure, nxtEnrichedNodeList, request) + updateHierarchyRelatedData(hierarchyStructure.getOrDefault(id, Map[String, Int]()), node.getMetadata.get(HierarchyConstants.DEPTH).asInstanceOf[Int] + 1, id, nodeList, hierarchyStructure, nxtEnrichedNodeList, request, rootId) } else Future(nxtEnrichedNodeList) }).flatMap(f => f) recoverWith { case e: CompletionException => throw e.getCause } From c57d1a236c5d0141fa4bde3fda7d01aedfe385c1 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 10 May 2022 13:34:07 +0530 Subject: [PATCH 023/105] Issue #SB-29808 debug: Review API failing --- .../mimetype/ecml/processor/LocalizeAssetProcessor.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/ecml/processor/LocalizeAssetProcessor.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/ecml/processor/LocalizeAssetProcessor.scala index d3d44e204..978cc60bd 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/ecml/processor/LocalizeAssetProcessor.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/ecml/processor/LocalizeAssetProcessor.scala @@ -2,12 +2,12 @@ package org.sunbird.mimetype.ecml.processor import java.io.{File, IOException} import java.net.URL - import org.apache.commons.io.{FileUtils, FilenameUtils} import org.apache.commons.lang3.StringUtils import org.sunbird.cloudstore.StorageService import org.sunbird.common.Platform import org.sunbird.common.exception.ClientException +import org.sunbird.telemetry.logger.TelemetryManager import scala.concurrent.{Await, ExecutionContext, Future} import scala.concurrent.duration.Duration @@ -62,6 +62,8 @@ trait LocalizeAssetProcessor extends IProcessor { } def downloadFile(downloadPath: String, fileUrl: String): File = try { + TelemetryManager.info("LocalizeAssetProcessor:: downloadFile:: downloadPath:: " + downloadPath) + TelemetryManager.info("LocalizeAssetProcessor:: downloadFile:: fileUrl:: " + fileUrl) createDirectory(downloadPath) val file = new File(downloadPath + File.separator + getFileNameFromURL(fileUrl)) FileUtils.copyURLToFile(new URL(fileUrl), file) From 66b16598d655e745a85afe241b07f58c8550b199 Mon Sep 17 00:00:00 2001 From: Kumar Gauraw Date: Fri, 27 May 2022 01:30:28 +0530 Subject: [PATCH 024/105] Issue #SB-26400 fix: Code fix for lastPublishedBy --- .../src/main/scala/org/sunbird/actors/QuestionActor.scala | 3 +++ .../main/scala/org/sunbird/actors/QuestionSetActor.scala | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionActor.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionActor.scala index 89d32184a..5e1eb12ca 100644 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionActor.scala +++ b/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionActor.scala @@ -58,8 +58,11 @@ class QuestionActor @Inject()(implicit oec: OntologyEngineContext) extends BaseA } def publish(request: Request): Future[Response] = { + val lastPublishedBy: String = request.getRequest.getOrDefault("lastPublishedBy", "").asInstanceOf[String] request.getRequest.put("identifier", request.getContext.get("identifier")) AssessmentManager.getValidatedNodeForPublish(request, "ERR_QUESTION_PUBLISH").map(node => { + if(StringUtils.isNotBlank(lastPublishedBy)) + node.getMetadata.put("lastPublishedBy", lastPublishedBy) AssessmentManager.pushInstructionEvent(node.getIdentifier, node) ResponseHandler.OK.putAll(Map[String, AnyRef]("identifier" -> node.getIdentifier.replace(".img", ""), "message" -> "Question is successfully sent for Publish").asJava) }) diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionSetActor.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionSetActor.scala index b4a68317c..797b684d9 100644 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionSetActor.scala +++ b/assessment-api/assessment-actors/src/main/scala/org/sunbird/actors/QuestionSetActor.scala @@ -1,8 +1,10 @@ package org.sunbird.actors import java.util + import javax.inject.Inject import org.apache.commons.collections4.CollectionUtils +import org.apache.commons.lang3.StringUtils import org.sunbird.`object`.importer.{ImportConfig, ImportManager} import org.sunbird.actor.core.BaseActor import org.sunbird.cache.impl.RedisCache @@ -65,13 +67,16 @@ class QuestionSetActor @Inject()(implicit oec: OntologyEngineContext) extends Ba } def publish(request: Request): Future[Response] = { + val lastPublishedBy: String = request.getRequest.getOrDefault("lastPublishedBy", "").asInstanceOf[String] request.getRequest.put("identifier", request.getContext.get("identifier")) request.put("mode", "edit") AssessmentManager.getValidatedNodeForPublish(request, "ERR_QUESTION_SET_PUBLISH").flatMap(node => { AssessmentManager.getQuestionSetHierarchy(request, node).map(hierarchyString => { AssessmentManager.validateQuestionSetHierarchy(hierarchyString.asInstanceOf[String], node.getMetadata.getOrDefault("createdBy", "").asInstanceOf[String]) + if(StringUtils.isNotBlank(lastPublishedBy)) + node.getMetadata.put("lastPublishedBy", lastPublishedBy) AssessmentManager.pushInstructionEvent(node.getIdentifier, node) - ResponseHandler.OK.putAll(Map[String, AnyRef]("identifier" -> node.getIdentifier.replace(".img", ""), "message" -> "Question is successfully sent for Publish").asJava) + ResponseHandler.OK.putAll(Map[String, AnyRef]("identifier" -> node.getIdentifier.replace(".img", ""), "message" -> "QuestionSet is successfully sent for Publish").asJava) }) }) } From 3b928954166ba403cfb4a553f3633208b22803f0 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 15 Jun 2022 19:02:05 +0530 Subject: [PATCH 025/105] Issue #SB-30307 fix: relational_metadata setting as string null --- .../scala/org/sunbird/content/actors/ContentActor.scala | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala index 16ebcc64d..7ad4e0dee 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala @@ -243,6 +243,12 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe "Yes".equalsIgnoreCase(node.getMetadata.getOrDefault("trackable", new java.util.HashMap[String, AnyRef]).asInstanceOf[java.util.Map[String, AnyRef]].getOrDefault("enabled", "").asInstanceOf[String])) { node.getMetadata.put("contentType", "Course") } + + //TODO: Below fix to be reviewed when the fix for null to Stringify in ExternalStore.scala is implemented + if(node.getExternalData != null && node.getExternalData.containsKey("relational_metadata") && node.getExternalData.get("relational_metadata") == null) { + node.getExternalData.put("relational_metadata", "{}") + } + node } From 89e77bc2931e3db9bd2ff58439147e8874a5bed0 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 15 Jun 2022 19:05:13 +0530 Subject: [PATCH 026/105] Issue #SB-30307 fix: relational_metadata setting as string null --- .../main/scala/org/sunbird/content/actors/ContentActor.scala | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala index 16ebcc64d..fabc95d43 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala @@ -243,6 +243,11 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe "Yes".equalsIgnoreCase(node.getMetadata.getOrDefault("trackable", new java.util.HashMap[String, AnyRef]).asInstanceOf[java.util.Map[String, AnyRef]].getOrDefault("enabled", "").asInstanceOf[String])) { node.getMetadata.put("contentType", "Course") } + + //TODO: Below fix to be reviewed when the fix for null to Stringify in ExternalStore.scala is implemented + if(node.getExternalData != null && node.getExternalData.containsKey("relational_metadata") && node.getExternalData.get("relational_metadata") == null) { + node.getExternalData.put("relational_metadata", "{}") + } node } From 079c080ac13bc181401a2726b353508331487de0 Mon Sep 17 00:00:00 2001 From: Kumar Gauraw Date: Mon, 27 Jun 2022 14:16:34 +0530 Subject: [PATCH 027/105] Issue #SB-30221 feat: added profile to build core components --- pom.xml | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index f3f14193a..2ce1e07bc 100644 --- a/pom.xml +++ b/pom.xml @@ -17,15 +17,34 @@ 3.0.8 2.9.8 - - platform-core - ontology-engine - content-api - assessment-api - taxonomy-api - platform-modules - search-api - + + + knowlg-platform + + true + + + platform-core + ontology-engine + content-api + assessment-api + taxonomy-api + platform-modules + search-api + + + + knowlg-core + + false + + + platform-core + ontology-engine + platform-modules/import-manager + + + From db528da02e6c842faeb1f7d5cc868096e51ab41b Mon Sep 17 00:00:00 2001 From: Kumar Gauraw Date: Tue, 28 Jun 2022 13:45:52 +0530 Subject: [PATCH 028/105] Issue #SB-26264 fix: Revert added dependency --- platform-modules/import-manager/pom.xml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/platform-modules/import-manager/pom.xml b/platform-modules/import-manager/pom.xml index 13c5fa70c..7914fcf5c 100644 --- a/platform-modules/import-manager/pom.xml +++ b/platform-modules/import-manager/pom.xml @@ -22,16 +22,6 @@ platform-telemetry 1.0-SNAPSHOT - - org.sunbird - mimetype-manager - 1.0-SNAPSHOT - - - org.sunbird - url-manager - 1.0-SNAPSHOT - org.sunbird graph-engine_2.11 From f4c9133a32cd08710a6e63893ed4972f35e1f823 Mon Sep 17 00:00:00 2001 From: Kumar Gauraw Date: Tue, 28 Jun 2022 16:47:44 +0530 Subject: [PATCH 029/105] Issue #SB-30221 fix: fixed build issue --- .../main/scala/org/sunbird/managers/CopyManager.scala | 11 ++++++----- .../main/scala/org/sunbird/utils/BranchingUtil.scala | 2 +- .../src/test/scala/org/sunbird/actors/CopySpec.scala | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/managers/CopyManager.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/managers/CopyManager.scala index dc73939e9..22aefc8f0 100644 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/managers/CopyManager.scala +++ b/assessment-api/assessment-actors/src/main/scala/org/sunbird/managers/CopyManager.scala @@ -1,8 +1,7 @@ package org.sunbird.managers -import org.apache.commons.collections.CollectionUtils +import org.apache.commons.collections4.CollectionUtils import org.apache.commons.collections4.MapUtils -import org.apache.commons.lang.StringUtils import org.sunbird.common.{JsonUtils, Platform} import org.sunbird.common.dto.{Request, Response, ResponseHandler} import org.sunbird.common.exception.{ClientException, ServerException} @@ -14,11 +13,13 @@ import org.sunbird.graph.schema.DefinitionNode import org.sunbird.graph.utils.{NodeUtil, ScalaJsonUtils} import org.sunbird.telemetry.logger.TelemetryManager import org.sunbird.utils.{AssessmentConstants, BranchingUtil, HierarchyConstants} - import java.util -import java.util.concurrent.{CompletionException} +import java.util.concurrent.CompletionException import java.util.{Optional, UUID} -import scala.collection.JavaConversions.{mapAsScalaMap} + +import org.apache.commons.lang3.StringUtils + +import scala.collection.JavaConversions.mapAsScalaMap import scala.collection.JavaConverters._ import scala.concurrent.{ExecutionContext, Future} diff --git a/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/BranchingUtil.scala b/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/BranchingUtil.scala index fa9098816..791079d42 100644 --- a/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/BranchingUtil.scala +++ b/assessment-api/assessment-actors/src/main/scala/org/sunbird/utils/BranchingUtil.scala @@ -1,6 +1,6 @@ package org.sunbird.utils -import org.apache.commons.lang.StringUtils +import org.apache.commons.lang3.StringUtils import org.sunbird.common.dto.Request import java.util diff --git a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/CopySpec.scala b/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/CopySpec.scala index 772a23d23..b5cbd725e 100644 --- a/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/CopySpec.scala +++ b/assessment-api/assessment-actors/src/test/scala/org/sunbird/actors/CopySpec.scala @@ -1,6 +1,6 @@ package org.sunbird.actors -import org.mortbay.util.StringUtil +import org.apache.commons.lang3.StringUtils import org.sunbird.common.dto.{Request, Response, ResponseParams} import org.sunbird.graph.dac.model.Node import org.sunbird.utils.AssessmentConstants @@ -105,7 +105,7 @@ object CopySpec { { put("code", "xyz") put("mimeType", { - if (StringUtil.endsWithIgnoreCase(objectType, AssessmentConstants.QUESTIONSET_SCHEMA_NAME)) { + if (StringUtils.endsWithIgnoreCase(objectType, AssessmentConstants.QUESTIONSET_SCHEMA_NAME)) { AssessmentConstants.QUESTIONSET_MIME_TYPE } else { AssessmentConstants.QUESTION_MIME_TYPE From 57574afa31c31ae81d543b158097f28a614dcf71 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 29 Jun 2022 11:08:36 +0530 Subject: [PATCH 030/105] Update ContentActor.scala --- .../src/main/scala/org/sunbird/content/actors/ContentActor.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala index c9bb0187b..fabc95d43 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala @@ -248,7 +248,6 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe if(node.getExternalData != null && node.getExternalData.containsKey("relational_metadata") && node.getExternalData.get("relational_metadata") == null) { node.getExternalData.put("relational_metadata", "{}") } - node } From 889040c424ec06f30a89aa42c42531287b09eed1 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 29 Jun 2022 11:09:34 +0530 Subject: [PATCH 031/105] Update LocalizeAssetProcessor.scala --- .../mimetype/ecml/processor/LocalizeAssetProcessor.scala | 3 --- 1 file changed, 3 deletions(-) diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/ecml/processor/LocalizeAssetProcessor.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/ecml/processor/LocalizeAssetProcessor.scala index 432f88773..629953a1a 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/ecml/processor/LocalizeAssetProcessor.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/ecml/processor/LocalizeAssetProcessor.scala @@ -7,7 +7,6 @@ import org.apache.commons.lang3.StringUtils import org.sunbird.cloudstore.StorageService import org.sunbird.common.Platform import org.sunbird.common.exception.ClientException -import org.sunbird.telemetry.logger.TelemetryManager import scala.concurrent.{Await, ExecutionContext, Future} import scala.concurrent.duration.Duration @@ -62,8 +61,6 @@ trait LocalizeAssetProcessor extends IProcessor { } def downloadFile(downloadPath: String, fileUrl: String): File = try { - TelemetryManager.info("LocalizeAssetProcessor:: downloadFile:: downloadPath:: " + downloadPath) - TelemetryManager.info("LocalizeAssetProcessor:: downloadFile:: fileUrl:: " + fileUrl) createDirectory(downloadPath) val file = new File(downloadPath + File.separator + getFileNameFromURL(fileUrl)) FileUtils.copyURLToFile(new URL(fileUrl), file) From 88d3ca9b5ad6b714b824b55024d659d940748a5a Mon Sep 17 00:00:00 2001 From: Kumar Gauraw Date: Wed, 29 Jun 2022 16:32:27 +0530 Subject: [PATCH 032/105] Issue #SB-30221 feat: fixed build issue --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2ce1e07bc..0558992df 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,7 @@ platform-core ontology-engine - platform-modules/import-manager + platform-modules From 65415159596b75e3eb7ae7f1027b79c6acb0c015 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 30 Jun 2022 14:57:40 +0530 Subject: [PATCH 033/105] Issue #SB-30154 feat: DIAL Link API refactoring debug. --- .../scala/org/sunbird/content/dial/DIALManager.scala | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index a62dcfe28..6bd706632 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -10,6 +10,7 @@ import org.sunbird.graph.dac.model.Node import org.sunbird.graph.nodes.DataNode import org.sunbird.graph.utils.ScalaJsonUtils import org.sunbird.managers.HierarchyManager +import org.sunbird.telemetry.logger.TelemetryManager import java.util import scala.collection.JavaConverters._ @@ -27,8 +28,11 @@ object DIALManager { val linkType: String = request.getContext.getOrDefault(DIALConstants.LINK_TYPE, DIALConstants.CONTENT).asInstanceOf[String] val channelId: String = request.getContext.getOrDefault(DIALConstants.CHANNEL, "").asInstanceOf[String] val objectId: String = request.getContext.getOrDefault(DIALConstants.IDENTIFIER, "").asInstanceOf[String] + TelemetryManager.info("DIALManager::link:: linkType: " + linkType + " || channelId: " + channelId + " || objectId: " + objectId) val reqList: List[Map[String, List[String]]] = getRequestData(request) + TelemetryManager.info("DIALManager::link:: reqList: " + reqList) val requestMap: Map[String, List[String]] = validateAndGetRequestMap(channelId, reqList) + TelemetryManager.info("DIALManager::link:: requestMap: " + requestMap) linkType match { case DIALConstants.CONTENT => linkContent(requestMap, request.getContext) case DIALConstants.COLLECTION => linkCollection(objectId, requestMap, request.getContext) @@ -126,17 +130,19 @@ object DIALManager { req.setContext(reqContext) req.put(ContentConstants.IDENTIFIER, objectId) req.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) + TelemetryManager.info("DIALManager::linkCollection:: req: " + req) DataNode.read(req).flatMap(rootNode => { req.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) req.getContext.put(ContentConstants.VERSION, ContentConstants.SCHEMA_VERSION) req.put(ContentConstants.ROOT_ID, objectId) + TelemetryManager.info("DIALManager::linkCollection:: updated req: " + req) HierarchyManager.getHierarchy(req).flatMap(getHierarchyResponse => { val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]] val updatedChildrenHierarchy = updateChildrenHierarchy(childrenHierarchy, requestMap) val childrenDIALMap = getChildrenDIALMap(updatedChildrenHierarchy, requestMap) val consolidatedUnitDIALMap = if (!requestMap.contains(objectId)) childrenDIALMap else childrenDIALMap ++ Map(objectId -> requestMap(objectId)) - + TelemetryManager.info("DIALManager::linkCollection:: consolidatedUnitDIALMap: " + consolidatedUnitDIALMap) validateDuplicateDIALCodes(consolidatedUnitDIALMap.filter(rec => rec._2.asInstanceOf[List[String]].nonEmpty)) val updatedHierarchy = new java.util.HashMap[String, AnyRef]() @@ -146,6 +152,7 @@ object DIALManager { val hierarchyReq = new Request(req) hierarchyReq.put(ContentConstants.HIERARCHY, ScalaJsonUtils.serialize(updatedHierarchy)) hierarchyReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) + TelemetryManager.info("DIALManager::linkCollection:: hierarchyReq: " + hierarchyReq) oec.graphService.saveExternalProps(hierarchyReq).flatMap(rec => if(requestMap.contains(objectId)) { val updateReq = new Request(req) updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) From 5891ebf706504c0e571f84b15c0ce9538020f904 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 30 Jun 2022 16:07:10 +0530 Subject: [PATCH 034/105] Issue #SB-30154 feat: DIAL Link API refactoring debug. --- .../main/scala/org/sunbird/content/dial/DIALManager.scala | 6 +++++- .../content-actors/src/test/resources/application.conf | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 6bd706632..bf2b734f2 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -65,8 +65,10 @@ object DIALManager { validateReqStructure(dialcodes, contents) contents.foreach(id => reqMap += (id -> dialcodes)) }) + TelemetryManager.info("DIALManager::validateAndGetRequestMap:: requestList: " + requestList) if (Platform.getBoolean("content.link_dialcode.validation", true)) { val dials = requestList.collect { case m if m.contains(DIALConstants.DIALCODE) => m(DIALConstants.DIALCODE) }.flatten + TelemetryManager.info("DIALManager::validateAndGetRequestMap:: dials: " + dials) validateDialCodes(channelId, dials) } reqMap @@ -90,8 +92,10 @@ object DIALManager { }}) }} val headerParam = new util.HashMap[String, String]{put(DIALConstants.X_CHANNEL_ID, channelId); put(DIALConstants.AUTHORIZATION, DIAL_API_AUTH_KEY);} - + TelemetryManager.info("DIALManager::validateAndGetRequestMap:: DIAL_SEARCH_API_URL: " + DIAL_SEARCH_API_URL) + TelemetryManager.info("DIALManager::validateAndGetRequestMap:: reqMap: " + reqMap) val searchResponse = oec.httpUtil.post(DIAL_SEARCH_API_URL, reqMap, headerParam) + TelemetryManager.info("DIALManager::validateAndGetRequestMap:: searchResponse.getResponseCode: " + searchResponse.getResponseCode) if (searchResponse.getResponseCode.toString == "OK") { val result = searchResponse.getResult if (dialcodes.distinct.size == result.get(DIALConstants.COUNT).asInstanceOf[Integer]) { diff --git a/content-api/content-actors/src/test/resources/application.conf b/content-api/content-actors/src/test/resources/application.conf index aa9400e59..0428b1e0e 100644 --- a/content-api/content-actors/src/test/resources/application.conf +++ b/content-api/content-actors/src/test/resources/application.conf @@ -495,7 +495,7 @@ dial_service { api { base_url = "https://qa.ekstep.in/api" auth_key = "auth_key" - search = "/dialcode/v1/search" + search = "/dialcode/v3/search" } } content.link_dialcode.validation=true From 4f5a0e552e13519d67d808f9d672c98b491fba79 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 30 Jun 2022 17:19:20 +0530 Subject: [PATCH 035/105] Issue #SB-30154 feat: DIAL Link API refactoring. --- .../org/sunbird/content/dial/DIALErrors.scala | 2 ++ .../org/sunbird/content/dial/DIALManager.scala | 18 +++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala index 53fa49388..3d528dde4 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala @@ -6,6 +6,7 @@ object DIALErrors { val ERR_DIALCODE_LINK_REQUEST: String = "ERR_DIALCODE_LINK_REQUEST" val ERR_DIALCODE_LINK: String = "ERR_DIALCODE_LINK" val ERR_DUPLICATE_DIAL_CODES: String = "ERR_DUPLICATE_DIAL_CODES" + val ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING: String = "ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING" //Error Messages val ERR_INVALID_REQ_MSG: String = "Invalid Request! Please Provide Valid Request." @@ -15,4 +16,5 @@ object DIALErrors { val ERR_CONTENT_NOT_FOUND_MSG: String = "Content Not Found With Id(s): " val ERR_SERVER_ERROR_MSG: String = "Something Went Wrong While Processing Your Request. Please Try Again After Sometime!" val ERR_DUPLICATE_DIAL_CODES_MSG: String = "QR Code should not be linked to multiple contents. Please validate: " + val ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING_MSG: String = "Required fields for content link dialcode are missing." } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index bf2b734f2..8fecd0c05 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -59,12 +59,16 @@ object DIALManager { def validateAndGetRequestMap(channelId: String, requestList: List[Map[String, List[String]]])(implicit oec:OntologyEngineContext): Map[String, List[String]] = { var reqMap = HashMap[String, List[String]]() - requestList.foreach(req => { - val contents: List[String] = req(DIALConstants.IDENTIFIER) - val dialcodes: List[String] = req(DIALConstants.DIALCODE) - validateReqStructure(dialcodes, contents) - contents.foreach(id => reqMap += (id -> dialcodes)) - }) + try { + requestList.foreach(req => { + val contents: List[String] = req(DIALConstants.IDENTIFIER) + val dialcodes: List[String] = req(DIALConstants.DIALCODE) + validateReqStructure(dialcodes, contents) + contents.foreach(id => reqMap += (id -> dialcodes)) + }) + } catch { + case e: Exception => throw new ClientException(DIALErrors.ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING, DIALErrors.ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING_MSG) + } TelemetryManager.info("DIALManager::validateAndGetRequestMap:: requestList: " + requestList) if (Platform.getBoolean("content.link_dialcode.validation", true)) { val dials = requestList.collect { case m if m.contains(DIALConstants.DIALCODE) => m(DIALConstants.DIALCODE) }.flatten @@ -257,7 +261,7 @@ object DIALManager { val dupUnitsList: List[String] = unitDIALCodesMap.flatMap(loopMapRec => if(loopMapRec._1 != mapRec._1 && loopMapRec._2.asInstanceOf[List[String]].contains(listRec)) { List(loopMapRec._1, mapRec._1) } else List.empty[String]).filter(unitRec => unitRec.nonEmpty).toList - Map(listRec -> dupUnitsList) + Map(listRec -> dupUnitsList.toSet) })).filter(unitRec => unitRec._2.nonEmpty) if (duplicateDIALCodes.nonEmpty) From 53b6ee2b40ef392102b7967c0adeadfb4b3c2b8b Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 30 Jun 2022 17:40:06 +0530 Subject: [PATCH 036/105] Issue #SB-30154 feat: DIAL Link API refactoring. --- .../org/sunbird/content/dial/DIALErrors.scala | 2 +- .../org/sunbird/content/dial/DIALManager.scala | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala index 3d528dde4..0dbff9d6f 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala @@ -16,5 +16,5 @@ object DIALErrors { val ERR_CONTENT_NOT_FOUND_MSG: String = "Content Not Found With Id(s): " val ERR_SERVER_ERROR_MSG: String = "Something Went Wrong While Processing Your Request. Please Try Again After Sometime!" val ERR_DUPLICATE_DIAL_CODES_MSG: String = "QR Code should not be linked to multiple contents. Please validate: " - val ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING_MSG: String = "Required fields for content link dialcode are missing." + val ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING_MSG: String = "Required fields for content link dialcode are missing: " } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 8fecd0c05..a7c0b8c10 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -59,16 +59,12 @@ object DIALManager { def validateAndGetRequestMap(channelId: String, requestList: List[Map[String, List[String]]])(implicit oec:OntologyEngineContext): Map[String, List[String]] = { var reqMap = HashMap[String, List[String]]() - try { - requestList.foreach(req => { - val contents: List[String] = req(DIALConstants.IDENTIFIER) - val dialcodes: List[String] = req(DIALConstants.DIALCODE) - validateReqStructure(dialcodes, contents) - contents.foreach(id => reqMap += (id -> dialcodes)) - }) - } catch { - case e: Exception => throw new ClientException(DIALErrors.ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING, DIALErrors.ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING_MSG) - } + requestList.foreach(req => { + val contents: List[String] = if(req.contains(DIALConstants.IDENTIFIER)) req(DIALConstants.IDENTIFIER) else throw new ClientException(DIALErrors.ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING, DIALErrors.ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING_MSG + DIALConstants.IDENTIFIER) + val dialcodes: List[String] = if(req.contains(DIALConstants.DIALCODE)) req(DIALConstants.DIALCODE) else throw new ClientException(DIALErrors.ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING, DIALErrors.ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING_MSG + DIALConstants.DIALCODE) + validateReqStructure(dialcodes, contents) + contents.foreach(id => reqMap += (id -> dialcodes)) + }) TelemetryManager.info("DIALManager::validateAndGetRequestMap:: requestList: " + requestList) if (Platform.getBoolean("content.link_dialcode.validation", true)) { val dials = requestList.collect { case m if m.contains(DIALConstants.DIALCODE) => m(DIALConstants.DIALCODE) }.flatten From 8139d0d210d8b4af491336268cde0629532385b4 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 5 Jul 2022 12:50:47 +0530 Subject: [PATCH 037/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../sunbird/content/actors/ContentActor.scala | 3 + .../org/sunbird/content/dial/DIALErrors.scala | 15 +++ .../sunbird/content/dial/DIALManager.scala | 120 +++++++++++++++++- .../src/test/resources/application.conf | 1 + .../controllers/v3/ContentController.scala | 10 +- .../content-service/app/utils/ApiId.scala | 1 + .../content-service/conf/application.conf | 1 + 7 files changed, 141 insertions(+), 10 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala index fabc95d43..e3925113f 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala @@ -49,6 +49,7 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe case "flagContent" => flag(request) case "acceptFlag" => acceptFlag(request) case "linkDIALCode" => linkDIALCode(request) + case "reserveDialCode" => reserveDialCode(request) case "importContent" => importContent(request) case "systemUpdate" => systemUpdate(request) case "reviewContent" => reviewContent(request) @@ -176,6 +177,8 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe def linkDIALCode(request: Request): Future[Response] = DIALManager.link(request) + def reserveDialCode(request: Request): Future[Response] = DIALManager.reserve(request) + def importContent(request: Request): Future[Response] = importMgr.importObject(request) def reviewContent(request: Request): Future[Response] = { diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala index 0dbff9d6f..743cbe86a 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala @@ -5,6 +5,12 @@ object DIALErrors { //Error Codes val ERR_DIALCODE_LINK_REQUEST: String = "ERR_DIALCODE_LINK_REQUEST" val ERR_DIALCODE_LINK: String = "ERR_DIALCODE_LINK" + val ERR_INVALID_CHANNEL: String = "ERR_INVALID_CHANNEL" + val ERR_CONTENT_BLANK_OBJECT_ID: String = "ERR_CONTENT_BLANK_OBJECT_ID" + val ERR_CONTENT_MIMETYPE: String = "ERR_CONTENT_MIMETYPE" + val ERR_INVALID_COUNT: String = "ERR_INVALID_COUNT" + val ERR_INVALID_COUNT_RANGE: String = "ERR_INVALID_COUNT_RANGE" + val ERR_CONTENT_INVALID_OBJECT: String = "ERR_CONTENT_INVALID_OBJECT" val ERR_DUPLICATE_DIAL_CODES: String = "ERR_DUPLICATE_DIAL_CODES" val ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING: String = "ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING" @@ -15,6 +21,15 @@ object DIALErrors { val ERR_DIAL_NOT_FOUND_MSG: String = "DIAL Code Not Found With Id(s): " val ERR_CONTENT_NOT_FOUND_MSG: String = "Content Not Found With Id(s): " val ERR_SERVER_ERROR_MSG: String = "Something Went Wrong While Processing Your Request. Please Try Again After Sometime!" + val ERR_INVALID_CHANNEL_MSG: String = "Invalid Channel Id." + val ERR_CONTENT_BLANK_OBJECT_ID_MSG: String = "Content Id cannot be Blank." + val ERR_CONTENT_MIMETYPE_MSG: String = "Invalid mimeType." + val ERR_INVALID_COUNT_MSG: String = "Invalid dialcode count." + val ERR_INVALID_COUNT_RANGE_MSG: String = "Invalid dialcode count range. It should be between 1 to " + val ERR_DIAL_GEN_LIST_EMPTY_MSG: String = "Dialcode generated list is empty. Please Try Again After Sometime!" + val ERR_DIAL_GENERATION_MSG: String = "Error During generate Dialcode. Please Try Again After Sometime!" + val ERR_DIAL_INVALID_COUNT_RESPONSE = "No new DIAL Codes have been generated, as requested count is less or equal to existing reserved dialcode count." + val ERR_CONTENT_INVALID_OBJECT_MSG = "Invalid Request. Cannot update status of Live Node." val ERR_DUPLICATE_DIAL_CODES_MSG: String = "QR Code should not be linked to multiple contents. Please validate: " val ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING_MSG: String = "Required fields for content link dialcode are missing: " } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index a7c0b8c10..1d65ed1be 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -21,6 +21,7 @@ import scala.concurrent.{ExecutionContext, Future} object DIALManager { val DIAL_SEARCH_API_URL: String = Platform.config.getString("dial_service.api.base_url") + Platform.config.getString("dial_service.api.search") + val DIALCODE_GENERATE_URI: String = Platform.config.getString("dial_service.api.base_url") + Platform.config.getString("dial_service.api.generate_url") val DIAL_API_AUTH_KEY: String = "Bearer " + Platform.config.getString("dial_service.api.auth_key") val PASSPORT_KEY: String = Platform.config.getString("graph.passport.key.base") @@ -28,11 +29,8 @@ object DIALManager { val linkType: String = request.getContext.getOrDefault(DIALConstants.LINK_TYPE, DIALConstants.CONTENT).asInstanceOf[String] val channelId: String = request.getContext.getOrDefault(DIALConstants.CHANNEL, "").asInstanceOf[String] val objectId: String = request.getContext.getOrDefault(DIALConstants.IDENTIFIER, "").asInstanceOf[String] - TelemetryManager.info("DIALManager::link:: linkType: " + linkType + " || channelId: " + channelId + " || objectId: " + objectId) val reqList: List[Map[String, List[String]]] = getRequestData(request) - TelemetryManager.info("DIALManager::link:: reqList: " + reqList) val requestMap: Map[String, List[String]] = validateAndGetRequestMap(channelId, reqList) - TelemetryManager.info("DIALManager::link:: requestMap: " + requestMap) linkType match { case DIALConstants.CONTENT => linkContent(requestMap, request.getContext) case DIALConstants.COLLECTION => linkCollection(objectId, requestMap, request.getContext) @@ -65,10 +63,8 @@ object DIALManager { validateReqStructure(dialcodes, contents) contents.foreach(id => reqMap += (id -> dialcodes)) }) - TelemetryManager.info("DIALManager::validateAndGetRequestMap:: requestList: " + requestList) if (Platform.getBoolean("content.link_dialcode.validation", true)) { - val dials = requestList.collect { case m if m.contains(DIALConstants.DIALCODE) => m(DIALConstants.DIALCODE) }.flatten - TelemetryManager.info("DIALManager::validateAndGetRequestMap:: dials: " + dials) + val dials = requestList.collect { case m if m.get(DIALConstants.DIALCODE).nonEmpty => m.get(DIALConstants.DIALCODE).get }.flatten validateDialCodes(channelId, dials) } reqMap @@ -95,7 +91,6 @@ object DIALManager { TelemetryManager.info("DIALManager::validateAndGetRequestMap:: DIAL_SEARCH_API_URL: " + DIAL_SEARCH_API_URL) TelemetryManager.info("DIALManager::validateAndGetRequestMap:: reqMap: " + reqMap) val searchResponse = oec.httpUtil.post(DIAL_SEARCH_API_URL, reqMap, headerParam) - TelemetryManager.info("DIALManager::validateAndGetRequestMap:: searchResponse.getResponseCode: " + searchResponse.getResponseCode) if (searchResponse.getResponseCode.toString == "OK") { val result = searchResponse.getResult if (dialcodes.distinct.size == result.get(DIALConstants.COUNT).asInstanceOf[Integer]) { @@ -263,4 +258,115 @@ object DIALManager { if (duplicateDIALCodes.nonEmpty) throw new ClientException(DIALErrors.ERR_DUPLICATE_DIAL_CODES, DIALErrors.ERR_DUPLICATE_DIAL_CODES_MSG + duplicateDIALCodes) } + + def reserve(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { + val channelId: String = request.getContext.getOrDefault(DIALConstants.CHANNEL, "").asInstanceOf[String] + val contentId: String = request.get(ContentConstants.IDENTIFIER).asInstanceOf[String] + + if (contentId == null || contentId.isEmpty) throw new ClientException(DIALErrors.ERR_CONTENT_BLANK_OBJECT_ID, DIALErrors.ERR_CONTENT_BLANK_OBJECT_ID_MSG) + + val req = new Request() + req.setContext(request.getContext) + req.put(DIALConstants.IDENTIFIER, contentId) + req.put(ContentConstants.ROOT_ID, contentId) + req.put(ContentConstants.MODE, "edit") + DataNode.read(req).flatMap(rootNode => { + val contentMetadata = rootNode.getMetadata + TelemetryManager.info("DialManager:: reserve:: contentMetadata: " + contentMetadata) + val contentChannel = contentMetadata.get("channel").asInstanceOf[String] + validateChannel(contentChannel, channelId) + validateContentForReservedDialcodes(contentMetadata) + validateCountForReservingDialCode(request.getRequest.get("dialcodes").asInstanceOf[util.Map[String, AnyRef]]) + + if (contentMetadata.get("status").asInstanceOf[String].equalsIgnoreCase("Live") || contentMetadata.get("status").asInstanceOf[String].equalsIgnoreCase("Unlisted")) + throw new ClientException(DIALErrors.ERR_CONTENT_INVALID_OBJECT, DIALErrors.ERR_CONTENT_INVALID_OBJECT_MSG) + + val reservedDialCodes = contentMetadata.getOrDefault("dialcodes", Map.empty[String, Integer]).asInstanceOf[Map[String, Integer]] + TelemetryManager.info("DialManager:: reserve:: reservedDialCodes: " + reservedDialCodes) + val maxIndex: Integer = if (reservedDialCodes.nonEmpty) reservedDialCodes.max._2 else -1 + val dialCodes = reservedDialCodes.keySet + val reqDialcodesCount = request.getRequest.get("dialcodes").asInstanceOf[util.Map[String, AnyRef]].get("count").asInstanceOf[Integer] + TelemetryManager.info("DialManager:: reserve:: reqDialcodesCount: " + reqDialcodesCount) + val updateDialCodes = if (dialCodes.size < reqDialcodesCount) { + val newDialcodes = generateDialCodes(channelId, contentId, reqDialcodesCount - dialCodes.size, request.get("publisher").asInstanceOf[String]) + val newDialCodesMap: Map[String, Integer] = newDialcodes.zipWithIndex.map { case (newDialCode, idx) => + (newDialCode -> (maxIndex + idx + 1).asInstanceOf[Integer]) + }.toMap + reservedDialCodes ++ newDialCodesMap + } else reservedDialCodes + TelemetryManager.info("DialManager:: reserve:: updateDialCodes: " + updateDialCodes) + if(updateDialCodes.size > reservedDialCodes.size) { + val updateReq = new Request(request) + updateReq.put("identifier", rootNode.getIdentifier) + val rootNodeMetadata = rootNode.getMetadata + rootNodeMetadata.remove("discussionForum") + rootNodeMetadata.remove("credentials") + rootNodeMetadata.remove("trackable") + + updateReq.put(DIALConstants.RESERVED_DIALCODES, updateDialCodes) + updateReq.getRequest.putAll(rootNodeMetadata) + DataNode.update(updateReq).map(updatedNode => { + val response = ResponseHandler.OK() + response.getResult.put("count", updateDialCodes.size.asInstanceOf[Integer]) + response.getResult.put("node_id", contentId) + response.getResult.put("processId", updatedNode.getMetadata.get("processId")) + response.getResult.put("reservedDialcodes", updatedNode.getMetadata.get("reservedDialcodes")) + response.getResult.put("versionKey", updatedNode.getMetadata.get("versionKey")) + TelemetryManager.info("DialManager:: reserve:: response: " + response) + response + }) + } else { + val errorResponse = ResponseHandler.ERROR(ResponseCode.CLIENT_ERROR, DIALErrors.ERR_INVALID_COUNT, DIALErrors.ERR_DIAL_INVALID_COUNT_RESPONSE) + errorResponse.getResult.put("count", reservedDialCodes.size.asInstanceOf[Integer]) + errorResponse.getResult.put("node_id", contentId) + errorResponse.getResult.put("processId", rootNode.getMetadata.get("processId")) + errorResponse.getResult.put("reservedDialcodes", rootNode.getMetadata.get("reservedDialcodes")) + TelemetryManager.info("DialManager:: reserve:: errorResponse: " + errorResponse) + Future(errorResponse) + } + }) + } + + def validateChannel(contentChannel: String, channelId: String): Unit = { + if(contentChannel == null || channelId == null || !contentChannel.equalsIgnoreCase(channelId)) + throw new ClientException(DIALErrors.ERR_INVALID_CHANNEL, DIALErrors.ERR_INVALID_CHANNEL_MSG) + } + + def validateContentForReservedDialcodes(metaData: util.Map[String, AnyRef]): Unit = { + val validMimeType = if (Platform.config.hasPath("reserve_dialcode.mimeType")) Platform.config.getStringList("reserve_dialcode.mimeType") else util.Arrays.asList("application/vnd.ekstep.content-collection") + if (!validMimeType.contains(metaData.get("mimeType"))) throw new ClientException(DIALErrors.ERR_CONTENT_MIMETYPE, DIALErrors.ERR_CONTENT_MIMETYPE_MSG) + } + + def validateCountForReservingDialCode(request: util.Map[String, AnyRef]): Unit = { + if (null == request.get("count") || !request.get("count").isInstanceOf[Integer]) throw new ClientException(DIALErrors.ERR_INVALID_COUNT, DIALErrors.ERR_INVALID_COUNT_MSG) + val count = request.get("count").asInstanceOf[Integer] + val maxCount = if (Platform.config.hasPath("reserve_dialcode.max_count")) Platform.config.getInt("reserve_dialcode.max_count") else 250 + if (count < 1 || count > maxCount) throw new ClientException(DIALErrors.ERR_INVALID_COUNT_RANGE, DIALErrors.ERR_INVALID_COUNT_RANGE_MSG + maxCount + ".") + } + + @throws[Exception] + private def generateDialCodes(channelId: String, contentId: String, dialcodeCount: Integer, publisher: String)(implicit oec: OntologyEngineContext): List[String] = { + val dialcodeMap = new util.HashMap[String, AnyRef] + dialcodeMap.put("count", dialcodeCount) + dialcodeMap.put("publisher", publisher) + dialcodeMap.put("batchCode", contentId) + val request = new util.HashMap[String, AnyRef] + request.put("dialcodes", dialcodeMap) + val requestMap = new util.HashMap[String, AnyRef] + requestMap.put("request", request) + val headerParam = new util.HashMap[String, String]{put(DIALConstants.X_CHANNEL_ID, channelId); put(DIALConstants.AUTHORIZATION, DIAL_API_AUTH_KEY);} + + val generateResponse = oec.httpUtil.post(DIALCODE_GENERATE_URI, requestMap, headerParam) + if ((generateResponse.getResponseCode == ResponseCode.OK) || (generateResponse.getResponseCode == ResponseCode.PARTIAL_SUCCESS)) { + val generatedDialCodes = generateResponse.getResult.get("dialcodes").asInstanceOf[util.ArrayList[String]].asScala.toList + if (generatedDialCodes.nonEmpty) generatedDialCodes + else throw new ServerException(ErrorCodes.ERR_SYSTEM_EXCEPTION.name, DIALErrors.ERR_DIAL_GEN_LIST_EMPTY_MSG) + } + else if (generateResponse.getResponseCode eq ResponseCode.CLIENT_ERROR) { + throw new ClientException(generateResponse.getParams.getErr, generateResponse.getParams.getErrmsg) + } + else { + throw new ServerException(ErrorCodes.ERR_SYSTEM_EXCEPTION.name, DIALErrors.ERR_DIAL_GENERATION_MSG) + } + } } diff --git a/content-api/content-actors/src/test/resources/application.conf b/content-api/content-actors/src/test/resources/application.conf index 0428b1e0e..45c1b629f 100644 --- a/content-api/content-actors/src/test/resources/application.conf +++ b/content-api/content-actors/src/test/resources/application.conf @@ -496,6 +496,7 @@ dial_service { base_url = "https://qa.ekstep.in/api" auth_key = "auth_key" search = "/dialcode/v3/search" + generate_url = "/dialcode/v1/generate" } } content.link_dialcode.validation=true diff --git a/content-api/content-service/app/controllers/v3/ContentController.scala b/content-api/content-service/app/controllers/v3/ContentController.scala index 05c5b2470..ab3538098 100644 --- a/content-api/content-service/app/controllers/v3/ContentController.scala +++ b/content-api/content-service/app/controllers/v3/ContentController.scala @@ -206,9 +206,13 @@ class ContentController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentActor: } def reserveDialCode(identifier: String) = Action.async { implicit request => - val result = ResponseHandler.OK() - val response = JavaJsonUtils.serialize(result) - Future(Ok(response).as("application/json")) + val headers = commonHeaders() + val body = requestBody() + body.putAll(headers) + body.putAll(Map("identifier" -> identifier).asJava) + val reserveDialCode = getRequest(body, headers, "reserveDialCode") + setRequestContext(reserveDialCode, version, objectType, schemaName) + getResult(ApiId.RESERVE_DIAL_CONTENT, contentActor, reserveDialCode) } def releaseDialcodes(identifier: String) = Action.async { implicit request => diff --git a/content-api/content-service/app/utils/ApiId.scala b/content-api/content-service/app/utils/ApiId.scala index 7aa95ac57..6bad01791 100644 --- a/content-api/content-service/app/utils/ApiId.scala +++ b/content-api/content-service/app/utils/ApiId.scala @@ -29,6 +29,7 @@ object ApiId { val UPDATE_HIERARCHY = "api.content.hierarchy.update" val GET_HIERARCHY = "api.content.hierarchy.get" val LINK_DIAL_COLLECTION = "api.collection.dialcode.link" + val RESERVE_DIAL_CONTENT = "api.content.dialcode.reserve" //License APIs val CREATE_LICENSE = "api.license.create" diff --git a/content-api/content-service/conf/application.conf b/content-api/content-service/conf/application.conf index f1e9714db..a4a6147e2 100644 --- a/content-api/content-service/conf/application.conf +++ b/content-api/content-service/conf/application.conf @@ -604,6 +604,7 @@ dial_service { base_url = "https://qa.ekstep.in/api" auth_key = "auth_key" search = "/dialcode/v1/search" + generate_url = "/dialcode/v1/generate" } } content.link_dialcode.validation=true From c7aee00e4c394454acea974c01eafde53e102a2b Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 5 Jul 2022 12:50:52 +0530 Subject: [PATCH 038/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../src/main/scala/org/sunbird/content/dial/DIALConstants.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALConstants.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALConstants.scala index 70d8f74da..4891f30e1 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALConstants.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALConstants.scala @@ -16,6 +16,7 @@ object DIALConstants { val AUTHORIZATION: String = "Authorization" val X_CHANNEL_ID: String = "X-Channel-Id" val VERSION_KEY: String = "versionKey" + val RESERVED_DIALCODES: String = "reservedDialcodes" val DISCUSSION_FORUM: String = "discussionForum" val CREDENTIALS: String = "credentials" val TRACKABLE: String = "trackable" From 7b9b5f3b242c0cb106ffad5f1d6d7faa1dfd5c2d Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 5 Jul 2022 12:52:55 +0530 Subject: [PATCH 039/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- content-api/content-actors/src/test/resources/application.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content-api/content-actors/src/test/resources/application.conf b/content-api/content-actors/src/test/resources/application.conf index 45c1b629f..39a6cadb9 100644 --- a/content-api/content-actors/src/test/resources/application.conf +++ b/content-api/content-actors/src/test/resources/application.conf @@ -495,7 +495,7 @@ dial_service { api { base_url = "https://qa.ekstep.in/api" auth_key = "auth_key" - search = "/dialcode/v3/search" + search = "/dialcode/v1/search" generate_url = "/dialcode/v1/generate" } } From e1b02c92bc17994bf8927717e127576df0ee2087 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 6 Jul 2022 16:32:19 +0530 Subject: [PATCH 040/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../sunbird/content/dial/DIALManager.scala | 15 ++-- .../src/test/resources/application.conf | 4 + .../content/dial/DIALManagerTest.scala | 85 +++++++++++++++++++ 3 files changed, 97 insertions(+), 7 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 1d65ed1be..9f4ca3b2a 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -296,12 +296,14 @@ object DIALManager { } else reservedDialCodes TelemetryManager.info("DialManager:: reserve:: updateDialCodes: " + updateDialCodes) if(updateDialCodes.size > reservedDialCodes.size) { - val updateReq = new Request(request) - updateReq.put("identifier", rootNode.getIdentifier) + val updateReq = new Request(req) + updateReq.setContext(request.getContext) + updateReq.getContext.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) + updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) val rootNodeMetadata = rootNode.getMetadata - rootNodeMetadata.remove("discussionForum") - rootNodeMetadata.remove("credentials") - rootNodeMetadata.remove("trackable") + rootNodeMetadata.remove(DIALConstants.DISCUSSION_FORUM) + rootNodeMetadata.remove(DIALConstants.CREDENTIALS) + rootNodeMetadata.remove(DIALConstants.TRACKABLE) updateReq.put(DIALConstants.RESERVED_DIALCODES, updateDialCodes) updateReq.getRequest.putAll(rootNodeMetadata) @@ -355,9 +357,8 @@ object DIALManager { val requestMap = new util.HashMap[String, AnyRef] requestMap.put("request", request) val headerParam = new util.HashMap[String, String]{put(DIALConstants.X_CHANNEL_ID, channelId); put(DIALConstants.AUTHORIZATION, DIAL_API_AUTH_KEY);} - val generateResponse = oec.httpUtil.post(DIALCODE_GENERATE_URI, requestMap, headerParam) - if ((generateResponse.getResponseCode == ResponseCode.OK) || (generateResponse.getResponseCode == ResponseCode.PARTIAL_SUCCESS)) { + if (generateResponse.getResponseCode == ResponseCode.OK || generateResponse.getResponseCode == ResponseCode.PARTIAL_SUCCESS) { val generatedDialCodes = generateResponse.getResult.get("dialcodes").asInstanceOf[util.ArrayList[String]].asScala.toList if (generatedDialCodes.nonEmpty) generatedDialCodes else throw new ServerException(ErrorCodes.ERR_SYSTEM_EXCEPTION.name, DIALErrors.ERR_DIAL_GEN_LIST_EMPTY_MSG) diff --git a/content-api/content-actors/src/test/resources/application.conf b/content-api/content-actors/src/test/resources/application.conf index 39a6cadb9..54ea3dcf7 100644 --- a/content-api/content-actors/src/test/resources/application.conf +++ b/content-api/content-actors/src/test/resources/application.conf @@ -501,6 +501,10 @@ dial_service { } content.link_dialcode.validation=true content.link_dialcode.max_limit=10 + + +reserve_dialcode.mimeType = ["application/vnd.ekstep.content-collection", "application/pdf"] + # This is added to handle large artifacts sizes differently content.artifact.size.for_online=209715200 diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index eac0e8686..a2d0d8ec7 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -7,9 +7,11 @@ import org.sunbird.common.dto.{Property, Request, Response} import org.sunbird.common.exception.{ClientException, ResourceNotFoundException, ResponseCode, ServerException} import org.sunbird.common.{HttpUtil, JsonUtils} import org.sunbird.graph.dac.model.{Node, SearchCriteria} +import org.sunbird.graph.utils.ScalaJsonUtils import org.sunbird.graph.{GraphService, OntologyEngineContext} import java.util +import scala.collection.JavaConversions.mapAsJavaMap import scala.concurrent.Future class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory { @@ -260,11 +262,51 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory }) } + "reserve DIAL" should "update content with reservedDialcodes" in { + (oec.httpUtil _).expects().returns(httpUtil) + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getGenerateDIALResponse) + + val nodes: util.List[Node] = getCategoryNode() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())) + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, "do_1111.img", *, *).returns(Future(getNode("do_1111"))).anyNumberOfTimes() + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, "do_1111", *, *).returns(Future(getNode("do_1111"))).anyNumberOfTimes() + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getDefinitionNode())).anyNumberOfTimes() + (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) + (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())) + + val request = getReserveDIALRequest() + + val response = DIALManager.reserve(request) + response.map(result => { + assert(result.getResponseCode.toString=="OK") + }) + + } + + def getDefinitionNode(): Node = { + val node = new Node() + node.setIdentifier("obj-cat:learning-resource_content_in.ekstep") + node.setNodeType("DATA_NODE") + node.setObjectType("Content") + node.setGraphId("domain") + node.setMetadata(mapAsJavaMap( + ScalaJsonUtils.deserialize[Map[String,AnyRef]]("{\n \"objectCategoryDefinition\": {\n \"name\": \"Learning Resource\",\n \"description\": \"Content Playlist\",\n \"categoryId\": \"obj-cat:learning-resource\",\n \"targetObjectType\": \"Content\",\n \"objectMetadata\": {\n \"config\": {},\n \"schema\": {\n \"required\": [\n \"author\",\n \"copyright\",\n \"license\",\n \"audience\"\n ],\n \"properties\": {\n \"audience\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"Student\",\n \"Teacher\"\n ]\n },\n \"default\": [\n \"Student\"\n ]\n },\n \"mimeType\": {\n \"type\": \"string\",\n \"enum\": [\n \"application/pdf\"\n ]\n }\n }\n }\n }\n }\n }"))) + node + } + def getDIALSearchResponse:Response = { val resString = "{\n \"id\": \"sunbird.dialcode.search\",\n \"ver\": \"3.0\",\n \"ts\": \"2020-04-21T19:39:14ZZ\",\n \"params\": {\n \"resmsgid\": \"1dfcc25b-6c37-49f8-a6c3-7185063e8752\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"dialcodes\": [\n {\n \"dialcode_index\": 7609876,\n \"identifier\": \"N4Z7D5\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.603+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610113,\n \"identifier\": \"E8B7Z6\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.635+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610117,\n \"identifier\": \"R4X2P2\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.637+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610961,\n \"identifier\": \"L4A6W8\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.734+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7611164,\n \"identifier\": \"D2E1J9\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.759+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n }\n ],\n \"count\": 5\n }\n}"; JsonUtils.deserialize(resString, classOf[Response]) } + def getGenerateDIALResponse:Response = { + val resString = "{\"id\": \"api.dialcode.generate\",\"ver\": \"1.0\",\"ts\": \"2022-07-05T09:47:26.000Z\",\"params\": {\"resmsgid\": \"79eb8b00-fc47-11ec-af25-0f53946b16ec\",\"msgid\": \"79be1260-fc47-11ec-8c03-63ca5ce41074\",\"status\": \"successful\",\"err\": null,\"errmsg\": null},\"responseCode\": \"OK\",\"result\": {\"dialcodes\": [\"K2C3R6\",\"H2E8F9\"],\"count\": 2,\"batchcode\": \"do_11357423520695910411\",\"publisher\": null}}" + JsonUtils.deserialize(resString, classOf[Response]) + } + def getRequestData(): List[Map[String, List[String]]] = { val reqMap : java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ put("content", new util.ArrayList[util.Map[String, AnyRef]](){{ @@ -332,6 +374,28 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory request } + def getReserveDIALRequest(): Request = { + val request = new Request() + request.setObjectType("Content") + request.setContext(getContext()) + request.getContext.put("identifier","do_1111") + request.put("identifier","do_1111") + request.putAll(getReserveRequest()) + request + } + + def getReserveRequest():util.Map[String, AnyRef] = { + val reqMap : java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){ + put("dialcodes", new util.HashMap[String, AnyRef](){ + put("count", 2.asInstanceOf[Integer]) + put("qrCodeSpec", new util.HashMap[String, AnyRef](){ + put("errorCorrectionLevel", "H") + }) + }) + } + reqMap + } + def getContext():util.Map[String, AnyRef] = { val contextMap: java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ put("graph_id", "domain") @@ -393,6 +457,27 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory put("channel", "test") put("versionKey", "1234") put("primaryCategory", "Learning Resource") + put("framework", "NCF") + put("board", "CBSE") + put("medium", new java.util.ArrayList[String](){ + add("English"); + }) + put("gradeLevel", new java.util.ArrayList[String](){ + add("Class 1"); + }) + put("subject", new java.util.ArrayList[String](){ + add("English"); + }) + put("se_boards", "CBSE") + put("se_mediums", new java.util.ArrayList[String](){ + add("English"); + }) + put("se_gradeLevels", new java.util.ArrayList[String](){ + add("Class 1"); + }) + put("se_subjects", new java.util.ArrayList[String](){ + add("English"); + }) } }) node From a45ecae788a7c43afc0e7f780cd36c7cef5ba3ff Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 7 Jul 2022 11:19:31 +0530 Subject: [PATCH 041/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../content/dial/DIALManagerTest.scala | 107 ++++++------------ 1 file changed, 36 insertions(+), 71 deletions(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index a2d0d8ec7..0b21bbb44 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -7,11 +7,9 @@ import org.sunbird.common.dto.{Property, Request, Response} import org.sunbird.common.exception.{ClientException, ResourceNotFoundException, ResponseCode, ServerException} import org.sunbird.common.{HttpUtil, JsonUtils} import org.sunbird.graph.dac.model.{Node, SearchCriteria} -import org.sunbird.graph.utils.ScalaJsonUtils import org.sunbird.graph.{GraphService, OntologyEngineContext} import java.util -import scala.collection.JavaConversions.mapAsJavaMap import scala.concurrent.Future class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory { @@ -19,7 +17,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] val graphDB: GraphService = mock[GraphService] val httpUtil: HttpUtil = mock[HttpUtil] - + "getRequestData with list input" should "return request data as list with scala types" in { val reqMap : java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ put("content", new util.ArrayList[util.Map[String, AnyRef]](){{ @@ -204,7 +202,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())) (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) - + val request = getCollectionDIALRequest() val response = DIALManager.link(request) @@ -267,17 +265,17 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getGenerateDIALResponse) + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(getNodes())).noMoreThanOnce() val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).noMoreThanOnce() + val contentId: String = "do_123456" (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, "do_1111.img", *, *).returns(Future(getNode("do_1111"))).anyNumberOfTimes() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, "do_1111", *, *).returns(Future(getNode("do_1111"))).anyNumberOfTimes() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getDefinitionNode())).anyNumberOfTimes() - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) - (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())) + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode(contentId))) + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode(contentId+".img"))) + (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) + (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode(contentId))) - val request = getReserveDIALRequest() + val request = getReserveDIALRequest(contentId) val response = DIALManager.reserve(request) response.map(result => { @@ -286,27 +284,11 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory } - def getDefinitionNode(): Node = { - val node = new Node() - node.setIdentifier("obj-cat:learning-resource_content_in.ekstep") - node.setNodeType("DATA_NODE") - node.setObjectType("Content") - node.setGraphId("domain") - node.setMetadata(mapAsJavaMap( - ScalaJsonUtils.deserialize[Map[String,AnyRef]]("{\n \"objectCategoryDefinition\": {\n \"name\": \"Learning Resource\",\n \"description\": \"Content Playlist\",\n \"categoryId\": \"obj-cat:learning-resource\",\n \"targetObjectType\": \"Content\",\n \"objectMetadata\": {\n \"config\": {},\n \"schema\": {\n \"required\": [\n \"author\",\n \"copyright\",\n \"license\",\n \"audience\"\n ],\n \"properties\": {\n \"audience\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\",\n \"enum\": [\n \"Student\",\n \"Teacher\"\n ]\n },\n \"default\": [\n \"Student\"\n ]\n },\n \"mimeType\": {\n \"type\": \"string\",\n \"enum\": [\n \"application/pdf\"\n ]\n }\n }\n }\n }\n }\n }"))) - node - } - def getDIALSearchResponse:Response = { val resString = "{\n \"id\": \"sunbird.dialcode.search\",\n \"ver\": \"3.0\",\n \"ts\": \"2020-04-21T19:39:14ZZ\",\n \"params\": {\n \"resmsgid\": \"1dfcc25b-6c37-49f8-a6c3-7185063e8752\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"dialcodes\": [\n {\n \"dialcode_index\": 7609876,\n \"identifier\": \"N4Z7D5\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.603+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610113,\n \"identifier\": \"E8B7Z6\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.635+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610117,\n \"identifier\": \"R4X2P2\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.637+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610961,\n \"identifier\": \"L4A6W8\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.734+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7611164,\n \"identifier\": \"D2E1J9\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.759+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n }\n ],\n \"count\": 5\n }\n}"; JsonUtils.deserialize(resString, classOf[Response]) } - def getGenerateDIALResponse:Response = { - val resString = "{\"id\": \"api.dialcode.generate\",\"ver\": \"1.0\",\"ts\": \"2022-07-05T09:47:26.000Z\",\"params\": {\"resmsgid\": \"79eb8b00-fc47-11ec-af25-0f53946b16ec\",\"msgid\": \"79be1260-fc47-11ec-8c03-63ca5ce41074\",\"status\": \"successful\",\"err\": null,\"errmsg\": null},\"responseCode\": \"OK\",\"result\": {\"dialcodes\": [\"K2C3R6\",\"H2E8F9\"],\"count\": 2,\"batchcode\": \"do_11357423520695910411\",\"publisher\": null}}" - JsonUtils.deserialize(resString, classOf[Response]) - } - def getRequestData(): List[Map[String, List[String]]] = { val reqMap : java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ put("content", new util.ArrayList[util.Map[String, AnyRef]](){{ @@ -374,28 +356,6 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory request } - def getReserveDIALRequest(): Request = { - val request = new Request() - request.setObjectType("Content") - request.setContext(getContext()) - request.getContext.put("identifier","do_1111") - request.put("identifier","do_1111") - request.putAll(getReserveRequest()) - request - } - - def getReserveRequest():util.Map[String, AnyRef] = { - val reqMap : java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){ - put("dialcodes", new util.HashMap[String, AnyRef](){ - put("count", 2.asInstanceOf[Integer]) - put("qrCodeSpec", new util.HashMap[String, AnyRef](){ - put("errorCorrectionLevel", "H") - }) - }) - } - reqMap - } - def getContext():util.Map[String, AnyRef] = { val contextMap: java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ put("graph_id", "domain") @@ -457,27 +417,6 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory put("channel", "test") put("versionKey", "1234") put("primaryCategory", "Learning Resource") - put("framework", "NCF") - put("board", "CBSE") - put("medium", new java.util.ArrayList[String](){ - add("English"); - }) - put("gradeLevel", new java.util.ArrayList[String](){ - add("Class 1"); - }) - put("subject", new java.util.ArrayList[String](){ - add("English"); - }) - put("se_boards", "CBSE") - put("se_mediums", new java.util.ArrayList[String](){ - add("English"); - }) - put("se_gradeLevels", new java.util.ArrayList[String](){ - add("Class 1"); - }) - put("se_subjects", new java.util.ArrayList[String](){ - add("English"); - }) } }) node @@ -608,4 +547,30 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory response.put("hierarchy", hierarchyString) } + def getReserveDIALRequest(identifier: String): Request = { + val request = new Request() + request.setObjectType("Content") + request.setContext(getContext()) + request.getContext.put("identifier",identifier) + request.put("identifier",identifier) + request.putAll(getReserveRequest()) + request + } + + def getReserveRequest():util.Map[String, AnyRef] = { + val reqMap : java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){ + put("dialcodes", new util.HashMap[String, AnyRef](){ + put("count", 2.asInstanceOf[Integer]) + put("qrCodeSpec", new util.HashMap[String, AnyRef](){ + put("errorCorrectionLevel", "H") + }) + }) + } + reqMap + } + + def getGenerateDIALResponse:Response = { + val resString = "{\"id\": \"api.dialcode.generate\",\"ver\": \"1.0\",\"ts\": \"2022-07-05T09:47:26.000Z\",\"params\": {\"resmsgid\": \"79eb8b00-fc47-11ec-af25-0f53946b16ec\",\"msgid\": \"79be1260-fc47-11ec-8c03-63ca5ce41074\",\"status\": \"successful\",\"err\": null,\"errmsg\": null},\"responseCode\": \"OK\",\"result\": {\"dialcodes\": [\"K2C3R6\",\"H2E8F9\"],\"count\": 2,\"batchcode\": \"do_11357423520695910411\",\"publisher\": null}}" + JsonUtils.deserialize(resString, classOf[Response]) + } } \ No newline at end of file From 544b567e0e9d3017a00b0f9bf8a5826973acb852 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 7 Jul 2022 12:19:43 +0530 Subject: [PATCH 042/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../org/sunbird/content/dial/DIALManagerTest.scala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index 0b21bbb44..fe532977d 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -265,13 +265,13 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() (httpUtil.post(_: String, _:java.util.Map[String, AnyRef], _:java.util.Map[String, String])).expects(*, *, *).returns(getGenerateDIALResponse) - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(getNodes())).noMoreThanOnce() val nodes: util.List[Node] = getCategoryNode() - (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).noMoreThanOnce() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + val contentId: String = "do_123456" - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode(contentId))) - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode(contentId+".img"))) +// (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode(contentId))).anyNumberOfTimes() +// (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode(contentId+".img"))).anyNumberOfTimes() (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode(contentId))) @@ -279,6 +279,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory val response = DIALManager.reserve(request) response.map(result => { + println("Result:: " + result.getResult) assert(result.getResponseCode.toString=="OK") }) @@ -397,6 +398,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory add(getNode("do_3333")) add(getNode("do_4444")) add(getNode("do_5555")) + add(getNode("do_123456")) }} result } From 3e0923810f604c829d55ad26aa3119389d8f9543 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 7 Jul 2022 14:57:36 +0530 Subject: [PATCH 043/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../content/dial/DIALManagerTest.scala | 25 +++++++++++++++++-- .../controllers/v4/CollectionController.scala | 10 ++++++++ .../controllers/v4/ContentController.scala | 10 ++++++++ content-api/content-service/conf/routes | 4 ++- 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index fe532977d..11e56e0ee 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -279,12 +279,11 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory val response = DIALManager.reserve(request) response.map(result => { - println("Result:: " + result.getResult) assert(result.getResponseCode.toString=="OK") }) - } + def getDIALSearchResponse:Response = { val resString = "{\n \"id\": \"sunbird.dialcode.search\",\n \"ver\": \"3.0\",\n \"ts\": \"2020-04-21T19:39:14ZZ\",\n \"params\": {\n \"resmsgid\": \"1dfcc25b-6c37-49f8-a6c3-7185063e8752\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"dialcodes\": [\n {\n \"dialcode_index\": 7609876,\n \"identifier\": \"N4Z7D5\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.603+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610113,\n \"identifier\": \"E8B7Z6\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.635+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610117,\n \"identifier\": \"R4X2P2\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.637+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610961,\n \"identifier\": \"L4A6W8\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.734+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7611164,\n \"identifier\": \"D2E1J9\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.759+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n }\n ],\n \"count\": 5\n }\n}"; JsonUtils.deserialize(resString, classOf[Response]) @@ -575,4 +574,26 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory val resString = "{\"id\": \"api.dialcode.generate\",\"ver\": \"1.0\",\"ts\": \"2022-07-05T09:47:26.000Z\",\"params\": {\"resmsgid\": \"79eb8b00-fc47-11ec-af25-0f53946b16ec\",\"msgid\": \"79be1260-fc47-11ec-8c03-63ca5ce41074\",\"status\": \"successful\",\"err\": null,\"errmsg\": null},\"responseCode\": \"OK\",\"result\": {\"dialcodes\": [\"K2C3R6\",\"H2E8F9\"],\"count\": 2,\"batchcode\": \"do_11357423520695910411\",\"publisher\": null}}" JsonUtils.deserialize(resString, classOf[Response]) } + + def getInvalidChannelReserveDIALRequest(identifier: String): Request = { + val request = new Request() + request.setObjectType("Content") + request.setContext(getInavlidChannelContext()) + request.getContext.put("identifier",identifier) + request.put("identifier",identifier) + request.putAll(getReserveRequest()) + request + } + + def getInavlidChannelContext():util.Map[String, AnyRef] = { + val contextMap: java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ + put("graph_id", "domain") + put("version" , "1.0") + put("objectType" , "Content") + put("schemaName", "content") + put("channel", "invalidChannel") + }} + contextMap + } + } \ No newline at end of file diff --git a/content-api/content-service/app/controllers/v4/CollectionController.scala b/content-api/content-service/app/controllers/v4/CollectionController.scala index 2c649a219..cd84c0579 100644 --- a/content-api/content-service/app/controllers/v4/CollectionController.scala +++ b/content-api/content-service/app/controllers/v4/CollectionController.scala @@ -186,6 +186,16 @@ class CollectionController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentAc getResult(ApiId.LINK_DIAL_COLLECTION, contentActor, contentRequest, version = apiVersion) } + def reserveDialCode(identifier: String) = Action.async { implicit request => + val headers = commonHeaders() + val body = requestBody() + body.putAll(headers) + body.putAll(Map("identifier" -> identifier).asJava) + val reserveDialCode = getRequest(body, headers, "reserveDialCode") + setRequestContext(reserveDialCode, version, objectType, schemaName) + getResult(ApiId.RESERVE_DIAL_CONTENT, contentActor, reserveDialCode) + } + def copy(identifier: String, mode: Option[String], copyType: String) = Action.async { implicit request => val headers = commonHeaders() val body = requestBody() diff --git a/content-api/content-service/app/controllers/v4/ContentController.scala b/content-api/content-service/app/controllers/v4/ContentController.scala index ddf2dc45c..f5a25d0fe 100644 --- a/content-api/content-service/app/controllers/v4/ContentController.scala +++ b/content-api/content-service/app/controllers/v4/ContentController.scala @@ -131,6 +131,16 @@ class ContentController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentActor: getResult(ApiId.LINK_DIAL_CONTENT, contentActor, contentRequest, version = apiVersion) } + def reserveDialCode(identifier: String) = Action.async { implicit request => + val headers = commonHeaders() + val body = requestBody() + body.putAll(headers) + body.putAll(Map("identifier" -> identifier).asJava) + val reserveDialCode = getRequest(body, headers, "reserveDialCode") + setRequestContext(reserveDialCode, version, objectType, schemaName) + getResult(ApiId.RESERVE_DIAL_CONTENT, contentActor, reserveDialCode) + } + def upload(identifier: String, fileFormat: Option[String], validation: Option[String]) = Action.async { implicit request => val headers = commonHeaders() val content = requestFormData(identifier) diff --git a/content-api/content-service/conf/routes b/content-api/content-service/conf/routes index fc4c8ad83..17b4e3059 100644 --- a/content-api/content-service/conf/routes +++ b/content-api/content-service/conf/routes @@ -99,6 +99,7 @@ DELETE /content/v4/retire/:identifier controllers.v4.ContentControl PATCH /content/v4/system/update/:identifier controllers.v4.ContentController.systemUpdate(identifier:String) POST /content/v4/review/:identifier controllers.v4.ContentController.review(identifier:String) POST /content/v4/reject/:identifier controllers.v4.ContentController.reviewReject(identifier:String) +POST /content/v4/dialcode/reserve/:identifier controllers.v4.ContentController.reserveDialCode(identifier:String) # App v4 APIs POST /app/v4/register controllers.v4.AppController.register @@ -129,4 +130,5 @@ GET /object/v4/read/:identifier controllers.v4.ObjectController # Collection V4 APIs POST /collection/v4/import/:collectionId controllers.v4.CollectionController.importCollection(collectionId:String) GET /collection/v4/export/:collectionId controllers.v4.CollectionController.exportCollection(collectionId:String, fileType:Option[String]) -POST /collection/v4/review/:identifier controllers.v4.CollectionController.review(identifier:String) \ No newline at end of file +POST /collection/v4/review/:identifier controllers.v4.CollectionController.review(identifier:String) +POST /collection/v4/dialcode/reserve/:identifier controllers.v4.CollectionController.reserveDialCode(identifier:String) \ No newline at end of file From 542ffcde42b99b972355f689130b1ae121f08e2d Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 7 Jul 2022 15:04:46 +0530 Subject: [PATCH 044/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../app/controllers/v4/CollectionController.scala | 2 +- content-api/content-service/app/utils/ApiId.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/content-api/content-service/app/controllers/v4/CollectionController.scala b/content-api/content-service/app/controllers/v4/CollectionController.scala index cd84c0579..4dfd17829 100644 --- a/content-api/content-service/app/controllers/v4/CollectionController.scala +++ b/content-api/content-service/app/controllers/v4/CollectionController.scala @@ -193,7 +193,7 @@ class CollectionController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentAc body.putAll(Map("identifier" -> identifier).asJava) val reserveDialCode = getRequest(body, headers, "reserveDialCode") setRequestContext(reserveDialCode, version, objectType, schemaName) - getResult(ApiId.RESERVE_DIAL_CONTENT, contentActor, reserveDialCode) + getResult(ApiId.RESERVE_DIAL_COLLECTION, contentActor, reserveDialCode) } def copy(identifier: String, mode: Option[String], copyType: String) = Action.async { implicit request => diff --git a/content-api/content-service/app/utils/ApiId.scala b/content-api/content-service/app/utils/ApiId.scala index 6bad01791..8b5afe44f 100644 --- a/content-api/content-service/app/utils/ApiId.scala +++ b/content-api/content-service/app/utils/ApiId.scala @@ -100,5 +100,5 @@ object ApiId { //Collection CSV APIs val IMPORT_CSV = "api.collection.import" val EXPORT_CSV = "api.collection.export" - + val RESERVE_DIAL_COLLECTION = "api.collection.dialcode.reserve" } From d2bf1945399cd3c4712530a54fbd789ceaaef774 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 7 Jul 2022 15:06:55 +0530 Subject: [PATCH 045/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../content/dial/DIALManagerTest.scala | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index 11e56e0ee..9457a4173 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -574,26 +574,4 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory val resString = "{\"id\": \"api.dialcode.generate\",\"ver\": \"1.0\",\"ts\": \"2022-07-05T09:47:26.000Z\",\"params\": {\"resmsgid\": \"79eb8b00-fc47-11ec-af25-0f53946b16ec\",\"msgid\": \"79be1260-fc47-11ec-8c03-63ca5ce41074\",\"status\": \"successful\",\"err\": null,\"errmsg\": null},\"responseCode\": \"OK\",\"result\": {\"dialcodes\": [\"K2C3R6\",\"H2E8F9\"],\"count\": 2,\"batchcode\": \"do_11357423520695910411\",\"publisher\": null}}" JsonUtils.deserialize(resString, classOf[Response]) } - - def getInvalidChannelReserveDIALRequest(identifier: String): Request = { - val request = new Request() - request.setObjectType("Content") - request.setContext(getInavlidChannelContext()) - request.getContext.put("identifier",identifier) - request.put("identifier",identifier) - request.putAll(getReserveRequest()) - request - } - - def getInavlidChannelContext():util.Map[String, AnyRef] = { - val contextMap: java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){{ - put("graph_id", "domain") - put("version" , "1.0") - put("objectType" , "Content") - put("schemaName", "content") - put("channel", "invalidChannel") - }} - contextMap - } - } \ No newline at end of file From 34ab1982e82c2da6cd097dad8e6baf6af08f6516 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 12 Jul 2022 11:19:50 +0530 Subject: [PATCH 046/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../main/scala/org/sunbird/content/dial/DIALManager.scala | 2 +- .../content-actors/src/test/resources/application.conf | 7 +++++-- content-api/content-service/conf/application.conf | 8 +++++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 9f4ca3b2a..a3bd862d4 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -21,7 +21,7 @@ import scala.concurrent.{ExecutionContext, Future} object DIALManager { val DIAL_SEARCH_API_URL: String = Platform.config.getString("dial_service.api.base_url") + Platform.config.getString("dial_service.api.search") - val DIALCODE_GENERATE_URI: String = Platform.config.getString("dial_service.api.base_url") + Platform.config.getString("dial_service.api.generate_url") + val DIALCODE_GENERATE_URI: String = Platform.config.getString("dial_service.api.base_url") + Platform.config.getString("dial_service.api.generate") val DIAL_API_AUTH_KEY: String = "Bearer " + Platform.config.getString("dial_service.api.auth_key") val PASSPORT_KEY: String = Platform.config.getString("graph.passport.key.base") diff --git a/content-api/content-actors/src/test/resources/application.conf b/content-api/content-actors/src/test/resources/application.conf index 54ea3dcf7..837e732ba 100644 --- a/content-api/content-actors/src/test/resources/application.conf +++ b/content-api/content-actors/src/test/resources/application.conf @@ -496,14 +496,17 @@ dial_service { base_url = "https://qa.ekstep.in/api" auth_key = "auth_key" search = "/dialcode/v1/search" - generate_url = "/dialcode/v1/generate" + generate = "/dialcode/v1/generate" } } content.link_dialcode.validation=true content.link_dialcode.max_limit=10 -reserve_dialcode.mimeType = ["application/vnd.ekstep.content-collection", "application/pdf"] +reserve_dialcode { + mimeType = ["application/vnd.ekstep.content-collection", "application/pdf"] + max_count = 250 +} # This is added to handle large artifacts sizes differently content.artifact.size.for_online=209715200 diff --git a/content-api/content-service/conf/application.conf b/content-api/content-service/conf/application.conf index a4a6147e2..b969a73eb 100644 --- a/content-api/content-service/conf/application.conf +++ b/content-api/content-service/conf/application.conf @@ -604,9 +604,15 @@ dial_service { base_url = "https://qa.ekstep.in/api" auth_key = "auth_key" search = "/dialcode/v1/search" - generate_url = "/dialcode/v1/generate" + generate = "/api/dialcode/v1/generate" } } + +reserve_dialcode { + mimeType = ["application/vnd.ekstep.content-collection"] + max_count = 250 +} + content.link_dialcode.validation=true content.link_dialcode.max_limit=10 # This is added to handle large artifacts sizes differently From 9bd4a32dcaf49b9de4a4210496eef20fee1a70bb Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Tue, 12 Jul 2022 19:25:28 +0530 Subject: [PATCH 047/105] Issue #SB-30119 test: Added the postman tests for content v2 create, read and update API. --- ...ontent V2 API Test.postman_collection.json | 1165 +++++++++++++++++ .../Content V2.postman_collection.json | 661 ++++++++++ 2 files changed, 1826 insertions(+) create mode 100644 content-api/api-test/Content V2 API Test.postman_collection.json create mode 100644 content-api/api-test/Content V2.postman_collection.json diff --git a/content-api/api-test/Content V2 API Test.postman_collection.json b/content-api/api-test/Content V2 API Test.postman_collection.json new file mode 100644 index 000000000..64dc2f6cf --- /dev/null +++ b/content-api/api-test/Content V2 API Test.postman_collection.json @@ -0,0 +1,1165 @@ +{ + "info": { + "_postman_id": "58a713b4-b8bb-4885-9909-b23d253f8f31", + "name": "Content V2 API Test", + "description": "The Content Management APIs allow you to create, manage and process content on the Sunbird platform. Content is the basic building block of the Knowledge Service. Some examples would be Videos, Audio, Pdfs, Html, ECML etc. The basic operations for this API include Create, Update, Read, Review, Publish.\n\nThe URL for Content Management API(s) is /content/v1.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "1419050" + }, + "item": [ + { + "name": "Positive", + "item": [ + { + "name": "Content Create ", + "item": [ + { + "name": "Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "pm.test(\"Content-Encoding header is present\", () => {", + " pm.response.to.have.header(\"Content-Encoding\");", + "});", + "pm.test(\"Content-Encoding header is gzip\", () => {", + " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", + " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.create\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", + "});", + "pm.test(\"ver should be 4.0\", function () {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.status should be successful\", function () {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", function () {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});", + "", + "// Set global variable", + "pm.globals.set(\"content_id\", jsonResponse.result.identifier);", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + } + ] + }, + { + "name": "Content Read", + "item": [ + { + "name": "Content Read", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200)", + "});", + "", + "//code name contains a string", + "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", + "", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "pm.test(\"Content-Encoding header is present\", () => {", + " pm.response.to.have.header(\"Content-Encoding\");", + "});", + "pm.test(\"Content-Encoding header is gzip\", () => {", + " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + " pm.expect(jsonResponse.result).to.be.an(\"object\").that.has.all.keys('content');", + " pm.expect(jsonResponse.result.content).to.be.an(\"object\")", + " pm.expect(jsonResponse.result.content).to.have.any.keys('identifier', 'versionKey', 'code', 'channel', 'mimeType', 'createdOn', 'primaryCategory', 'contentDisposition', 'contentEncoding', 'objectType', 'visibility', 'discussionForum', 'license', 'version', 'compatibilityLevel', 'name', 'status');", + " pm.expect(jsonResponse.result.content.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.content.versionKey).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.content.version).to.be.a(\"number\");", + " pm.expect(jsonResponse.result.content.channel).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.content.compatibilityLevel).to.be.a(\"number\");", + " pm.expect(jsonResponse.result.content.ownershipType).to.be.an(\"array\");", + " pm.expect(jsonResponse.result.content.trackable).to.be.an(\"object\");", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.read\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.read\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.status should be successful\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});", + "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), () => {", + " pm.expect(jsonResponse.result.content.identifier).to.eql(pm.globals.get(\"content_id\"));", + "});", + "pm.test(\"objectType should be Content\", () => {", + " pm.expect(jsonResponse.result.content.objectType).to.eql(\"Content\");", + "});", + "pm.test(\"visibility should be Default\", () => {", + " pm.expect(jsonResponse.result.content.visibility).to.eql(\"Default\");", + "});", + "pm.test(\"compatibilityLevel should be 1\", () => {", + " pm.expect(jsonResponse.result.content.compatibilityLevel).to.eql(1);", + "});", + "pm.test(\"status should be Draft\", () => {", + " pm.expect(jsonResponse.result.content.status).to.eql(\"Draft\");", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + } + ], + "url": { + "raw": "{{host}}/content/v2/read/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "read", + "{{content_id}}" + ] + }, + "description": "Fetch a particular Batch\nThis API is associated with fetching a particular batch on the Sunbird Platform.\nThe endpoint for Fetch a particular Batch is /batch/read/{Batch_ID}\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "Content Read - fields query params", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200)", + "});", + "", + "//code name contains a string", + "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", + "", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "pm.test(\"Content-Encoding header is present\", () => {", + " pm.response.to.have.header(\"Content-Encoding\");", + "});", + "pm.test(\"Content-Encoding header is gzip\", () => {", + " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + " pm.expect(jsonResponse.result).to.be.an(\"object\").that.has.all.keys('content');", + " pm.expect(jsonResponse.result.content).to.be.an(\"object\")", + " pm.expect(jsonResponse.result.content).to.have.all.keys('identifier', 'primaryCategory', 'name', 'languageCode');", + " pm.expect(jsonResponse.result.content.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.content.versionKey).to.be.undefined;", + " pm.expect(jsonResponse.result.content.version).to.be.undefined;", + " pm.expect(jsonResponse.result.content.channel).to.be.undefined;", + " pm.expect(jsonResponse.result.content.compatibilityLevel).to.be.undefined;", + " pm.expect(jsonResponse.result.content.languageCode).to.be.an(\"array\");", + " pm.expect(jsonResponse.result.content.trackable).to.be.undefined;", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.read\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.read\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.status should be successful\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});", + "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), () => {", + " pm.expect(jsonResponse.result.content.identifier).to.eql(pm.globals.get(\"content_id\"));", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + } + ], + "url": { + "raw": "{{host}}/content/v2/read/{{content_id}}?fields=name,primaryCategory", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "read", + "{{content_id}}" + ], + "query": [ + { + "key": "fields", + "value": "name,primaryCategory" + } + ] + }, + "description": "Fetch a particular Batch\nThis API is associated with fetching a particular batch on the Sunbird Platform.\nThe endpoint for Fetch a particular Batch is /batch/read/{Batch_ID}\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Content Update", + "item": [ + { + "name": "Content Update", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "pm.test(\"Content-Encoding header is present\", () => {", + " pm.response.to.have.header(\"Content-Encoding\");", + "});", + "pm.test(\"Content-Encoding header is gzip\", () => {", + " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", + " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.update\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", + "});", + "pm.test(\"ver should be 4.0\", function () {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.status should be successful\", function () {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", function () {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});", + "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), function () {", + " pm.expect(jsonResponse.result.identifier).to.eql(pm.globals.get(\"content_id\"));", + "});", + "pm.test(\"node_id should be equal to \" + pm.globals.get(\"content_id\"), function () {", + " pm.expect(jsonResponse.result.node_id).to.eql(pm.globals.get(\"content_id\"));", + "});", + "", + "// Set global variable", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "update", + "{{content_id}}" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + } + ] + }, + { + "name": "Negative", + "item": [ + { + "name": "Content Create", + "item": [ + { + "name": "Content Create - 404 - Invalid primaryCategory", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", + "", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "pm.test(\"Content-Encoding header should not present\", () => {", + " pm.response.to.have.header(\"Content-Encoding\");", + "});", + "pm.test(\"Content-Encoding header is gzip\", () => {", + " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.a(\"string\");", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.be.null;", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.create\", () => {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.err should be \\\"404\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"404\");", + "});", + "pm.test(\"params.status should be \\\"failed\\\"\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "});", + "pm.test(\"params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:aaaa_content_all {}\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Entry is not found in cassandra for content with identifier: obj-cat:aaaa_content_all {}\");", + "});", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "});", + "pm.test(\"messages should be null\", () => {", + " pm.expect(jsonResponse.result.messages).to.eql(null);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"aaaa\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + } + ] + }, + { + "name": "Content Read", + "item": [ + { + "name": "Content Read", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", + "", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "pm.test(\"Content-Encoding header should not present\", () => {", + " pm.response.to.have.header(\"Content-Encoding\");", + "});", + "pm.test(\"Content-Encoding header is gzip\", () => {", + " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.a(\"string\");", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.be.null;", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.read\", () => {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.read\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.err should be \\\"NOT_FOUND\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"NOT_FOUND\");", + "});", + "pm.test(\"params.status should be \\\"failed\\\"\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "});", + "pm.test(\"params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_42353245436534\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_42353245436534\");", + "});", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "});", + "pm.test(\"messages should be null\", () => {", + " pm.expect(jsonResponse.result.messages).to.eql(null);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + } + ], + "url": { + "raw": "{{host}}/content/v2/read/do_42353245436534", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "read", + "do_42353245436534" + ] + }, + "description": "Fetch a particular Batch\nThis API is associated with fetching a particular batch on the Sunbird Platform.\nThe endpoint for Fetch a particular Batch is /batch/read/{Batch_ID}\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Content Update", + "item": [ + { + "name": "Content Update - 400 - Invalid versionKey", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string Bad Request\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "pm.test(\"Content-Encoding header should not present\", () => {", + " pm.response.to.not.have.header(\"Content-Encoding\");", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.a(\"string\");", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.be.null;", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.update\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", + "});", + "pm.test(\"ver should be 4.0\", function () {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.err should be CLIENT_ERROR\", function () {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.status should be failed\", function () {", + " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "});", + "pm.test(\"params.errmsg should be \\\"Invalid version Key\\\"\", function () {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Invalid version Key\");", + "});", + "pm.test(\"responseCode should be CLIENT_ERROR\", function () {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"messages should be null\", function () {", + " pm.expect(jsonResponse.result.messages).to.eql(null);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"3423423\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/update/do_213579099726987264122", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "update", + "do_213579099726987264122" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "Content Update - 404 - Invalid content id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", + "", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "pm.test(\"Content-Encoding header should not present\", () => {", + " pm.response.to.have.header(\"Content-Encoding\");", + "});", + "pm.test(\"Content-Encoding header is gzip\", () => {", + " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.a(\"string\");", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.be.null;", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.update\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", + "});", + "pm.test(\"ver should be 4.0\", function () {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.err should be NOT_FOUND\", function () {", + " pm.expect(jsonResponse.params.err).to.eql(\"NOT_FOUND\");", + "});", + "pm.test(\"params.status should be failed\", function () {", + " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "});", + "pm.test(\"params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_21357909972698726412211\\\"\", function () {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_21357909972698726412211\");", + "});", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", function () {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "});", + "pm.test(\"messages should be null\", function () {", + " pm.expect(jsonResponse.result.messages).to.eql(null);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/update/do_21357909972698726412211", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "update", + "do_21357909972698726412211" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "Content Update - 404 - Invalid primaryCategory", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", + "", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "pm.test(\"Content-Encoding header should not present\", () => {", + " pm.response.to.have.header(\"Content-Encoding\");", + "});", + "pm.test(\"Content-Encoding header is gzip\", () => {", + " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.a(\"string\");", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.be.null;", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.update\", () => {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.err should be \\\"404\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"404\");", + "});", + "pm.test(\"params.status should be \\\"failed\\\"\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "});", + "pm.test(\"params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\");", + "});", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "});", + "pm.test(\"messages should be null\", () => {", + " pm.expect(jsonResponse.result.messages).to.eql(null);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "update", + "{{content_id}}" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/content-api/api-test/Content V2.postman_collection.json b/content-api/api-test/Content V2.postman_collection.json new file mode 100644 index 000000000..b11d5a029 --- /dev/null +++ b/content-api/api-test/Content V2.postman_collection.json @@ -0,0 +1,661 @@ +{ + "info": { + "_postman_id": "c1421998-1fcb-44c7-9db1-9421f27b0a98", + "name": "Content V2", + "description": "The Content Management APIs allow you to create, manage and process content on the Sunbird platform. Content is the basic building block of the Knowledge Service. Some examples would be Videos, Audio, Pdfs, Html, ECML etc. The basic operations for this API include Create, Update, Read, Review, Publish.\n\nThe URL for Content Management API(s) is /content/v1.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "1419050" + }, + "item": [ + { + "name": "Content Create ", + "item": [ + { + "name": "Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "pm.test(\"Content-Encoding header is present\", () => {", + " pm.response.to.have.header(\"Content-Encoding\");", + "});", + "pm.test(\"Content-Encoding header is gzip\", () => {", + " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", + " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.create\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", + "});", + "pm.test(\"ver should be 4.0\", function () {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.status should be successful\", function () {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", function () {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});", + "", + "// Set global variable", + "pm.globals.set(\"content_id\", jsonResponse.result.identifier);", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "userId", + "value": "user", + "type": "text" + }, + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "Cookie", + "value": "connect.sid=s%3AyRLPeHt6zZ93WjZ2BD_Cejc11xNN-isK.ANbL%2FZ1t88yXax%2BiXjGFVtgFUAKhoWdl%2FgXU4yBX9rU; 81f30cf708470b974874c8a96a6bcdb2=l99ob678op07nq0qs5i0dae0m3; AWSELB=83D53DFF08C363B9195F6717118E44E326DE55CB796FB96A69500BA54C477B7512D6342B64B0B494BBD6699FCFFFB308C0DC9247AA23DA73B4F62BA4C399A735F647C86F50", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"mimeType\": \"application/pdf\",\n \"code\": \"api-docs\",\n \"primaryCategory\": \"Explanation Content\",\n \"createdBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Mon, 23 Nov 2020 06:42:39 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "30000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "29991" + }, + { + "key": "Referrer-Policy", + "value": "origin-when-cross-origin, strict-origin-when-cross-origin" + }, + { + "key": "X-Frame-Options", + "value": "DENY" + }, + { + "key": "X-XSS-Protection", + "value": "1; mode=block" + }, + { + "key": "x-response-length", + "value": "55" + }, + { + "key": "X-Content-Type-Options", + "value": "nosniff" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Permitted-Cross-Domain-Policies", + "value": "master-only" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "53" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "36" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"1.0\",\n \"ts\": \"2020-12-09T11:11:12.697Z\",\n \"params\": {\n \"resmsgid\": \"3f5de290-3a0f-11eb-be5b-f9d249ba9049\",\n \"msgid\": \"3f57a100-3a0f-11eb-be5b-f9d249ba9049\",\n \"status\": \"successful\",\n \"err\": null,\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"content_id\": \"do_1131687405374504961738\",\n \"versionKey\": \"1607512272640\"\n }\n}" + } + ] + } + ] + }, + { + "name": "Content Read", + "item": [ + { + "name": "Content Read", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200)", + "});", + "", + "//code name contains a string", + "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", + "", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "pm.test(\"Content-Encoding header is present\", () => {", + " pm.response.to.have.header(\"Content-Encoding\");", + "});", + "pm.test(\"Content-Encoding header is gzip\", () => {", + " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + " pm.expect(jsonResponse.result).to.be.an(\"object\").that.has.all.keys('content');", + " pm.expect(jsonResponse.result.content).to.be.an(\"object\")", + " pm.expect(jsonResponse.result.content).to.have.any.keys('identifier', 'versionKey', 'code', 'channel', 'mimeType', 'createdOn', 'primaryCategory', 'contentDisposition', 'contentEncoding', 'objectType', 'visibility', 'discussionForum', 'license', 'version', 'compatibilityLevel', 'name', 'status');", + " pm.expect(jsonResponse.result.content.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.content.versionKey).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.content.version).to.be.a(\"number\");", + " pm.expect(jsonResponse.result.content.channel).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.content.compatibilityLevel).to.be.a(\"number\");", + " pm.expect(jsonResponse.result.content.ownershipType).to.be.an(\"array\");", + " pm.expect(jsonResponse.result.content.trackable).to.be.an(\"object\");", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.read\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.read\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.status should be successful\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});", + "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), () => {", + " pm.expect(jsonResponse.result.content.identifier).to.eql(pm.globals.get(\"content_id\"));", + "});", + "pm.test(\"objectType should be Content\", () => {", + " pm.expect(jsonResponse.result.content.objectType).to.eql(\"Content\");", + "});", + "pm.test(\"visibility should be Default\", () => {", + " pm.expect(jsonResponse.result.content.visibility).to.eql(\"Default\");", + "});", + "pm.test(\"compatibilityLevel should be 1\", () => {", + " pm.expect(jsonResponse.result.content.compatibilityLevel).to.eql(1);", + "});", + "pm.test(\"status should be Draft\", () => {", + " pm.expect(jsonResponse.result.content.status).to.eql(\"Draft\");", + "});", + "", + "pm.globals.set(\"versionKey\", jsonResponse.result.content.versionKey);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + } + ], + "url": { + "raw": "{{host}}/content/v2/read/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "read", + "{{content_id}}" + ] + }, + "description": "Fetch a particular Batch\nThis API is associated with fetching a particular batch on the Sunbird Platform.\nThe endpoint for Fetch a particular Batch is /batch/read/{Batch_ID}\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [ + { + "name": "Content Read - 200 OK", + "originalRequest": { + "method": "GET", + "header": [ + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + } + ], + "url": { + "raw": "{{host}}/content/v2/read/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "read", + "{{content_id}}" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Mon, 23 Nov 2020 04:48:35 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "30000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "29999" + }, + { + "key": "Referrer-Policy", + "value": "origin-when-cross-origin, strict-origin-when-cross-origin" + }, + { + "key": "X-Frame-Options", + "value": "DENY" + }, + { + "key": "X-XSS-Protection", + "value": "1; mode=block" + }, + { + "key": "x-response-length", + "value": "2759" + }, + { + "key": "X-Content-Type-Options", + "value": "nosniff" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Permitted-Cross-Domain-Policies", + "value": "master-only" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "11" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "35" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "X-Proxy-Cache", + "value": "MISS" + }, + { + "key": "X-Proxy-Cache-Date", + "value": "Mon, 23 Nov 2020 04:48:35 GMT" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.read\",\n \"ver\": \"1.0\",\n \"ts\": \"2020-12-09T12:09:04.202Z\",\n \"params\": {\n \"resmsgid\": \"548b82a0-3a17-11eb-be5b-f9d249ba9049\",\n \"msgid\": \"5488ea90-3a17-11eb-be5b-f9d249ba9049\",\n \"status\": \"successful\",\n \"err\": null,\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"content\": {\n \"ownershipType\": [\n \"createdBy\"\n ],\n \"code\": \"org.sunbird.ccG6ru\",\n \"credentials\": {\n \"enabled\": \"No\"\n },\n \"channel\": \"in.ekstep\",\n \"language\": [\n \"English\"\n ],\n \"mimeType\": \"application/pdf\",\n \"idealScreenSize\": \"normal\",\n \"createdOn\": \"2020-12-09T12:08:54.913+0000\",\n \"objectType\": \"Content\",\n \"primaryCategory\": \"Explanation Content\",\n \"contentDisposition\": \"inline\",\n \"lastUpdatedOn\": \"2020-12-09T12:08:54.913+0000\",\n \"contentEncoding\": \"identity\",\n \"contentType\": \"Resource\",\n \"dialcodeRequired\": \"No\",\n \"identifier\": \"do_1131687689003827201864\",\n \"lastStatusChangedOn\": \"2020-12-09T12:08:54.913+0000\",\n \"audience\": [\n \"Student\"\n ],\n \"os\": [\n \"All\"\n ],\n \"visibility\": \"Default\",\n \"consumerId\": \"7411b6bd-89f3-40ec-98d1-229dc64ce77d\",\n \"mediaType\": \"content\",\n \"osId\": \"org.ekstep.quiz.app\",\n \"languageCode\": [\n \"en\"\n ],\n \"version\": 2,\n \"versionKey\": \"1607515734913\",\n \"license\": \"CC BY 4.0\",\n \"idealScreenDensity\": \"hdpi\",\n \"framework\": \"NCF\",\n \"createdBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"compatibilityLevel\": 1,\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"status\": \"Draft\"\n }\n }\n}" + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Content Update", + "item": [ + { + "name": "Content Update", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "pm.test(\"Content-Encoding header is present\", () => {", + " pm.response.to.have.header(\"Content-Encoding\");", + "});", + "pm.test(\"Content-Encoding header is gzip\", () => {", + " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", + " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.update\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", + "});", + "pm.test(\"ver should be 4.0\", function () {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.status should be successful\", function () {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", function () {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});", + "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), function () {", + " pm.expect(jsonResponse.result.identifier).to.eql(pm.globals.get(\"content_id\"));", + "});", + "pm.test(\"node_id should be equal to \" + pm.globals.get(\"content_id\"), function () {", + " pm.expect(jsonResponse.result.node_id).to.eql(pm.globals.get(\"content_id\"));", + "});", + "", + "// Set global variable", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "update", + "{{content_id}}" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + } + ] +} \ No newline at end of file From c2604aa3f4649d8f402d206425b842eba455b00c Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 14 Jul 2022 12:11:16 +0530 Subject: [PATCH 048/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../sunbird/content/dial/DIALConstants.scala | 6 +- .../sunbird/content/dial/DIALManager.scala | 216 ++++++++++-------- .../content/util/ContentConstants.scala | 3 + 3 files changed, 128 insertions(+), 97 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALConstants.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALConstants.scala index 4891f30e1..6d6c99e25 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALConstants.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALConstants.scala @@ -20,5 +20,9 @@ object DIALConstants { val DISCUSSION_FORUM: String = "discussionForum" val CREDENTIALS: String = "credentials" val TRACKABLE: String = "trackable" - + val PROCESS_ID: String = "processId" + val PUBLISHER: String = "publisher" + val BATCH_CODE: String = "batchCode" + val LIVE_STATUS: String = "Live" + val UNLISTED_STATUS: String = "Unlisted" } \ No newline at end of file diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index a3bd862d4..81087b514 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -10,7 +10,6 @@ import org.sunbird.graph.dac.model.Node import org.sunbird.graph.nodes.DataNode import org.sunbird.graph.utils.ScalaJsonUtils import org.sunbird.managers.HierarchyManager -import org.sunbird.telemetry.logger.TelemetryManager import java.util import scala.collection.JavaConverters._ @@ -22,7 +21,7 @@ object DIALManager { val DIAL_SEARCH_API_URL: String = Platform.config.getString("dial_service.api.base_url") + Platform.config.getString("dial_service.api.search") val DIALCODE_GENERATE_URI: String = Platform.config.getString("dial_service.api.base_url") + Platform.config.getString("dial_service.api.generate") - val DIAL_API_AUTH_KEY: String = "Bearer " + Platform.config.getString("dial_service.api.auth_key") + val DIAL_API_AUTH_KEY: String = ContentConstants.BEARER + Platform.config.getString("dial_service.api.auth_key") val PASSPORT_KEY: String = Platform.config.getString("graph.passport.key.base") def link(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { @@ -64,7 +63,7 @@ object DIALManager { contents.foreach(id => reqMap += (id -> dialcodes)) }) if (Platform.getBoolean("content.link_dialcode.validation", true)) { - val dials = requestList.collect { case m if m.get(DIALConstants.DIALCODE).nonEmpty => m.get(DIALConstants.DIALCODE).get }.flatten + val dials = requestList.collect { case m if m.contains(DIALConstants.DIALCODE) => m(DIALConstants.DIALCODE) }.flatten validateDialCodes(channelId, dials) } reqMap @@ -88,10 +87,8 @@ object DIALManager { }}) }} val headerParam = new util.HashMap[String, String]{put(DIALConstants.X_CHANNEL_ID, channelId); put(DIALConstants.AUTHORIZATION, DIAL_API_AUTH_KEY);} - TelemetryManager.info("DIALManager::validateAndGetRequestMap:: DIAL_SEARCH_API_URL: " + DIAL_SEARCH_API_URL) - TelemetryManager.info("DIALManager::validateAndGetRequestMap:: reqMap: " + reqMap) val searchResponse = oec.httpUtil.post(DIAL_SEARCH_API_URL, reqMap, headerParam) - if (searchResponse.getResponseCode.toString == "OK") { + if (searchResponse.getResponseCode.toString == ContentConstants.OK_RESPONSE_CODE) { val result = searchResponse.getResult if (dialcodes.distinct.size == result.get(DIALConstants.COUNT).asInstanceOf[Integer]) { return true @@ -129,46 +126,18 @@ object DIALManager { req.setContext(reqContext) req.put(ContentConstants.IDENTIFIER, objectId) req.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) - TelemetryManager.info("DIALManager::linkCollection:: req: " + req) DataNode.read(req).flatMap(rootNode => { req.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) req.getContext.put(ContentConstants.VERSION, ContentConstants.SCHEMA_VERSION) req.put(ContentConstants.ROOT_ID, objectId) - TelemetryManager.info("DIALManager::linkCollection:: updated req: " + req) HierarchyManager.getHierarchy(req).flatMap(getHierarchyResponse => { - val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]] - val updatedChildrenHierarchy = updateChildrenHierarchy(childrenHierarchy, requestMap) - val childrenDIALMap = getChildrenDIALMap(updatedChildrenHierarchy, requestMap) - val consolidatedUnitDIALMap = if (!requestMap.contains(objectId)) childrenDIALMap else childrenDIALMap ++ Map(objectId -> requestMap(objectId)) - TelemetryManager.info("DIALManager::linkCollection:: consolidatedUnitDIALMap: " + consolidatedUnitDIALMap) + val updatedChildrenHierarchy = getUpdatedChildrenHierarchy(getHierarchyResponse, requestMap) + val consolidatedUnitDIALMap = getConsolidatedUnitDIALMap(updatedChildrenHierarchy, requestMap, objectId) validateDuplicateDIALCodes(consolidatedUnitDIALMap.filter(rec => rec._2.asInstanceOf[List[String]].nonEmpty)) - val updatedHierarchy = new java.util.HashMap[String, AnyRef]() - updatedHierarchy.put(ContentConstants.IDENTIFIER, objectId) - updatedHierarchy.put(ContentConstants.CHILDREN, updatedChildrenHierarchy.asJava) - - val hierarchyReq = new Request(req) - hierarchyReq.put(ContentConstants.HIERARCHY, ScalaJsonUtils.serialize(updatedHierarchy)) - hierarchyReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) - TelemetryManager.info("DIALManager::linkCollection:: hierarchyReq: " + hierarchyReq) + val hierarchyReq = getHierarchyRequest(req, objectId, updatedChildrenHierarchy, rootNode) oec.graphService.saveExternalProps(hierarchyReq).flatMap(rec => if(requestMap.contains(objectId)) { - val updateReq = new Request(req) - updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) - val rootNodeMetadata = rootNode.getMetadata - rootNodeMetadata.remove(DIALConstants.DISCUSSION_FORUM) - rootNodeMetadata.remove(DIALConstants.CREDENTIALS) - rootNodeMetadata.remove(DIALConstants.TRACKABLE) - - if(rootNodeMetadata.containsKey(DIALConstants.DIALCODES)) - rootNodeMetadata.remove(DIALConstants.DIALCODES) - - if(requestMap(objectId).isEmpty) - updateReq.put(DIALConstants.DIALCODES, null) - else - updateReq.put(DIALConstants.DIALCODES, requestMap(objectId).toArray[String]) - - updateReq.getRequest.putAll(rootNodeMetadata) + val updateReq = getLinkUpdateRequest(req, rootNode, requestMap, objectId) DataNode.update(updateReq).flatMap(response => { getResponseCollectionLink(requestMap, consolidatedUnitDIALMap.keySet.toList, requestMap.keySet.diff(consolidatedUnitDIALMap.keySet).toList) @@ -180,6 +149,49 @@ object DIALManager { }) } + def getUpdatedChildrenHierarchy(getHierarchyResponse: Response, requestMap: Map[String, List[String]]): List[util.Map[String, AnyRef]] = { + val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] + val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]] + updateChildrenHierarchy(childrenHierarchy, requestMap) + } + + def getConsolidatedUnitDIALMap(updatedChildrenHierarchy: List[util.Map[String, AnyRef]], requestMap: Map[String, List[String]], objectId: String): Map[String, AnyRef] = { + val childrenDIALMap = getChildrenDIALMap(updatedChildrenHierarchy, requestMap) + if (!requestMap.contains(objectId)) childrenDIALMap else childrenDIALMap ++ Map(objectId -> requestMap(objectId)) + } + + def getHierarchyRequest(req: Request, objectId: String, updatedChildrenHierarchy: List[util.Map[String, AnyRef]], rootNode: Node): Request = { + val updatedHierarchy = new java.util.HashMap[String, AnyRef]() + updatedHierarchy.put(ContentConstants.IDENTIFIER, objectId) + updatedHierarchy.put(ContentConstants.CHILDREN, updatedChildrenHierarchy.asJava) + + val hierarchyReq = new Request(req) + hierarchyReq.put(ContentConstants.HIERARCHY, ScalaJsonUtils.serialize(updatedHierarchy)) + hierarchyReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) + + hierarchyReq + } + + def getLinkUpdateRequest(req: Request, rootNode: Node, requestMap: Map[String, List[String]], objectId: String): Request = { + val updateReq = new Request(req) + updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) + val rootNodeMetadata = rootNode.getMetadata + rootNodeMetadata.remove(DIALConstants.DISCUSSION_FORUM) + rootNodeMetadata.remove(DIALConstants.CREDENTIALS) + rootNodeMetadata.remove(DIALConstants.TRACKABLE) + + if(rootNodeMetadata.containsKey(DIALConstants.DIALCODES)) + rootNodeMetadata.remove(DIALConstants.DIALCODES) + + if(requestMap(objectId).isEmpty) + updateReq.put(DIALConstants.DIALCODES, null) + else + updateReq.put(DIALConstants.DIALCODES, requestMap(objectId).toArray[String]) + + updateReq.getRequest.putAll(rootNodeMetadata) + updateReq + } + def validateContents(requestMap: Map[String, List[String]], reqContext: util.Map[String, AnyRef])(implicit ec: ExecutionContext, oec:OntologyEngineContext): Future[List[String]] = { val request = new Request() request.setContext(reqContext) @@ -219,7 +231,7 @@ object DIALManager { def updateChildrenHierarchy(childrenHierarchy: util.List[util.Map[String, AnyRef]], requestMap: Map[String, List[String]]): List[util.Map[String, AnyRef]] = { childrenHierarchy.asScala.toList.map(child => { - if (requestMap.contains(child.get(ContentConstants.IDENTIFIER).toString) && StringUtils.equalsIgnoreCase("Parent", child.get(ContentConstants.VISIBILITY).toString)) { + if (requestMap.contains(child.get(ContentConstants.IDENTIFIER).toString) && StringUtils.equalsIgnoreCase(ContentConstants.PARENT, child.get(ContentConstants.VISIBILITY).toString)) { if (requestMap.getOrElse(child.get(ContentConstants.IDENTIFIER).toString, List.empty).nonEmpty && requestMap(child.get(ContentConstants.IDENTIFIER).toString).exists(rec => rec.trim.nonEmpty)) child.put(DIALConstants.DIALCODES, requestMap(child.get(ContentConstants.IDENTIFIER).toString)) else @@ -269,62 +281,30 @@ object DIALManager { req.setContext(request.getContext) req.put(DIALConstants.IDENTIFIER, contentId) req.put(ContentConstants.ROOT_ID, contentId) - req.put(ContentConstants.MODE, "edit") + req.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) DataNode.read(req).flatMap(rootNode => { val contentMetadata = rootNode.getMetadata - TelemetryManager.info("DialManager:: reserve:: contentMetadata: " + contentMetadata) - val contentChannel = contentMetadata.get("channel").asInstanceOf[String] - validateChannel(contentChannel, channelId) + + validateChannel(contentMetadata.get(DIALConstants.CHANNEL).asInstanceOf[String], channelId) validateContentForReservedDialcodes(contentMetadata) - validateCountForReservingDialCode(request.getRequest.get("dialcodes").asInstanceOf[util.Map[String, AnyRef]]) - - if (contentMetadata.get("status").asInstanceOf[String].equalsIgnoreCase("Live") || contentMetadata.get("status").asInstanceOf[String].equalsIgnoreCase("Unlisted")) - throw new ClientException(DIALErrors.ERR_CONTENT_INVALID_OBJECT, DIALErrors.ERR_CONTENT_INVALID_OBJECT_MSG) - - val reservedDialCodes = contentMetadata.getOrDefault("dialcodes", Map.empty[String, Integer]).asInstanceOf[Map[String, Integer]] - TelemetryManager.info("DialManager:: reserve:: reservedDialCodes: " + reservedDialCodes) - val maxIndex: Integer = if (reservedDialCodes.nonEmpty) reservedDialCodes.max._2 else -1 - val dialCodes = reservedDialCodes.keySet - val reqDialcodesCount = request.getRequest.get("dialcodes").asInstanceOf[util.Map[String, AnyRef]].get("count").asInstanceOf[Integer] - TelemetryManager.info("DialManager:: reserve:: reqDialcodesCount: " + reqDialcodesCount) - val updateDialCodes = if (dialCodes.size < reqDialcodesCount) { - val newDialcodes = generateDialCodes(channelId, contentId, reqDialcodesCount - dialCodes.size, request.get("publisher").asInstanceOf[String]) - val newDialCodesMap: Map[String, Integer] = newDialcodes.zipWithIndex.map { case (newDialCode, idx) => - (newDialCode -> (maxIndex + idx + 1).asInstanceOf[Integer]) - }.toMap - reservedDialCodes ++ newDialCodesMap - } else reservedDialCodes - TelemetryManager.info("DialManager:: reserve:: updateDialCodes: " + updateDialCodes) + validateCountForReservingDialCode(request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]]) + validateContentStatus(contentMetadata) + + val reservedDialCodes = contentMetadata.getOrDefault(DIALConstants.DIALCODES, Map.empty[String, Integer]).asInstanceOf[Map[String, Integer]] + val updateDialCodes = getUpdateDIALCodes(reservedDialCodes, request, channelId, contentId) + if(updateDialCodes.size > reservedDialCodes.size) { - val updateReq = new Request(req) - updateReq.setContext(request.getContext) - updateReq.getContext.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) - updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) - val rootNodeMetadata = rootNode.getMetadata - rootNodeMetadata.remove(DIALConstants.DISCUSSION_FORUM) - rootNodeMetadata.remove(DIALConstants.CREDENTIALS) - rootNodeMetadata.remove(DIALConstants.TRACKABLE) - - updateReq.put(DIALConstants.RESERVED_DIALCODES, updateDialCodes) - updateReq.getRequest.putAll(rootNodeMetadata) + val updateReq = getDIALReserveUpdateRequest(req, request, rootNode, updateDialCodes) DataNode.update(updateReq).map(updatedNode => { val response = ResponseHandler.OK() - response.getResult.put("count", updateDialCodes.size.asInstanceOf[Integer]) - response.getResult.put("node_id", contentId) - response.getResult.put("processId", updatedNode.getMetadata.get("processId")) - response.getResult.put("reservedDialcodes", updatedNode.getMetadata.get("reservedDialcodes")) - response.getResult.put("versionKey", updatedNode.getMetadata.get("versionKey")) - TelemetryManager.info("DialManager:: reserve:: response: " + response) - response + val updatedSuccessResponse = getDIALReserveUpdateResponse(response, updateDialCodes.size.asInstanceOf[Integer], contentId, updatedNode) + updatedSuccessResponse.getResult.put(DIALConstants.VERSION_KEY, updatedNode.getMetadata.get(DIALConstants.VERSION_KEY)) + updatedSuccessResponse }) } else { val errorResponse = ResponseHandler.ERROR(ResponseCode.CLIENT_ERROR, DIALErrors.ERR_INVALID_COUNT, DIALErrors.ERR_DIAL_INVALID_COUNT_RESPONSE) - errorResponse.getResult.put("count", reservedDialCodes.size.asInstanceOf[Integer]) - errorResponse.getResult.put("node_id", contentId) - errorResponse.getResult.put("processId", rootNode.getMetadata.get("processId")) - errorResponse.getResult.put("reservedDialcodes", rootNode.getMetadata.get("reservedDialcodes")) - TelemetryManager.info("DialManager:: reserve:: errorResponse: " + errorResponse) - Future(errorResponse) + val updatedErrorResponse = getDIALReserveUpdateResponse(errorResponse, reservedDialCodes.size.asInstanceOf[Integer], contentId, rootNode) + Future(updatedErrorResponse) } }) } @@ -335,31 +315,50 @@ object DIALManager { } def validateContentForReservedDialcodes(metaData: util.Map[String, AnyRef]): Unit = { - val validMimeType = if (Platform.config.hasPath("reserve_dialcode.mimeType")) Platform.config.getStringList("reserve_dialcode.mimeType") else util.Arrays.asList("application/vnd.ekstep.content-collection") - if (!validMimeType.contains(metaData.get("mimeType"))) throw new ClientException(DIALErrors.ERR_CONTENT_MIMETYPE, DIALErrors.ERR_CONTENT_MIMETYPE_MSG) + val validMimeType = if (Platform.config.hasPath("reserve_dialcode.mimeType")) Platform.config.getStringList("reserve_dialcode.mimeType") else util.Arrays.asList(ContentConstants.COLLECTION_MIME_TYPE) + if (!validMimeType.contains(metaData.get(ContentConstants.MIME_TYPE))) throw new ClientException(DIALErrors.ERR_CONTENT_MIMETYPE, DIALErrors.ERR_CONTENT_MIMETYPE_MSG) } def validateCountForReservingDialCode(request: util.Map[String, AnyRef]): Unit = { - if (null == request.get("count") || !request.get("count").isInstanceOf[Integer]) throw new ClientException(DIALErrors.ERR_INVALID_COUNT, DIALErrors.ERR_INVALID_COUNT_MSG) - val count = request.get("count").asInstanceOf[Integer] + if (null == request.get(DIALConstants.COUNT) || !request.get(DIALConstants.COUNT).isInstanceOf[Integer]) throw new ClientException(DIALErrors.ERR_INVALID_COUNT, DIALErrors.ERR_INVALID_COUNT_MSG) + val count = request.get(DIALConstants.COUNT).asInstanceOf[Integer] val maxCount = if (Platform.config.hasPath("reserve_dialcode.max_count")) Platform.config.getInt("reserve_dialcode.max_count") else 250 if (count < 1 || count > maxCount) throw new ClientException(DIALErrors.ERR_INVALID_COUNT_RANGE, DIALErrors.ERR_INVALID_COUNT_RANGE_MSG + maxCount + ".") } + def validateContentStatus(contentMetadata: util.Map[String, AnyRef]): Unit = { + if (contentMetadata.get(ContentConstants.STATUS).asInstanceOf[String].equalsIgnoreCase(DIALConstants.LIVE_STATUS) || contentMetadata.get(ContentConstants.STATUS).asInstanceOf[String].equalsIgnoreCase(DIALConstants.UNLISTED_STATUS)) + throw new ClientException(DIALErrors.ERR_CONTENT_INVALID_OBJECT, DIALErrors.ERR_CONTENT_INVALID_OBJECT_MSG) + } + + def getUpdateDIALCodes(reservedDialCodes: Map[String, Integer], request: Request, channelId: String, contentId: String)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Map[String, Integer] = { + val maxIndex: Integer = if (reservedDialCodes.nonEmpty) reservedDialCodes.max._2 else -1 + val dialCodes = reservedDialCodes.keySet + val reqDialcodesCount = request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]].get(DIALConstants.COUNT).asInstanceOf[Integer] + + if (dialCodes.size < reqDialcodesCount) { + val newDialcodes = generateDialCodes(channelId, contentId, reqDialcodesCount - dialCodes.size, request.get(DIALConstants.PUBLISHER).asInstanceOf[String]) + val newDialCodesMap: Map[String, Integer] = newDialcodes.zipWithIndex.map { case (newDialCode, idx) => + (newDialCode -> (maxIndex + idx + 1).asInstanceOf[Integer]) + }.toMap + reservedDialCodes ++ newDialCodesMap + } else reservedDialCodes + } + @throws[Exception] private def generateDialCodes(channelId: String, contentId: String, dialcodeCount: Integer, publisher: String)(implicit oec: OntologyEngineContext): List[String] = { val dialcodeMap = new util.HashMap[String, AnyRef] - dialcodeMap.put("count", dialcodeCount) - dialcodeMap.put("publisher", publisher) - dialcodeMap.put("batchCode", contentId) + dialcodeMap.put(DIALConstants.COUNT, dialcodeCount) + dialcodeMap.put(DIALConstants.PUBLISHER, publisher) + dialcodeMap.put(DIALConstants.BATCH_CODE, contentId) val request = new util.HashMap[String, AnyRef] - request.put("dialcodes", dialcodeMap) + request.put(DIALConstants.DIALCODES, dialcodeMap) val requestMap = new util.HashMap[String, AnyRef] - requestMap.put("request", request) + requestMap.put(DIALConstants.REQUEST, request) val headerParam = new util.HashMap[String, String]{put(DIALConstants.X_CHANNEL_ID, channelId); put(DIALConstants.AUTHORIZATION, DIAL_API_AUTH_KEY);} val generateResponse = oec.httpUtil.post(DIALCODE_GENERATE_URI, requestMap, headerParam) if (generateResponse.getResponseCode == ResponseCode.OK || generateResponse.getResponseCode == ResponseCode.PARTIAL_SUCCESS) { - val generatedDialCodes = generateResponse.getResult.get("dialcodes").asInstanceOf[util.ArrayList[String]].asScala.toList + val generatedDialCodes = generateResponse.getResult.get(DIALConstants.DIALCODES).asInstanceOf[util.ArrayList[String]].asScala.toList if (generatedDialCodes.nonEmpty) generatedDialCodes else throw new ServerException(ErrorCodes.ERR_SYSTEM_EXCEPTION.name, DIALErrors.ERR_DIAL_GEN_LIST_EMPTY_MSG) } @@ -370,4 +369,29 @@ object DIALManager { throw new ServerException(ErrorCodes.ERR_SYSTEM_EXCEPTION.name, DIALErrors.ERR_DIAL_GENERATION_MSG) } } + + def getDIALReserveUpdateRequest(req: Request, request: Request, rootNode: Node, updateDialCodes: Map[String, Integer]): Request = { + val updateReq = new Request(req) + updateReq.setContext(request.getContext) + updateReq.getContext.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) + updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) + val rootNodeMetadata = rootNode.getMetadata + rootNodeMetadata.remove(DIALConstants.DISCUSSION_FORUM) + rootNodeMetadata.remove(DIALConstants.CREDENTIALS) + rootNodeMetadata.remove(DIALConstants.TRACKABLE) + + updateReq.put(DIALConstants.RESERVED_DIALCODES, updateDialCodes) + updateReq.getRequest.putAll(rootNodeMetadata) + + updateReq + } + + def getDIALReserveUpdateResponse(response: Response, count: Integer, contentId: String, node: Node): Response = { + response.getResult.put(DIALConstants.COUNT, count) + response.getResult.put(ContentConstants.NODE_ID, contentId) + response.getResult.put(DIALConstants.PROCESS_ID, node.getMetadata.get(DIALConstants.PROCESS_ID)) + response.getResult.put(DIALConstants.RESERVED_DIALCODES, node.getMetadata.get(DIALConstants.RESERVED_DIALCODES)) + + response + } } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala index 29889d0eb..c0640131e 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala @@ -56,4 +56,7 @@ object ContentConstants { val LAST_UPDATED_ON:String = "lastUpdatedOn" val VERSION:String = "version" val COPY_SCHEME:String = "copyScheme" + val PARENT: String = "Parent" + val BEARER: String = "Bearer" + val OK_RESPONSE_CODE: String = "OK" } From 32a30bf03194dff2d6835a2d5ae46a1ffd3d2db0 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 15 Jul 2022 20:40:36 +0530 Subject: [PATCH 049/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../sunbird/content/dial/DIALManager.scala | 20 ++++++++++--------- .../content/util/ContentConstants.scala | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 81087b514..2974228ce 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -347,14 +347,16 @@ object DIALManager { @throws[Exception] private def generateDialCodes(channelId: String, contentId: String, dialcodeCount: Integer, publisher: String)(implicit oec: OntologyEngineContext): List[String] = { - val dialcodeMap = new util.HashMap[String, AnyRef] - dialcodeMap.put(DIALConstants.COUNT, dialcodeCount) - dialcodeMap.put(DIALConstants.PUBLISHER, publisher) - dialcodeMap.put(DIALConstants.BATCH_CODE, contentId) - val request = new util.HashMap[String, AnyRef] - request.put(DIALConstants.DIALCODES, dialcodeMap) - val requestMap = new util.HashMap[String, AnyRef] - requestMap.put(DIALConstants.REQUEST, request) + val requestMap = new util.HashMap[String, AnyRef]() {{ + put(DIALConstants.REQUEST, new util.HashMap[String, AnyRef]() {{ + put(DIALConstants.DIALCODES, new util.HashMap[String, AnyRef]() {{ + put(DIALConstants.COUNT, dialcodeCount) + put(DIALConstants.PUBLISHER, publisher) + put(DIALConstants.BATCH_CODE, contentId) + }}) + }}) + }} + val headerParam = new util.HashMap[String, String]{put(DIALConstants.X_CHANNEL_ID, channelId); put(DIALConstants.AUTHORIZATION, DIAL_API_AUTH_KEY);} val generateResponse = oec.httpUtil.post(DIALCODE_GENERATE_URI, requestMap, headerParam) if (generateResponse.getResponseCode == ResponseCode.OK || generateResponse.getResponseCode == ResponseCode.PARTIAL_SUCCESS) { @@ -380,7 +382,7 @@ object DIALManager { rootNodeMetadata.remove(DIALConstants.CREDENTIALS) rootNodeMetadata.remove(DIALConstants.TRACKABLE) - updateReq.put(DIALConstants.RESERVED_DIALCODES, updateDialCodes) + updateReq.put(DIALConstants.RESERVED_DIALCODES, updateDialCodes.asJava) updateReq.getRequest.putAll(rootNodeMetadata) updateReq diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala index c0640131e..622011222 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala @@ -57,6 +57,6 @@ object ContentConstants { val VERSION:String = "version" val COPY_SCHEME:String = "copyScheme" val PARENT: String = "Parent" - val BEARER: String = "Bearer" + val BEARER: String = "Bearer " val OK_RESPONSE_CODE: String = "OK" } From 242664c35da3786d83f2505f4a76a6c9b7b4ce06 Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Mon, 18 Jul 2022 15:33:48 +0530 Subject: [PATCH 050/105] Issue #SB-30119 test: Added the postman tests for content v2 create, read and update API. --- ...ontent V2 API Test.postman_collection.json | 1395 ++++++++++++----- .../Content V2.postman_collection.json | 1066 ++++++------- 2 files changed, 1539 insertions(+), 922 deletions(-) diff --git a/content-api/api-test/Content V2 API Test.postman_collection.json b/content-api/api-test/Content V2 API Test.postman_collection.json index 64dc2f6cf..7093dbae2 100644 --- a/content-api/api-test/Content V2 API Test.postman_collection.json +++ b/content-api/api-test/Content V2 API Test.postman_collection.json @@ -14,44 +14,93 @@ "name": "Content Create ", "item": [ { - "name": "Content Create", + "name": "Content Create - with minimal required attribute", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", + "let jsonResponse = pm.response.json();", "", - "//Verification", - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200)", - "});", - "pm.test(\"Content-Type header is present\", () => {", - " pm.response.to.have.header(\"Content-Type\");", - "});", - "pm.test(\"Content-Type header is application/json\", () => {", - " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", + " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", "});", - "pm.test(\"Content-Encoding header is present\", () => {", - " pm.response.to.have.header(\"Content-Encoding\");", + "", + "//Validation", + "pm.test(\"id should be api.content.create\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", "});", - "pm.test(\"Content-Encoding header is gzip\", () => {", - " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "pm.test(\"ver should be 4.0\", function () {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", "});", "", - "pm.test(\"Test data type of the response and keys\", () => {", - " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", - " pm.expect(jsonResponse.id).to.be.a(\"string\");", - " pm.expect(jsonResponse.ver).to.be.a(\"string\");", - " pm.expect(jsonResponse.ts).to.be.a(\"string\");", - " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", - " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.null;", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.null;", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", + "// Set global variable", + "pm.globals.set(\"content_id\", jsonResponse.result.identifier);", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "Content Create - Special character in name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", @@ -65,12 +114,6 @@ "pm.test(\"ver should be 4.0\", function () {", " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", "});", - "pm.test(\"params.status should be successful\", function () {", - " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", - "});", - "pm.test(\"responseCode should be OK\", function () {", - " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", - "});", "", "// Set global variable", "pm.globals.set(\"content_id\", jsonResponse.result.identifier);", @@ -109,7 +152,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"~`S!@#$%^&*()_+=:;\\\"'<,>.?/\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { "raw": "{{host}}/content/v2/create", @@ -138,42 +181,10 @@ "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 200\", () => {", - " pm.response.to.have.status(200)", - "});", - "", - "//code name contains a string", - "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", - "", - "pm.test(\"Content-Type header is present\", () => {", - " pm.response.to.have.header(\"Content-Type\");", - "});", - "pm.test(\"Content-Type header is application/json\", () => {", - " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", - "});", - "pm.test(\"Content-Encoding header is present\", () => {", - " pm.response.to.have.header(\"Content-Encoding\");", - "});", - "pm.test(\"Content-Encoding header is gzip\", () => {", - " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", - "});", + "let jsonResponse = pm.response.json();", "", - "pm.test(\"Test data type of the response and keys\", () => {", - " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", - " pm.expect(jsonResponse.id).to.be.a(\"string\");", - " pm.expect(jsonResponse.ver).to.be.a(\"string\");", - " pm.expect(jsonResponse.ts).to.be.a(\"string\");", - " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", - " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.null;", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.null;", - " pm.expect(jsonResponse.result).to.be.an(\"object\").that.has.all.keys('content');", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.have.all.keys('content');", " pm.expect(jsonResponse.result.content).to.be.an(\"object\")", " pm.expect(jsonResponse.result.content).to.have.any.keys('identifier', 'versionKey', 'code', 'channel', 'mimeType', 'createdOn', 'primaryCategory', 'contentDisposition', 'contentEncoding', 'objectType', 'visibility', 'discussionForum', 'license', 'version', 'compatibilityLevel', 'name', 'status');", " pm.expect(jsonResponse.result.content.identifier).to.be.a(\"string\");", @@ -182,23 +193,17 @@ " pm.expect(jsonResponse.result.content.channel).to.be.a(\"string\");", " pm.expect(jsonResponse.result.content.compatibilityLevel).to.be.a(\"number\");", " pm.expect(jsonResponse.result.content.ownershipType).to.be.an(\"array\");", - " pm.expect(jsonResponse.result.content.trackable).to.be.an(\"object\");", "});", "", "//Validation", - "pm.test(\"id should be api.content.read\", function () {", + "pm.test(\"id should be api.content.read\", () => {", " pm.expect(jsonResponse.id).to.eql(\"api.content.read\");", "});", "pm.test(\"ver should be 4.0\", () => {", " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", "});", - "pm.test(\"params.status should be successful\", () => {", - " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", - "});", - "pm.test(\"responseCode should be OK\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", - "});", - "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), () => {", + "", + "pm.test(`identifier should be equal to ${pm.globals.get(\"content_id\")}`, () => {", " pm.expect(jsonResponse.result.content.identifier).to.eql(pm.globals.get(\"content_id\"));", "});", "pm.test(\"objectType should be Content\", () => {", @@ -217,6 +222,15 @@ ], "type": "text/javascript" } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "// pm.globals.set('content_id', '');" + ], + "type": "text/javascript" + } } ], "request": { @@ -256,42 +270,10 @@ "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 200\", () => {", - " pm.response.to.have.status(200)", - "});", - "", - "//code name contains a string", - "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", - "", - "pm.test(\"Content-Type header is present\", () => {", - " pm.response.to.have.header(\"Content-Type\");", - "});", - "pm.test(\"Content-Type header is application/json\", () => {", - " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", - "});", - "pm.test(\"Content-Encoding header is present\", () => {", - " pm.response.to.have.header(\"Content-Encoding\");", - "});", - "pm.test(\"Content-Encoding header is gzip\", () => {", - " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", - "});", + "let jsonResponse = pm.response.json();", "", - "pm.test(\"Test data type of the response and keys\", () => {", - " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", - " pm.expect(jsonResponse.id).to.be.a(\"string\");", - " pm.expect(jsonResponse.ver).to.be.a(\"string\");", - " pm.expect(jsonResponse.ts).to.be.a(\"string\");", - " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", - " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.null;", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.null;", - " pm.expect(jsonResponse.result).to.be.an(\"object\").that.has.all.keys('content');", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.have.all.keys('content');", " pm.expect(jsonResponse.result.content).to.be.an(\"object\")", " pm.expect(jsonResponse.result.content).to.have.all.keys('identifier', 'primaryCategory', 'name', 'languageCode');", " pm.expect(jsonResponse.result.content.identifier).to.be.a(\"string\");", @@ -300,7 +282,6 @@ " pm.expect(jsonResponse.result.content.channel).to.be.undefined;", " pm.expect(jsonResponse.result.content.compatibilityLevel).to.be.undefined;", " pm.expect(jsonResponse.result.content.languageCode).to.be.an(\"array\");", - " pm.expect(jsonResponse.result.content.trackable).to.be.undefined;", "});", "", "//Validation", @@ -310,19 +291,23 @@ "pm.test(\"ver should be 4.0\", () => {", " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", "});", - "pm.test(\"params.status should be successful\", () => {", - " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", - "});", - "pm.test(\"responseCode should be OK\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", - "});", - "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), () => {", + "", + "pm.test(`identifier should be equal to ${pm.globals.get(\"content_id\")}`, () => {", " pm.expect(jsonResponse.result.content.identifier).to.eql(pm.globals.get(\"content_id\"));", "});", "" ], "type": "text/javascript" } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "// pm.globals.set('content_id', '');" + ], + "type": "text/javascript" + } } ], "request": { @@ -393,38 +378,9 @@ "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200)", - "});", - "pm.test(\"Content-Type header is present\", () => {", - " pm.response.to.have.header(\"Content-Type\");", - "});", - "pm.test(\"Content-Type header is application/json\", () => {", - " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", - "});", - "pm.test(\"Content-Encoding header is present\", () => {", - " pm.response.to.have.header(\"Content-Encoding\");", - "});", - "pm.test(\"Content-Encoding header is gzip\", () => {", - " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", - "});", + "let jsonResponse = pm.response.json();", "", - "pm.test(\"Test data type of the response and keys\", () => {", - " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", - " pm.expect(jsonResponse.id).to.be.a(\"string\");", - " pm.expect(jsonResponse.ver).to.be.a(\"string\");", - " pm.expect(jsonResponse.ts).to.be.a(\"string\");", - " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", - " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.null;", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.null;", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", + "pm.test(\"Verify keys and data type of the response result\", () => {", " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", @@ -432,22 +388,17 @@ "});", "", "//Validation", - "pm.test(\"id should be api.content.update\", function () {", + "pm.test(\"id should be api.content.update\", () => {", " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", "});", - "pm.test(\"ver should be 4.0\", function () {", + "pm.test(\"ver should be 4.0\", () => {", " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", "});", - "pm.test(\"params.status should be successful\", function () {", - " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", - "});", - "pm.test(\"responseCode should be OK\", function () {", - " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", - "});", - "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), function () {", + "", + "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), () => {", " pm.expect(jsonResponse.result.identifier).to.eql(pm.globals.get(\"content_id\"));", "});", - "pm.test(\"node_id should be equal to \" + pm.globals.get(\"content_id\"), function () {", + "pm.test(\"node_id should be equal to \" + pm.globals.get(\"content_id\"), () => {", " pm.expect(jsonResponse.result.node_id).to.eql(pm.globals.get(\"content_id\"));", "});", "", @@ -457,6 +408,15 @@ ], "type": "text/javascript" } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "// pm.globals.set('content_id');" + ], + "type": "text/javascript" + } } ], "request": { @@ -485,7 +445,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" }, "url": { "raw": "{{host}}/content/v2/update/{{content_id}}", @@ -502,39 +462,9 @@ "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." }, "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } }, { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - } - ] - }, - { - "name": "Negative", - "item": [ - { - "name": "Content Create", - "item": [ - { - "name": "Content Create - 404 - Invalid primaryCategory", + "name": "Content Update - Special character in name", "event": [ { "listen": "test", @@ -562,7 +492,7 @@ " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", "});", "", - "pm.test(\"Test data type of the response and keys\", () => {", + "pm.test(\"Verify keys and data type of the response result\", () => {", " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", " pm.expect(jsonResponse.id).to.be.a(\"string\");", " pm.expect(jsonResponse.ver).to.be.a(\"string\");", @@ -580,8 +510,9 @@ "});", "", "//Validation", - "pm.test(\"id should be api.content.create\", () => {", - " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", + "// Response body", + "pm.test(\"id should be api.content.update\", () => {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", "});", "pm.test(\"ver should be 4.0\", () => {", " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", @@ -592,8 +523,8 @@ "pm.test(\"params.status should be \\\"failed\\\"\", () => {", " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", "});", - "pm.test(\"params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:aaaa_content_all {}\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Entry is not found in cassandra for content with identifier: obj-cat:aaaa_content_all {}\");", + "pm.test(\"params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\");", "});", "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", @@ -607,10 +538,636 @@ } } ], - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true - } + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"~`S!@#$%^&*()_+=:;\\\"'<,>.?/\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "update", + "{{content_id}}" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "//Verification", + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200)", + "});", + "//code name contains a string", + "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", + "", + "// pm.test(\"Content-Encoding header is present\", () => {", + "// pm.response.to.have.header(\"Content-Encoding\");", + "// });", + "// pm.test(\"Content-Encoding header is gzip\", () => {", + "// pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "// });", + "", + "pm.test(\"Verify keys and data type of the params in positive scenario\", () => {", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + "});", + "", + "pm.test(\"params.status should be \\\"successful\\\"\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});" + ] + } + } + ] + }, + { + "name": "Negative", + "item": [ + { + "name": "Content Create", + "item": [ + { + "name": "Content Create - 404 - missing name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "Content Create - 404 - name empty", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "Content Create - 404 - missing code", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata code not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata code not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "Content Create - 404 - missing mimeType", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata mimeType not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata mimeType not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "Content Create - 404 - missing primaryCategory", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"VALIDATION_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"VALIDATION_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"primaryCategory is a mandatory parameter\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"primaryCategory is a mandatory parameter\");", + "});", + "", + "// Result", + "pm.test(\"result body should be empty\", () => {", + " pm.expect(jsonResponse.result).to.eql({});", + " pm.expect(jsonResponse.result).to.be.empty;", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "Content Create - 404 - Invalid primaryCategory", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 404\", () => {", + " pm.response.to.have.status(404)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.be.null;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"404\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"404\");", + "});", + "pm.test(`params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}\\\"`, () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(`Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}`);", + "});", + "", + "// Result", + "pm.test(\"messages should be null\", () => {", + " pm.expect(jsonResponse.result.messages).to.eql(null);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } }, "request": { "method": "POST", @@ -635,7 +1192,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"aaaa\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"aabaa\"\n }\n }\n}" }, "url": { "raw": "{{host}}/content/v2/create", @@ -652,6 +1209,33 @@ }, "response": [] } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "pm.test(\"id should be api.content.create\", () => {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});" + ] + } + } ] }, { @@ -673,55 +1257,36 @@ "//code name contains a string", "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", "", - "pm.test(\"Content-Type header is present\", () => {", - " pm.response.to.have.header(\"Content-Type\");", - "});", - "pm.test(\"Content-Type header is application/json\", () => {", - " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", - "});", - "pm.test(\"Content-Encoding header should not present\", () => {", - " pm.response.to.have.header(\"Content-Encoding\");", - "});", - "pm.test(\"Content-Encoding header is gzip\", () => {", - " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", - "});", - "", "pm.test(\"Test data type of the response and keys\", () => {", - " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", - " pm.expect(jsonResponse.id).to.be.a(\"string\");", - " pm.expect(jsonResponse.ver).to.be.a(\"string\");", - " pm.expect(jsonResponse.ts).to.be.a(\"string\");", - " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", - " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.a(\"string\");", " pm.expect(jsonResponse.result).to.be.an(\"object\");", " pm.expect(jsonResponse.result).to.have.all.keys('messages');", " pm.expect(jsonResponse.result.messages).to.be.null;", "});", "", "//Validation", + "// Response body", "pm.test(\"id should be api.content.read\", () => {", " pm.expect(jsonResponse.id).to.eql(\"api.content.read\");", "});", "pm.test(\"ver should be 4.0\", () => {", " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", "});", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "});", + "", + "// Params", "pm.test(\"params.err should be \\\"NOT_FOUND\\\"\", () => {", " pm.expect(jsonResponse.params.err).to.eql(\"NOT_FOUND\");", "});", "pm.test(\"params.status should be \\\"failed\\\"\", () => {", " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", "});", - "pm.test(\"params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_42353245436534\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_42353245436534\");", - "});", - "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "pm.test(`params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get('invalid_content_id')}\\\"`, () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(`Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get('invalid_content_id')}`);", "});", + "", + "// Result", "pm.test(\"messages should be null\", () => {", " pm.expect(jsonResponse.result.messages).to.eql(null);", "});", @@ -729,6 +1294,15 @@ ], "type": "text/javascript" } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.globals.set('invalid_content_id', 'do_42353245436534');" + ], + "type": "text/javascript" + } } ], "request": { @@ -746,7 +1320,7 @@ } ], "url": { - "raw": "{{host}}/content/v2/read/do_42353245436534", + "raw": "{{host}}/content/v2/read/{{invalid_content_id}}", "host": [ "{{host}}" ], @@ -754,7 +1328,7 @@ "content", "v2", "read", - "do_42353245436534" + "{{invalid_content_id}}" ] }, "description": "Fetch a particular Batch\nThis API is associated with fetching a particular batch on the Sunbird Platform.\nThe endpoint for Fetch a particular Batch is /batch/read/{Batch_ID}\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." @@ -796,65 +1370,57 @@ "let jsonResponse = pm.response.json()", "", "//Verification", - "pm.test(\"Status code is 400\", function () {", + "pm.test(\"Status code is 400\", () => {", " pm.response.to.have.status(400)", "});", "//code name contains a string", "tests[\"Status code name has string Bad Request\"] = responseCode.name.has(\"Bad Request\");", "", - "pm.test(\"Content-Type header is present\", () => {", - " pm.response.to.have.header(\"Content-Type\");", - "});", - "pm.test(\"Content-Type header is application/json\", () => {", - " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", - "});", "pm.test(\"Content-Encoding header should not present\", () => {", " pm.response.to.not.have.header(\"Content-Encoding\");", "});", "", - "pm.test(\"Test data type of the response and keys\", () => {", - " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", - " pm.expect(jsonResponse.id).to.be.a(\"string\");", - " pm.expect(jsonResponse.ver).to.be.a(\"string\");", - " pm.expect(jsonResponse.ts).to.be.a(\"string\");", - " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", - " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.a(\"string\");", + "pm.test(\"Verify keys and data type of the response result\", () => {", " pm.expect(jsonResponse.result).to.be.an(\"object\");", " pm.expect(jsonResponse.result).to.have.all.keys('messages');", " pm.expect(jsonResponse.result.messages).to.be.null;", "});", "", "//Validation", - "pm.test(\"id should be api.content.update\", function () {", - " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", - "});", - "pm.test(\"ver should be 4.0\", function () {", - " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "// Response body", + "pm.test(\"responseCode should be CLIENT_ERROR\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", "});", - "pm.test(\"params.err should be CLIENT_ERROR\", function () {", + "", + "// Params", + "pm.test(\"params.err should be CLIENT_ERROR\", () => {", " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", "});", - "pm.test(\"params.status should be failed\", function () {", + "pm.test(\"params.status should be failed\", () => {", " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", "});", - "pm.test(\"params.errmsg should be \\\"Invalid version Key\\\"\", function () {", + "pm.test(\"params.errmsg should be \\\"Invalid version Key\\\"\", () => {", " pm.expect(jsonResponse.params.errmsg).to.eql(\"Invalid version Key\");", "});", - "pm.test(\"responseCode should be CLIENT_ERROR\", function () {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", - "});", - "pm.test(\"messages should be null\", function () {", + "", + "// Result", + "pm.test(\"messages should be null\", () => {", " pm.expect(jsonResponse.result.messages).to.eql(null);", "});", "" ], "type": "text/javascript" } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.globals.set('versionKey', '3534534543');", + "// pm.globals.set(\"content_id\", '');" + ], + "type": "text/javascript" + } } ], "request": { @@ -883,10 +1449,10 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"3423423\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/update/do_213579099726987264122", + "raw": "{{host}}/content/v2/update/{{content_id}}", "host": [ "{{host}}" ], @@ -894,7 +1460,7 @@ "content", "v2", "update", - "do_213579099726987264122" + "{{content_id}}" ] }, "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." @@ -911,68 +1477,49 @@ "let jsonResponse = pm.response.json()", "", "//Verification", - "pm.test(\"Status code is 404\", function () {", + "pm.test(\"Status code is 404\", () => {", " pm.response.to.have.status(404)", "});", "//code name contains a string", "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", "", - "pm.test(\"Content-Type header is present\", () => {", - " pm.response.to.have.header(\"Content-Type\");", - "});", - "pm.test(\"Content-Type header is application/json\", () => {", - " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", - "});", - "pm.test(\"Content-Encoding header should not present\", () => {", - " pm.response.to.have.header(\"Content-Encoding\");", - "});", - "pm.test(\"Content-Encoding header is gzip\", () => {", - " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", - "});", - "", - "pm.test(\"Test data type of the response and keys\", () => {", - " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", - " pm.expect(jsonResponse.id).to.be.a(\"string\");", - " pm.expect(jsonResponse.ver).to.be.a(\"string\");", - " pm.expect(jsonResponse.ts).to.be.a(\"string\");", - " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", - " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.a(\"string\");", + "pm.test(\"Verify keys and data type of the response result\", () => {", " pm.expect(jsonResponse.result).to.be.an(\"object\");", " pm.expect(jsonResponse.result).to.have.all.keys('messages');", " pm.expect(jsonResponse.result.messages).to.be.null;", "});", "", "//Validation", - "pm.test(\"id should be api.content.update\", function () {", - " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", - "});", - "pm.test(\"ver should be 4.0\", function () {", - " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "// Response body", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", "});", - "pm.test(\"params.err should be NOT_FOUND\", function () {", + "", + "// Params", + "pm.test(\"params.err should be NOT_FOUND\", () => {", " pm.expect(jsonResponse.params.err).to.eql(\"NOT_FOUND\");", "});", - "pm.test(\"params.status should be failed\", function () {", - " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", - "});", - "pm.test(\"params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_21357909972698726412211\\\"\", function () {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_21357909972698726412211\");", - "});", - "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", function () {", - " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "pm.test(`params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"content_id\")}\\\"`, () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(`Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"content_id\")}`);", "});", - "pm.test(\"messages should be null\", function () {", + "", + "// Result", + "pm.test(\"messages should be null\", () => {", " pm.expect(jsonResponse.result.messages).to.eql(null);", "});", "" ], "type": "text/javascript" } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.globals.set(\"content_id\", 'do_21357909972698726412211');" + ], + "type": "text/javascript" + } } ], "request": { @@ -1004,7 +1551,7 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/update/do_21357909972698726412211", + "raw": "{{host}}/content/v2/update/{{content_id}}", "host": [ "{{host}}" ], @@ -1012,7 +1559,7 @@ "content", "v2", "update", - "do_21357909972698726412211" + "{{content_id}}" ] }, "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." @@ -1029,61 +1576,35 @@ "let jsonResponse = pm.response.json()", "", "//Verification", - "pm.test(\"Status code is 404\", function () {", + "pm.test(\"Status code is 404\", () => {", " pm.response.to.have.status(404)", "});", "//code name contains a string", "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", "", - "pm.test(\"Content-Type header is present\", () => {", - " pm.response.to.have.header(\"Content-Type\");", - "});", - "pm.test(\"Content-Type header is application/json\", () => {", - " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", - "});", - "pm.test(\"Content-Encoding header should not present\", () => {", - " pm.response.to.have.header(\"Content-Encoding\");", - "});", - "pm.test(\"Content-Encoding header is gzip\", () => {", - " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", - "});", - "", - "pm.test(\"Test data type of the response and keys\", () => {", - " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", - " pm.expect(jsonResponse.id).to.be.a(\"string\");", - " pm.expect(jsonResponse.ver).to.be.a(\"string\");", - " pm.expect(jsonResponse.ts).to.be.a(\"string\");", - " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", - " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.a(\"string\");", + "pm.test(\"Verify keys and data type of the response result\", () => {", " pm.expect(jsonResponse.result).to.be.an(\"object\");", " pm.expect(jsonResponse.result).to.have.all.keys('messages');", " pm.expect(jsonResponse.result.messages).to.be.null;", "});", "", "//Validation", - "pm.test(\"id should be api.content.update\", () => {", - " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", - "});", - "pm.test(\"ver should be 4.0\", () => {", - " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "// Response body", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", "});", + "", + "// Params", "pm.test(\"params.err should be \\\"404\\\"\", () => {", " pm.expect(jsonResponse.params.err).to.eql(\"404\");", "});", "pm.test(\"params.status should be \\\"failed\\\"\", () => {", " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", "});", - "pm.test(\"params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\");", - "});", - "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "pm.test(`params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}\\\"`, () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(`Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}`);", "});", + "", "pm.test(\"messages should be null\", () => {", " pm.expect(jsonResponse.result.messages).to.eql(null);", "});", @@ -1136,6 +1657,97 @@ "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." }, "response": [] + }, + { + "name": "Content Update - 404 - Empty name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "update", + "{{content_id}}" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] } ], "event": [ @@ -1144,7 +1756,7 @@ "script": { "type": "text/javascript", "exec": [ - "" + "// pm.globals.set(\"content_id\", '');" ] } }, @@ -1153,13 +1765,94 @@ "script": { "type": "text/javascript", "exec": [ - "" + "let jsonResponse = pm.response.json();", + "", + "pm.test(\"id should be api.content.update\", () => {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});" ] } } ] } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "//Verification", + "// pm.test(\"Content-Encoding header should not present\", () => {", + "// pm.response.to.not.have.header(\"Content-Encoding\");", + "// });", + "", + "pm.test(\"Verify keys and data type of the params in negative scenario\", () => {", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.a(\"string\");", + "});", + "", + "pm.test(\"params.status should be \\\"failed\\\"\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "});", + "" + ] + } + } ] } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "", + "pm.test(\"Validate keys and data type of the response body\", () => {", + " let jsonResponse = pm.response.json();", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + "});" + ] + } + } ] } \ No newline at end of file diff --git a/content-api/api-test/Content V2.postman_collection.json b/content-api/api-test/Content V2.postman_collection.json index b11d5a029..d116d704d 100644 --- a/content-api/api-test/Content V2.postman_collection.json +++ b/content-api/api-test/Content V2.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "c1421998-1fcb-44c7-9db1-9421f27b0a98", + "_postman_id": "95bee03d-d782-47da-89f9-cc70bb0a267e", "name": "Content V2", "description": "The Content Management APIs allow you to create, manage and process content on the Sunbird platform. Content is the basic building block of the Knowledge Service. Some examples would be Videos, Audio, Pdfs, Html, ECML etc. The basic operations for this API include Create, Update, Read, Review, Publish.\n\nThe URL for Content Management API(s) is /content/v1.", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", @@ -8,105 +8,143 @@ }, "item": [ { - "name": "Content Create ", - "item": [ + "name": "Content Create", + "event": [ { - "name": "Content Create", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200)", - "});", - "pm.test(\"Content-Type header is present\", () => {", - " pm.response.to.have.header(\"Content-Type\");", - "});", - "pm.test(\"Content-Type header is application/json\", () => {", - " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", - "});", - "pm.test(\"Content-Encoding header is present\", () => {", - " pm.response.to.have.header(\"Content-Encoding\");", - "});", - "pm.test(\"Content-Encoding header is gzip\", () => {", - " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", - "});", - "", - "pm.test(\"Test data type of the response and keys\", () => {", - " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", - " pm.expect(jsonResponse.id).to.be.a(\"string\");", - " pm.expect(jsonResponse.ver).to.be.a(\"string\");", - " pm.expect(jsonResponse.ts).to.be.a(\"string\");", - " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", - " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.null;", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.null;", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", - " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", - " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", - " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", - "});", - "", - "//Validation", - "pm.test(\"id should be api.content.create\", function () {", - " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", - "});", - "pm.test(\"ver should be 4.0\", function () {", - " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", - "});", - "pm.test(\"params.status should be successful\", function () {", - " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", - "});", - "pm.test(\"responseCode should be OK\", function () {", - " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", - "});", - "", - "// Set global variable", - "pm.globals.set(\"content_id\", jsonResponse.result.identifier);", - "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", - "" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true - } + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", + " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.create\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", + "});", + "pm.test(\"ver should be 4.0\", function () {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.status should be successful\", function () {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", function () {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});", + "", + "// Set global variable", + "pm.globals.set(\"content_id\", jsonResponse.result.identifier);", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" }, - "request": { + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { "method": "POST", "header": [ + { + "key": "userId", + "value": "user", + "type": "text" + }, { "key": "Content-Type", - "value": "application/json" + "value": "application/json", + "type": "text" }, { "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" + "value": "{{keycloak_access_token}}", + "type": "text" }, { "key": "Authorization", - "value": "{{kong_api_key}}" + "value": "{{kong_api_key}}", + "type": "text" }, { - "key": "X-Channel-Id", - "value": "{{channel_id}}", + "key": "Cookie", + "value": "connect.sid=s%3AyRLPeHt6zZ93WjZ2BD_Cejc11xNN-isK.ANbL%2FZ1t88yXax%2BiXjGFVtgFUAKhoWdl%2FgXU4yBX9rU; 81f30cf708470b974874c8a96a6bcdb2=l99ob678op07nq0qs5i0dae0m3; AWSELB=83D53DFF08C363B9195F6717118E44E326DE55CB796FB96A69500BA54C477B7512D6342B64B0B494BBD6699FCFFFB308C0DC9247AA23DA73B4F62BA4C399A735F647C86F50", "type": "text" } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"mimeType\": \"application/pdf\",\n \"code\": \"api-docs\",\n \"primaryCategory\": \"Explanation Content\",\n \"createdBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\"\n }\n }\n}" }, "url": { "raw": "{{host}}/content/v2/create", @@ -118,234 +156,204 @@ "v2", "create" ] - }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, - "response": [ - { - "name": "Content Create - 200 OK", - "originalRequest": { - "method": "POST", - "header": [ - { - "key": "userId", - "value": "user", - "type": "text" - }, - { - "key": "Content-Type", - "value": "application/json", - "type": "text" - }, - { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}", - "type": "text" - }, - { - "key": "Authorization", - "value": "{{kong_api_key}}", - "type": "text" - }, - { - "key": "Cookie", - "value": "connect.sid=s%3AyRLPeHt6zZ93WjZ2BD_Cejc11xNN-isK.ANbL%2FZ1t88yXax%2BiXjGFVtgFUAKhoWdl%2FgXU4yBX9rU; 81f30cf708470b974874c8a96a6bcdb2=l99ob678op07nq0qs5i0dae0m3; AWSELB=83D53DFF08C363B9195F6717118E44E326DE55CB796FB96A69500BA54C477B7512D6342B64B0B494BBD6699FCFFFB308C0DC9247AA23DA73B4F62BA4C399A735F647C86F50", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"mimeType\": \"application/pdf\",\n \"code\": \"api-docs\",\n \"primaryCategory\": \"Explanation Content\",\n \"createdBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\"\n }\n }\n}" - }, - "url": { - "raw": "{{host}}/content/v2/create", - "host": [ - "{{host}}" - ], - "path": [ - "content", - "v2", - "create" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Date", - "value": "Mon, 23 Nov 2020 06:42:39 GMT" - }, - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Transfer-Encoding", - "value": "chunked" - }, - { - "key": "Connection", - "value": "keep-alive" - }, - { - "key": "Vary", - "value": "Accept-Encoding" - }, - { - "key": "X-RateLimit-Limit-hour", - "value": "30000" - }, - { - "key": "X-RateLimit-Remaining-hour", - "value": "29991" - }, - { - "key": "Referrer-Policy", - "value": "origin-when-cross-origin, strict-origin-when-cross-origin" - }, - { - "key": "X-Frame-Options", - "value": "DENY" - }, - { - "key": "X-XSS-Protection", - "value": "1; mode=block" - }, - { - "key": "x-response-length", - "value": "55" - }, - { - "key": "X-Content-Type-Options", - "value": "nosniff" - }, - { - "key": "Access-Control-Allow-Origin", - "value": "*" - }, - { - "key": "X-Permitted-Cross-Domain-Policies", - "value": "master-only" - }, - { - "key": "X-Kong-Upstream-Latency", - "value": "53" - }, - { - "key": "X-Kong-Proxy-Latency", - "value": "36" - }, - { - "key": "Via", - "value": "kong/0.14.1" - }, - { - "key": "Content-Encoding", - "value": "gzip" - } - ], - "cookie": [], - "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"1.0\",\n \"ts\": \"2020-12-09T11:11:12.697Z\",\n \"params\": {\n \"resmsgid\": \"3f5de290-3a0f-11eb-be5b-f9d249ba9049\",\n \"msgid\": \"3f57a100-3a0f-11eb-be5b-f9d249ba9049\",\n \"status\": \"successful\",\n \"err\": null,\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"content_id\": \"do_1131687405374504961738\",\n \"versionKey\": \"1607512272640\"\n }\n}" + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Mon, 23 Nov 2020 06:42:39 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "30000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "29991" + }, + { + "key": "Referrer-Policy", + "value": "origin-when-cross-origin, strict-origin-when-cross-origin" + }, + { + "key": "X-Frame-Options", + "value": "DENY" + }, + { + "key": "X-XSS-Protection", + "value": "1; mode=block" + }, + { + "key": "x-response-length", + "value": "55" + }, + { + "key": "X-Content-Type-Options", + "value": "nosniff" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Permitted-Cross-Domain-Policies", + "value": "master-only" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "53" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "36" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" } - ] + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"1.0\",\n \"ts\": \"2020-12-09T11:11:12.697Z\",\n \"params\": {\n \"resmsgid\": \"3f5de290-3a0f-11eb-be5b-f9d249ba9049\",\n \"msgid\": \"3f57a100-3a0f-11eb-be5b-f9d249ba9049\",\n \"status\": \"successful\",\n \"err\": null,\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"content_id\": \"do_1131687405374504961738\",\n \"versionKey\": \"1607512272640\"\n }\n}" } ] }, { "name": "Content Read", - "item": [ + "event": [ { - "name": "Content Read", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 200\", () => {", - " pm.response.to.have.status(200)", - "});", - "", - "//code name contains a string", - "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", - "", - "pm.test(\"Content-Type header is present\", () => {", - " pm.response.to.have.header(\"Content-Type\");", - "});", - "pm.test(\"Content-Type header is application/json\", () => {", - " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", - "});", - "pm.test(\"Content-Encoding header is present\", () => {", - " pm.response.to.have.header(\"Content-Encoding\");", - "});", - "pm.test(\"Content-Encoding header is gzip\", () => {", - " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", - "});", - "", - "pm.test(\"Test data type of the response and keys\", () => {", - " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", - " pm.expect(jsonResponse.id).to.be.a(\"string\");", - " pm.expect(jsonResponse.ver).to.be.a(\"string\");", - " pm.expect(jsonResponse.ts).to.be.a(\"string\");", - " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", - " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.null;", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.null;", - " pm.expect(jsonResponse.result).to.be.an(\"object\").that.has.all.keys('content');", - " pm.expect(jsonResponse.result.content).to.be.an(\"object\")", - " pm.expect(jsonResponse.result.content).to.have.any.keys('identifier', 'versionKey', 'code', 'channel', 'mimeType', 'createdOn', 'primaryCategory', 'contentDisposition', 'contentEncoding', 'objectType', 'visibility', 'discussionForum', 'license', 'version', 'compatibilityLevel', 'name', 'status');", - " pm.expect(jsonResponse.result.content.identifier).to.be.a(\"string\");", - " pm.expect(jsonResponse.result.content.versionKey).to.be.a(\"string\");", - " pm.expect(jsonResponse.result.content.version).to.be.a(\"number\");", - " pm.expect(jsonResponse.result.content.channel).to.be.a(\"string\");", - " pm.expect(jsonResponse.result.content.compatibilityLevel).to.be.a(\"number\");", - " pm.expect(jsonResponse.result.content.ownershipType).to.be.an(\"array\");", - " pm.expect(jsonResponse.result.content.trackable).to.be.an(\"object\");", - "});", - "", - "//Validation", - "pm.test(\"id should be api.content.read\", function () {", - " pm.expect(jsonResponse.id).to.eql(\"api.content.read\");", - "});", - "pm.test(\"ver should be 4.0\", () => {", - " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", - "});", - "pm.test(\"params.status should be successful\", () => {", - " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", - "});", - "pm.test(\"responseCode should be OK\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", - "});", - "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), () => {", - " pm.expect(jsonResponse.result.content.identifier).to.eql(pm.globals.get(\"content_id\"));", - "});", - "pm.test(\"objectType should be Content\", () => {", - " pm.expect(jsonResponse.result.content.objectType).to.eql(\"Content\");", - "});", - "pm.test(\"visibility should be Default\", () => {", - " pm.expect(jsonResponse.result.content.visibility).to.eql(\"Default\");", - "});", - "pm.test(\"compatibilityLevel should be 1\", () => {", - " pm.expect(jsonResponse.result.content.compatibilityLevel).to.eql(1);", - "});", - "pm.test(\"status should be Draft\", () => {", - " pm.expect(jsonResponse.result.content.status).to.eql(\"Draft\");", - "});", - "", - "pm.globals.set(\"versionKey\", jsonResponse.result.content.versionKey);" - ], - "type": "text/javascript" - } - } + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200)", + "});", + "", + "//code name contains a string", + "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", + "", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + " pm.expect(jsonResponse.result).to.be.an(\"object\").that.has.all.keys('content');", + " pm.expect(jsonResponse.result.content).to.be.an(\"object\")", + " pm.expect(jsonResponse.result.content).to.have.any.keys('identifier', 'versionKey', 'code', 'channel', 'mimeType', 'createdOn', 'primaryCategory', 'contentDisposition', 'contentEncoding', 'objectType', 'visibility', 'discussionForum', 'license', 'version', 'compatibilityLevel', 'name', 'status');", + " pm.expect(jsonResponse.result.content.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.content.versionKey).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.content.version).to.be.a(\"number\");", + " pm.expect(jsonResponse.result.content.channel).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.content.compatibilityLevel).to.be.a(\"number\");", + " pm.expect(jsonResponse.result.content.ownershipType).to.be.an(\"array\");", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.read\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.read\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.status should be successful\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});", + "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), () => {", + " pm.expect(jsonResponse.result.content.identifier).to.eql(pm.globals.get(\"content_id\"));", + "});", + "pm.test(\"objectType should be Content\", () => {", + " pm.expect(jsonResponse.result.content.objectType).to.eql(\"Content\");", + "});", + "pm.test(\"visibility should be Default\", () => {", + " pm.expect(jsonResponse.result.content.visibility).to.eql(\"Default\");", + "});", + "pm.test(\"compatibilityLevel should be 1\", () => {", + " pm.expect(jsonResponse.result.content.compatibilityLevel).to.eql(1);", + "});", + "pm.test(\"status should be Draft\", () => {", + " pm.expect(jsonResponse.result.content.status).to.eql(\"Draft\");", + "});", + "", + "pm.globals.set(\"versionKey\", jsonResponse.result.content.versionKey);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + } + ], + "url": { + "raw": "{{host}}/content/v2/read/{{content_id}}", + "host": [ + "{{host}}" ], - "request": { + "path": [ + "content", + "v2", + "read", + "{{content_id}}" + ] + }, + "description": "Fetch a particular Batch\nThis API is associated with fetching a particular batch on the Sunbird Platform.\nThe endpoint for Fetch a particular Batch is /batch/read/{Batch_ID}\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [ + { + "name": "Content Read - 200 OK", + "originalRequest": { "method": "GET", "header": [ { @@ -370,292 +378,208 @@ "read", "{{content_id}}" ] - }, - "description": "Fetch a particular Batch\nThis API is associated with fetching a particular batch on the Sunbird Platform.\nThe endpoint for Fetch a particular Batch is /batch/read/{Batch_ID}\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, - "response": [ - { - "name": "Content Read - 200 OK", - "originalRequest": { - "method": "GET", - "header": [ - { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}", - "type": "text" - }, - { - "key": "Authorization", - "value": "{{kong_api_key}}", - "type": "text" - } - ], - "url": { - "raw": "{{host}}/content/v2/read/{{content_id}}", - "host": [ - "{{host}}" - ], - "path": [ - "content", - "v2", - "read", - "{{content_id}}" - ] - } - }, - "status": "OK", - "code": 200, - "_postman_previewlanguage": "json", - "header": [ - { - "key": "Date", - "value": "Mon, 23 Nov 2020 04:48:35 GMT" - }, - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "Transfer-Encoding", - "value": "chunked" - }, - { - "key": "Connection", - "value": "keep-alive" - }, - { - "key": "Vary", - "value": "Accept-Encoding" - }, - { - "key": "X-RateLimit-Limit-hour", - "value": "30000" - }, - { - "key": "X-RateLimit-Remaining-hour", - "value": "29999" - }, - { - "key": "Referrer-Policy", - "value": "origin-when-cross-origin, strict-origin-when-cross-origin" - }, - { - "key": "X-Frame-Options", - "value": "DENY" - }, - { - "key": "X-XSS-Protection", - "value": "1; mode=block" - }, - { - "key": "x-response-length", - "value": "2759" - }, - { - "key": "X-Content-Type-Options", - "value": "nosniff" - }, - { - "key": "Access-Control-Allow-Origin", - "value": "*" - }, - { - "key": "X-Permitted-Cross-Domain-Policies", - "value": "master-only" - }, - { - "key": "X-Kong-Upstream-Latency", - "value": "11" - }, - { - "key": "X-Kong-Proxy-Latency", - "value": "35" - }, - { - "key": "Via", - "value": "kong/0.14.1" - }, - { - "key": "X-Proxy-Cache", - "value": "MISS" - }, - { - "key": "X-Proxy-Cache-Date", - "value": "Mon, 23 Nov 2020 04:48:35 GMT" - }, - { - "key": "Content-Encoding", - "value": "gzip" - } - ], - "cookie": [], - "body": "{\n \"id\": \"api.content.read\",\n \"ver\": \"1.0\",\n \"ts\": \"2020-12-09T12:09:04.202Z\",\n \"params\": {\n \"resmsgid\": \"548b82a0-3a17-11eb-be5b-f9d249ba9049\",\n \"msgid\": \"5488ea90-3a17-11eb-be5b-f9d249ba9049\",\n \"status\": \"successful\",\n \"err\": null,\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"content\": {\n \"ownershipType\": [\n \"createdBy\"\n ],\n \"code\": \"org.sunbird.ccG6ru\",\n \"credentials\": {\n \"enabled\": \"No\"\n },\n \"channel\": \"in.ekstep\",\n \"language\": [\n \"English\"\n ],\n \"mimeType\": \"application/pdf\",\n \"idealScreenSize\": \"normal\",\n \"createdOn\": \"2020-12-09T12:08:54.913+0000\",\n \"objectType\": \"Content\",\n \"primaryCategory\": \"Explanation Content\",\n \"contentDisposition\": \"inline\",\n \"lastUpdatedOn\": \"2020-12-09T12:08:54.913+0000\",\n \"contentEncoding\": \"identity\",\n \"contentType\": \"Resource\",\n \"dialcodeRequired\": \"No\",\n \"identifier\": \"do_1131687689003827201864\",\n \"lastStatusChangedOn\": \"2020-12-09T12:08:54.913+0000\",\n \"audience\": [\n \"Student\"\n ],\n \"os\": [\n \"All\"\n ],\n \"visibility\": \"Default\",\n \"consumerId\": \"7411b6bd-89f3-40ec-98d1-229dc64ce77d\",\n \"mediaType\": \"content\",\n \"osId\": \"org.ekstep.quiz.app\",\n \"languageCode\": [\n \"en\"\n ],\n \"version\": 2,\n \"versionKey\": \"1607515734913\",\n \"license\": \"CC BY 4.0\",\n \"idealScreenDensity\": \"hdpi\",\n \"framework\": \"NCF\",\n \"createdBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"compatibilityLevel\": 1,\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"status\": \"Draft\"\n }\n }\n}" + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Mon, 23 Nov 2020 04:48:35 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "30000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "29999" + }, + { + "key": "Referrer-Policy", + "value": "origin-when-cross-origin, strict-origin-when-cross-origin" + }, + { + "key": "X-Frame-Options", + "value": "DENY" + }, + { + "key": "X-XSS-Protection", + "value": "1; mode=block" + }, + { + "key": "x-response-length", + "value": "2759" + }, + { + "key": "X-Content-Type-Options", + "value": "nosniff" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Permitted-Cross-Domain-Policies", + "value": "master-only" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "11" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "35" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "X-Proxy-Cache", + "value": "MISS" + }, + { + "key": "X-Proxy-Cache-Date", + "value": "Mon, 23 Nov 2020 04:48:35 GMT" + }, + { + "key": "Content-Encoding", + "value": "gzip" } - ] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.read\",\n \"ver\": \"1.0\",\n \"ts\": \"2020-12-09T12:09:04.202Z\",\n \"params\": {\n \"resmsgid\": \"548b82a0-3a17-11eb-be5b-f9d249ba9049\",\n \"msgid\": \"5488ea90-3a17-11eb-be5b-f9d249ba9049\",\n \"status\": \"successful\",\n \"err\": null,\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"content\": {\n \"ownershipType\": [\n \"createdBy\"\n ],\n \"code\": \"org.sunbird.ccG6ru\",\n \"credentials\": {\n \"enabled\": \"No\"\n },\n \"channel\": \"in.ekstep\",\n \"language\": [\n \"English\"\n ],\n \"mimeType\": \"application/pdf\",\n \"idealScreenSize\": \"normal\",\n \"createdOn\": \"2020-12-09T12:08:54.913+0000\",\n \"objectType\": \"Content\",\n \"primaryCategory\": \"Explanation Content\",\n \"contentDisposition\": \"inline\",\n \"lastUpdatedOn\": \"2020-12-09T12:08:54.913+0000\",\n \"contentEncoding\": \"identity\",\n \"contentType\": \"Resource\",\n \"dialcodeRequired\": \"No\",\n \"identifier\": \"do_1131687689003827201864\",\n \"lastStatusChangedOn\": \"2020-12-09T12:08:54.913+0000\",\n \"audience\": [\n \"Student\"\n ],\n \"os\": [\n \"All\"\n ],\n \"visibility\": \"Default\",\n \"consumerId\": \"7411b6bd-89f3-40ec-98d1-229dc64ce77d\",\n \"mediaType\": \"content\",\n \"osId\": \"org.ekstep.quiz.app\",\n \"languageCode\": [\n \"en\"\n ],\n \"version\": 2,\n \"versionKey\": \"1607515734913\",\n \"license\": \"CC BY 4.0\",\n \"idealScreenDensity\": \"hdpi\",\n \"framework\": \"NCF\",\n \"createdBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"compatibilityLevel\": 1,\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"status\": \"Draft\"\n }\n }\n}" } ] }, { "name": "Content Update", - "item": [ - { - "name": "Content Update", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 200\", function () {", - " pm.response.to.have.status(200)", - "});", - "pm.test(\"Content-Type header is present\", () => {", - " pm.response.to.have.header(\"Content-Type\");", - "});", - "pm.test(\"Content-Type header is application/json\", () => {", - " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", - "});", - "pm.test(\"Content-Encoding header is present\", () => {", - " pm.response.to.have.header(\"Content-Encoding\");", - "});", - "pm.test(\"Content-Encoding header is gzip\", () => {", - " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", - "});", - "", - "pm.test(\"Test data type of the response and keys\", () => {", - " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", - " pm.expect(jsonResponse.id).to.be.a(\"string\");", - " pm.expect(jsonResponse.ver).to.be.a(\"string\");", - " pm.expect(jsonResponse.ts).to.be.a(\"string\");", - " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", - " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.null;", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.null;", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", - " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", - " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", - " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", - "});", - "", - "//Validation", - "pm.test(\"id should be api.content.update\", function () {", - " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", - "});", - "pm.test(\"ver should be 4.0\", function () {", - " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", - "});", - "pm.test(\"params.status should be successful\", function () {", - " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", - "});", - "pm.test(\"responseCode should be OK\", function () {", - " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", - "});", - "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), function () {", - " pm.expect(jsonResponse.result.identifier).to.eql(pm.globals.get(\"content_id\"));", - "});", - "pm.test(\"node_id should be equal to \" + pm.globals.get(\"content_id\"), function () {", - " pm.expect(jsonResponse.result.node_id).to.eql(pm.globals.get(\"content_id\"));", - "});", - "", - "// Set global variable", - "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Content-Type", - "value": "application/json", - "type": "text" - }, - { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}", - "type": "text" - }, - { - "key": "Authorization", - "value": "{{kong_api_key}}", - "type": "text" - }, - { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" - }, - "url": { - "raw": "{{host}}/content/v2/update/{{content_id}}", - "host": [ - "{{host}}" - ], - "path": [ - "content", - "v2", - "update", - "{{content_id}}" - ] - }, - "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." - }, - "response": [] - } - ], "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, { "listen": "test", "script": { - "type": "text/javascript", "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", + " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.update\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", + "});", + "pm.test(\"ver should be 4.0\", function () {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"params.status should be successful\", function () {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", function () {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});", + "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), function () {", + " pm.expect(jsonResponse.result.identifier).to.eql(pm.globals.get(\"content_id\"));", + "});", + "pm.test(\"node_id should be equal to \" + pm.globals.get(\"content_id\"), function () {", + " pm.expect(jsonResponse.result.node_id).to.eql(pm.globals.get(\"content_id\"));", + "});", + "", + "// Set global variable", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", "" - ] + ], + "type": "text/javascript" } } - ] + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v2", + "update", + "{{content_id}}" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] } ] } \ No newline at end of file From e4644377426beba8ae4fdd3e18cd059359d0e8d8 Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Tue, 19 Jul 2022 09:23:35 +0530 Subject: [PATCH 051/105] Issue #SB-30119 test: Added the postman tests for content v2 create, read and update API. --- .../Content V2.postman_collection.json | 78 ++++++++++++------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/content-api/api-test/Content V2.postman_collection.json b/content-api/api-test/Content V2.postman_collection.json index d116d704d..c70084091 100644 --- a/content-api/api-test/Content V2.postman_collection.json +++ b/content-api/api-test/Content V2.postman_collection.json @@ -2,7 +2,7 @@ "info": { "_postman_id": "95bee03d-d782-47da-89f9-cc70bb0a267e", "name": "Content V2", - "description": "The Content Management APIs allow you to create, manage and process content on the Sunbird platform. Content is the basic building block of the Knowledge Service. Some examples would be Videos, Audio, Pdfs, Html, ECML etc. The basic operations for this API include Create, Update, Read, Review, Publish.\n\nThe URL for Content Management API(s) is /content/v1.", + "description": "The Content Management APIs allow you to create, manage and process content on the Sunbird platform. Content is the basic building block of the Knowledge Service. Some examples would be Videos, Audio, Pdfs, Html, ECML etc. The basic operations for this API include Create, Update, Read, Review, Publish.\n\n* Each of the endpoints serve a different purpose, so which one to use depends on what you want to do\n* The operations include CRUD (Create, Update, Read and Delete) operations and other operations such as upload, publish, flag, link DIAL code, etc.\n* The URL for Content Management API(s) is /content/v2.\n \n\nAPI tests", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", "_exporter_id": "1419050" }, @@ -77,25 +77,29 @@ "header": [ { "key": "Content-Type", - "value": "application/json" + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." }, { "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." }, { "key": "Authorization", - "value": "{{kong_api_key}}" + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." }, { "key": "X-Channel-Id", "value": "{{channel_id}}", - "type": "text" + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { "raw": "{{host}}/content/v2/create", @@ -108,7 +112,7 @@ "create" ] }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" }, "response": [ { @@ -116,11 +120,6 @@ "originalRequest": { "method": "POST", "header": [ - { - "key": "userId", - "value": "user", - "type": "text" - }, { "key": "Content-Type", "value": "application/json", @@ -137,8 +136,8 @@ "type": "text" }, { - "key": "Cookie", - "value": "connect.sid=s%3AyRLPeHt6zZ93WjZ2BD_Cejc11xNN-isK.ANbL%2FZ1t88yXax%2BiXjGFVtgFUAKhoWdl%2FgXU4yBX9rU; 81f30cf708470b974874c8a96a6bcdb2=l99ob678op07nq0qs5i0dae0m3; AWSELB=83D53DFF08C363B9195F6717118E44E326DE55CB796FB96A69500BA54C477B7512D6342B64B0B494BBD6699FCFFFB308C0DC9247AA23DA73B4F62BA4C399A735F647C86F50", + "key": "X-Channel-Id", + "value": "{{channel_id}}", "type": "text" } ], @@ -147,11 +146,16 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"mimeType\": \"application/pdf\",\n \"code\": \"api-docs\",\n \"primaryCategory\": \"Explanation Content\",\n \"createdBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/create", + "raw": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "protocol": "https", "host": [ - "{{host}}" + "dev", + "knowlg", + "sunbird", + "org" ], "path": [ + "api", "content", "v2", "create" @@ -325,15 +329,23 @@ "request": { "method": "GET", "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, { "key": "X-Authenticated-User-token", "value": "{{keycloak_access_token}}", - "type": "text" + "type": "text", + "description": "Represents the authorized User ID to execute the API." }, { "key": "Authorization", "value": "{{kong_api_key}}", - "type": "text" + "type": "text", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." } ], "url": { @@ -348,7 +360,7 @@ "{{content_id}}" ] }, - "description": "Fetch a particular Batch\nThis API is associated with fetching a particular batch on the Sunbird Platform.\nThe endpoint for Fetch a particular Batch is /batch/read/{Batch_ID}\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + "description": "This API is associated with viewing and reading out the content on the Sunbird Platform. You need to provide a valid content Id value in {{content_id}} field of API URL." }, "response": [ { @@ -356,6 +368,11 @@ "originalRequest": { "method": "GET", "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, { "key": "X-Authenticated-User-token", "value": "{{keycloak_access_token}}", @@ -368,11 +385,16 @@ } ], "url": { - "raw": "{{host}}/content/v2/read/{{content_id}}", + "raw": "https://dev.knowlg.sunbird.org/api/content/v2/read/{{content_id}}", + "protocol": "https", "host": [ - "{{host}}" + "dev", + "knowlg", + "sunbird", + "org" ], "path": [ + "api", "content", "v2", "read", @@ -543,22 +565,26 @@ { "key": "Content-Type", "value": "application/json", - "type": "text" + "type": "text", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." }, { "key": "X-Authenticated-User-token", "value": "{{keycloak_access_token}}", - "type": "text" + "type": "text", + "description": "Represents the authorized User ID to execute the API." }, { "key": "Authorization", "value": "{{kong_api_key}}", - "type": "text" + "type": "text", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." }, { "key": "X-Channel-Id", "value": "{{channel_id}}", - "type": "text" + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." } ], "body": { @@ -577,7 +603,7 @@ "{{content_id}}" ] }, - "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + "description": "This API is associated with updating content on the Sunbird Platform. Mandatory fields cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" }, "response": [] } From a0909944e720b7a8e127c3d0421edc811931f573 Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Tue, 19 Jul 2022 12:20:24 +0530 Subject: [PATCH 052/105] Issue #SB-30119 test: Added the postman tests for content v2 create, read and update API. --- ...ontent V2 API Test.postman_collection.json | 159 ++-- .../Content V2.postman_collection.json | 757 ++++++++++++++++-- 2 files changed, 775 insertions(+), 141 deletions(-) diff --git a/content-api/api-test/Content V2 API Test.postman_collection.json b/content-api/api-test/Content V2 API Test.postman_collection.json index 7093dbae2..77efae5c8 100644 --- a/content-api/api-test/Content V2 API Test.postman_collection.json +++ b/content-api/api-test/Content V2 API Test.postman_collection.json @@ -77,11 +77,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/create", + "raw": "{{host}}/api/content/v2/create", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "create" @@ -155,11 +156,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"~`S!@#$%^&*()_+=:;\\\"'<,>.?/\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/create", + "raw": "{{host}}/api/content/v2/create", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "create" @@ -248,11 +250,12 @@ } ], "url": { - "raw": "{{host}}/content/v2/read/{{content_id}}", + "raw": "{{host}}/api/content/v2/read/{{content_id}}", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "read", @@ -325,11 +328,12 @@ } ], "url": { - "raw": "{{host}}/content/v2/read/{{content_id}}?fields=name,primaryCategory", + "raw": "{{host}}/api/content/v2/read/{{content_id}}?fields=name,primaryCategory", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "read", @@ -448,11 +452,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/update/{{content_id}}", + "raw": "{{host}}/api/content/v2/update/{{content_id}}", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "update", @@ -567,11 +572,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"~`S!@#$%^&*()_+=:;\\\"'<,>.?/\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/update/{{content_id}}", + "raw": "{{host}}/api/content/v2/update/{{content_id}}", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "update", @@ -662,7 +668,7 @@ "name": "Content Create", "item": [ { - "name": "Content Create - 404 - missing name", + "name": "Content Create - 400 - missing name", "event": [ { "listen": "test", @@ -739,11 +745,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/create", + "raw": "{{host}}/api/content/v2/create", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "create" @@ -754,7 +761,7 @@ "response": [] }, { - "name": "Content Create - 404 - name empty", + "name": "Content Create - 400 - name empty", "event": [ { "listen": "test", @@ -831,11 +838,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/create", + "raw": "{{host}}/api/content/v2/create", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "create" @@ -846,7 +854,7 @@ "response": [] }, { - "name": "Content Create - 404 - missing code", + "name": "Content Create - 400 - missing code", "event": [ { "listen": "test", @@ -923,11 +931,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/create", + "raw": "{{host}}/api/content/v2/create", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "create" @@ -938,7 +947,7 @@ "response": [] }, { - "name": "Content Create - 404 - missing mimeType", + "name": "Content Create - 400 - missing mimeType", "event": [ { "listen": "test", @@ -1015,11 +1024,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/create", + "raw": "{{host}}/api/content/v2/create", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "create" @@ -1030,7 +1040,7 @@ "response": [] }, { - "name": "Content Create - 404 - missing primaryCategory", + "name": "Content Create - 400 - missing primaryCategory", "event": [ { "listen": "test", @@ -1105,11 +1115,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/create", + "raw": "{{host}}/api/content/v2/create", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "create" @@ -1195,11 +1206,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"aabaa\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/create", + "raw": "{{host}}/api/content/v2/create", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "create" @@ -1242,7 +1254,7 @@ "name": "Content Read", "item": [ { - "name": "Content Read", + "name": "Content Read - 404 - Not Found", "event": [ { "listen": "test", @@ -1320,11 +1332,12 @@ } ], "url": { - "raw": "{{host}}/content/v2/read/{{invalid_content_id}}", + "raw": "{{host}}/api/content/v2/read/{{invalid_content_id}}", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "read", @@ -1452,11 +1465,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/update/{{content_id}}", + "raw": "{{host}}/api/content/v2/update/{{content_id}}", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "update", @@ -1468,7 +1482,7 @@ "response": [] }, { - "name": "Content Update - 404 - Invalid content id", + "name": "Content Update - 400 - Empty name", "event": [ { "listen": "test", @@ -1477,49 +1491,41 @@ "let jsonResponse = pm.response.json()", "", "//Verification", - "pm.test(\"Status code is 404\", () => {", - " pm.response.to.have.status(404)", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", "});", "//code name contains a string", - "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", "", "pm.test(\"Verify keys and data type of the response result\", () => {", " pm.expect(jsonResponse.result).to.be.an(\"object\");", " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.be.null;", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", "});", "", "//Validation", "// Response body", - "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", "});", "", "// Params", - "pm.test(\"params.err should be NOT_FOUND\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"NOT_FOUND\");", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", "});", - "pm.test(`params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"content_id\")}\\\"`, () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(`Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"content_id\")}`);", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", "});", "", "// Result", - "pm.test(\"messages should be null\", () => {", - " pm.expect(jsonResponse.result.messages).to.eql(null);", + "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", "});", "" ], "type": "text/javascript" } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "pm.globals.set(\"content_id\", 'do_21357909972698726412211');" - ], - "type": "text/javascript" - } } ], "request": { @@ -1548,14 +1554,15 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/update/{{content_id}}", + "raw": "{{host}}/api/content/v2/update/{{content_id}}", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "update", @@ -1567,7 +1574,7 @@ "response": [] }, { - "name": "Content Update - 404 - Invalid primaryCategory", + "name": "Content Update - 404 - Invalid content id", "event": [ { "listen": "test", @@ -1595,16 +1602,14 @@ "});", "", "// Params", - "pm.test(\"params.err should be \\\"404\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"404\");", - "});", - "pm.test(\"params.status should be \\\"failed\\\"\", () => {", - " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "pm.test(\"params.err should be NOT_FOUND\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"NOT_FOUND\");", "});", - "pm.test(`params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}\\\"`, () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(`Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}`);", + "pm.test(`params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"content_id\")}\\\"`, () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(`Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"content_id\")}`);", "});", "", + "// Result", "pm.test(\"messages should be null\", () => {", " pm.expect(jsonResponse.result.messages).to.eql(null);", "});", @@ -1612,6 +1617,15 @@ ], "type": "text/javascript" } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.globals.set(\"content_id\", 'do_21357909972698726412211');" + ], + "type": "text/javascript" + } } ], "request": { @@ -1640,14 +1654,15 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/update/{{content_id}}", + "raw": "{{host}}/api/content/v2/update/{{content_id}}", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "update", @@ -1659,7 +1674,7 @@ "response": [] }, { - "name": "Content Update - 404 - Empty name", + "name": "Content Update - 404 - Invalid primaryCategory", "event": [ { "listen": "test", @@ -1668,36 +1683,37 @@ "let jsonResponse = pm.response.json()", "", "//Verification", - "pm.test(\"Status code is 400\", () => {", - " pm.response.to.have.status(400)", + "pm.test(\"Status code is 404\", () => {", + " pm.response.to.have.status(404)", "});", "//code name contains a string", - "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", "", "pm.test(\"Verify keys and data type of the response result\", () => {", " pm.expect(jsonResponse.result).to.be.an(\"object\");", " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + " pm.expect(jsonResponse.result.messages).to.be.null;", "});", "", "//Validation", "// Response body", - "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", "});", "", "// Params", - "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "pm.test(\"params.err should be \\\"404\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"404\");", "});", - "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "pm.test(\"params.status should be \\\"failed\\\"\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "});", + "pm.test(`params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}\\\"`, () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(`Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}`);", "});", "", - "// Result", - "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", - " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", + "pm.test(\"messages should be null\", () => {", + " pm.expect(jsonResponse.result.messages).to.eql(null);", "});", "" ], @@ -1731,14 +1747,15 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/update/{{content_id}}", + "raw": "{{host}}/api/content/v2/update/{{content_id}}", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "update", diff --git a/content-api/api-test/Content V2.postman_collection.json b/content-api/api-test/Content V2.postman_collection.json index c70084091..db88bf77e 100644 --- a/content-api/api-test/Content V2.postman_collection.json +++ b/content-api/api-test/Content V2.postman_collection.json @@ -102,11 +102,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/create", + "raw": "{{host}}/api/content/v2/create", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "create" @@ -123,36 +124,33 @@ { "key": "Content-Type", "value": "application/json", - "type": "text" + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." }, { "key": "X-Authenticated-User-token", "value": "{{keycloak_access_token}}", - "type": "text" + "description": "Represents the authorized User ID to execute the API." }, { "key": "Authorization", "value": "{{kong_api_key}}", - "type": "text" + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." }, { "key": "X-Channel-Id", "value": "{{channel_id}}", - "type": "text" + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"mimeType\": \"application/pdf\",\n \"code\": \"api-docs\",\n \"primaryCategory\": \"Explanation Content\",\n \"createdBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { - "raw": "https://dev.knowlg.sunbird.org/api/content/v2/create", - "protocol": "https", + "raw": "{{host}}/api/content/v2/create", "host": [ - "dev", - "knowlg", - "sunbird", - "org" + "{{host}}" ], "path": [ "api", @@ -168,7 +166,7 @@ "header": [ { "key": "Date", - "value": "Mon, 23 Nov 2020 06:42:39 GMT" + "value": "Tue, 19 Jul 2022 06:42:53 GMT" }, { "key": "Content-Type", @@ -188,47 +186,239 @@ }, { "key": "X-RateLimit-Limit-hour", - "value": "30000" + "value": "1000000" }, { "key": "X-RateLimit-Remaining-hour", - "value": "29991" + "value": "999995" }, { - "key": "Referrer-Policy", - "value": "origin-when-cross-origin, strict-origin-when-cross-origin" + "key": "request-time", + "value": "34" }, { - "key": "X-Frame-Options", - "value": "DENY" + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" }, { - "key": "X-XSS-Protection", - "value": "1; mode=block" + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" }, { - "key": "x-response-length", - "value": "55" + "key": "request-time", + "value": "11" }, { - "key": "X-Content-Type-Options", - "value": "nosniff" + "key": "x-envoy-upstream-service-time", + "value": "13" }, { "key": "Access-Control-Allow-Origin", "value": "*" }, { - "key": "X-Permitted-Cross-Domain-Policies", - "value": "master-only" + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" }, { "key": "X-Kong-Upstream-Latency", - "value": "53" + "value": "23" }, { "key": "X-Kong-Proxy-Latency", - "value": "36" + "value": "115" }, { "key": "Via", @@ -240,7 +430,7 @@ } ], "cookie": [], - "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"1.0\",\n \"ts\": \"2020-12-09T11:11:12.697Z\",\n \"params\": {\n \"resmsgid\": \"3f5de290-3a0f-11eb-be5b-f9d249ba9049\",\n \"msgid\": \"3f57a100-3a0f-11eb-be5b-f9d249ba9049\",\n \"status\": \"successful\",\n \"err\": null,\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"content_id\": \"do_1131687405374504961738\",\n \"versionKey\": \"1607512272640\"\n }\n}" + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" } ] }, @@ -324,6 +514,15 @@ ], "type": "text/javascript" } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "// pm.globals.set('content_id', 'do_213584064677732352111');" + ], + "type": "text/javascript" + } } ], "request": { @@ -349,11 +548,12 @@ } ], "url": { - "raw": "{{host}}/content/v2/read/{{content_id}}", + "raw": "{{host}}/api/content/v2/read/{{content_id}}", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "read", @@ -371,27 +571,26 @@ { "key": "Content-Type", "value": "application/json", - "type": "text" + "type": "text", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." }, { "key": "X-Authenticated-User-token", "value": "{{keycloak_access_token}}", - "type": "text" + "type": "text", + "description": "Represents the authorized User ID to execute the API." }, { "key": "Authorization", "value": "{{kong_api_key}}", - "type": "text" + "type": "text", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." } ], "url": { - "raw": "https://dev.knowlg.sunbird.org/api/content/v2/read/{{content_id}}", - "protocol": "https", + "raw": "{{host}}/api/content/v2/read/{{content_id}}", "host": [ - "dev", - "knowlg", - "sunbird", - "org" + "{{host}}" ], "path": [ "api", @@ -408,7 +607,7 @@ "header": [ { "key": "Date", - "value": "Mon, 23 Nov 2020 04:48:35 GMT" + "value": "Tue, 19 Jul 2022 06:44:16 GMT" }, { "key": "Content-Type", @@ -428,59 +627,137 @@ }, { "key": "X-RateLimit-Limit-hour", - "value": "30000" + "value": "1000000" }, { "key": "X-RateLimit-Remaining-hour", - "value": "29999" + "value": "999996" }, { - "key": "Referrer-Policy", - "value": "origin-when-cross-origin, strict-origin-when-cross-origin" + "key": "request-time", + "value": "26" }, { - "key": "X-Frame-Options", - "value": "DENY" + "key": "x-envoy-upstream-service-time", + "value": "28" }, { - "key": "X-XSS-Protection", - "value": "1; mode=block" + "key": "Access-Control-Allow-Origin", + "value": "*" }, { - "key": "x-response-length", - "value": "2759" + "key": "X-Kong-Upstream-Latency", + "value": "32" }, { - "key": "X-Content-Type-Options", - "value": "nosniff" + "key": "X-Kong-Proxy-Latency", + "value": "14" }, { - "key": "Access-Control-Allow-Origin", - "value": "*" + "key": "Via", + "value": "kong/0.14.1" }, { - "key": "X-Permitted-Cross-Domain-Policies", - "value": "master-only" + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.read\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:44:16ZZ\",\n \"params\": {\n \"resmsgid\": \"2c23c136-d4eb-4c88-897b-7077bd2894cd\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"content\": {\n \"ownershipType\": [\n \"createdBy\"\n ],\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"interceptionPoints\": {},\n \"credentials\": {\n \"enabled\": \"No\"\n },\n \"channel\": \"channel_id\",\n \"language\": [\n \"English\"\n ],\n \"mimeType\": \"application/pdf\",\n \"idealScreenSize\": \"normal\",\n \"createdOn\": \"2022-07-19T06:42:53.248+0000\",\n \"objectType\": \"Content\",\n \"primaryCategory\": \"Explanation Content\",\n \"contentDisposition\": \"inline\",\n \"lastUpdatedOn\": \"2022-07-19T06:42:53.248+0000\",\n \"contentEncoding\": \"identity\",\n \"contentType\": \"ClassroomTeachingVideo\",\n \"dialcodeRequired\": \"No\",\n \"identifier\": \"do_21358408067678208014\",\n \"lastStatusChangedOn\": \"2022-07-19T06:42:53.248+0000\",\n \"audience\": [\n \"Student\"\n ],\n \"os\": [\n \"All\"\n ],\n \"visibility\": \"Default\",\n \"consumerId\": \"ab35de9d-2a45-410a-901f-82a25e05af6d\",\n \"discussionForum\": {\n \"enabled\": \"No\"\n },\n \"mediaType\": \"content\",\n \"osId\": \"org.ekstep.quiz.app\",\n \"languageCode\": [\n \"en\"\n ],\n \"version\": 2,\n \"versionKey\": \"1658212973248\",\n \"license\": \"CC BY 4.0\",\n \"idealScreenDensity\": \"hdpi\",\n \"framework\": \"NCF\",\n \"compatibilityLevel\": 1,\n \"name\": \"Untitled Content\",\n \"status\": \"Draft\"\n }\n }\n}" + }, + { + "name": "Content Read - 404 Not Found", + "originalRequest": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + } + ], + "url": { + "raw": "{{host}}/api/content/v2/read/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "read", + "{{content_id}}" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:36:38 GMT" }, { - "key": "X-Kong-Upstream-Latency", - "value": "11" + "key": "Content-Type", + "value": "application/json" }, { - "key": "X-Kong-Proxy-Latency", - "value": "35" + "key": "Transfer-Encoding", + "value": "chunked" }, { - "key": "Via", - "value": "kong/0.14.1" + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" }, { - "key": "X-Proxy-Cache", - "value": "MISS" + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "59" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "61" }, { - "key": "X-Proxy-Cache-Date", - "value": "Mon, 23 Nov 2020 04:48:35 GMT" + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "74" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "116" + }, + { + "key": "Via", + "value": "kong/0.14.1" }, { "key": "Content-Encoding", @@ -488,7 +765,7 @@ } ], "cookie": [], - "body": "{\n \"id\": \"api.content.read\",\n \"ver\": \"1.0\",\n \"ts\": \"2020-12-09T12:09:04.202Z\",\n \"params\": {\n \"resmsgid\": \"548b82a0-3a17-11eb-be5b-f9d249ba9049\",\n \"msgid\": \"5488ea90-3a17-11eb-be5b-f9d249ba9049\",\n \"status\": \"successful\",\n \"err\": null,\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"content\": {\n \"ownershipType\": [\n \"createdBy\"\n ],\n \"code\": \"org.sunbird.ccG6ru\",\n \"credentials\": {\n \"enabled\": \"No\"\n },\n \"channel\": \"in.ekstep\",\n \"language\": [\n \"English\"\n ],\n \"mimeType\": \"application/pdf\",\n \"idealScreenSize\": \"normal\",\n \"createdOn\": \"2020-12-09T12:08:54.913+0000\",\n \"objectType\": \"Content\",\n \"primaryCategory\": \"Explanation Content\",\n \"contentDisposition\": \"inline\",\n \"lastUpdatedOn\": \"2020-12-09T12:08:54.913+0000\",\n \"contentEncoding\": \"identity\",\n \"contentType\": \"Resource\",\n \"dialcodeRequired\": \"No\",\n \"identifier\": \"do_1131687689003827201864\",\n \"lastStatusChangedOn\": \"2020-12-09T12:08:54.913+0000\",\n \"audience\": [\n \"Student\"\n ],\n \"os\": [\n \"All\"\n ],\n \"visibility\": \"Default\",\n \"consumerId\": \"7411b6bd-89f3-40ec-98d1-229dc64ce77d\",\n \"mediaType\": \"content\",\n \"osId\": \"org.ekstep.quiz.app\",\n \"languageCode\": [\n \"en\"\n ],\n \"version\": 2,\n \"versionKey\": \"1607515734913\",\n \"license\": \"CC BY 4.0\",\n \"idealScreenDensity\": \"hdpi\",\n \"framework\": \"NCF\",\n \"createdBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"compatibilityLevel\": 1,\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"status\": \"Draft\"\n }\n }\n}" + "body": "{\n \"id\": \"api.content.read\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:36:38ZZ\",\n \"params\": {\n \"resmsgid\": \"e8f48807-bff1-45c0-8eeb-760dcf7f98cf\",\n \"msgid\": null,\n \"err\": \"NOT_FOUND\",\n \"status\": \"failed\",\n \"errmsg\": \"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_213584064677732352111\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" } ] }, @@ -557,6 +834,16 @@ ], "type": "text/javascript" } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "// pm.globals.set('versionKey', '3534534543');", + "// pm.globals.set(\"content_id\", 'do_213584064677732352111');" + ], + "type": "text/javascript" + } } ], "request": { @@ -592,11 +879,12 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/content/v2/update/{{content_id}}", + "raw": "{{host}}/api/content/v2/update/{{content_id}}", "host": [ "{{host}}" ], "path": [ + "api", "content", "v2", "update", @@ -605,7 +893,336 @@ }, "description": "This API is associated with updating content on the Sunbird Platform. Mandatory fields cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" }, - "response": [] + "response": [ + { + "name": "Content Update - 400 Bad Request", + "originalRequest": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "update", + "{{content_id}}" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:38:11 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "269" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "33" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "35" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "38" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "12" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.update\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:38:11ZZ\",\n \"params\": {\n \"resmsgid\": \"0237c6eb-9d37-474f-aed5-c83aee24116b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Invalid version Key\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": null\n }\n}" + }, + { + "name": "Content Update - 404 Not Found", + "originalRequest": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "update", + "{{content_id}}" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:39:22 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999996" + }, + { + "key": "request-time", + "value": "12" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "14" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "116" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.update\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:39:22ZZ\",\n \"params\": {\n \"resmsgid\": \"e60a2a4d-c8f9-4f10-bc66-695e0f86d82c\",\n \"msgid\": null,\n \"err\": \"NOT_FOUND\",\n \"status\": \"failed\",\n \"errmsg\": \"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_213584064677732352111\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + }, + { + "name": "Content Update - 200 OK", + "originalRequest": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "update", + "{{content_id}}" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:44:37 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "87" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "88" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "92" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.update\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:44:37ZZ\",\n \"params\": {\n \"resmsgid\": \"767eada1-6342-4503-ad0d-b18aea711aab\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658213077381\"\n }\n}" + } + ] } ] } \ No newline at end of file From d8a8bb816912b6fd4905608f3670f7a1f983457f Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 20 Jul 2022 12:05:11 +0530 Subject: [PATCH 053/105] Issue #SB-30154 feat: DIAL code Link API refactor. --- .../src/main/scala/org/sunbird/content/dial/DIALManager.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 2974228ce..acbda5f8a 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -179,6 +179,7 @@ object DIALManager { rootNodeMetadata.remove(DIALConstants.DISCUSSION_FORUM) rootNodeMetadata.remove(DIALConstants.CREDENTIALS) rootNodeMetadata.remove(DIALConstants.TRACKABLE) + rootNodeMetadata.remove(DIALConstants.RESERVED_DIALCODES) if(rootNodeMetadata.containsKey(DIALConstants.DIALCODES)) rootNodeMetadata.remove(DIALConstants.DIALCODES) From 7522a8fd83e98db36397fa4242b4883cc16ac190 Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Wed, 27 Jul 2022 08:58:24 +0530 Subject: [PATCH 054/105] Issue #SB-30119 test: Added the postman tests for content v2 create, read and update API. --- .../Content V2.postman_collection.json | 90 +++++++++---------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/content-api/api-test/Content V2.postman_collection.json b/content-api/api-test/Content V2.postman_collection.json index db88bf77e..baf4d7f39 100644 --- a/content-api/api-test/Content V2.postman_collection.json +++ b/content-api/api-test/Content V2.postman_collection.json @@ -2,7 +2,7 @@ "info": { "_postman_id": "95bee03d-d782-47da-89f9-cc70bb0a267e", "name": "Content V2", - "description": "The Content Management APIs allow you to create, manage and process content on the Sunbird platform. Content is the basic building block of the Knowledge Service. Some examples would be Videos, Audio, Pdfs, Html, ECML etc. The basic operations for this API include Create, Update, Read, Review, Publish.\n\n* Each of the endpoints serve a different purpose, so which one to use depends on what you want to do\n* The operations include CRUD (Create, Update, Read and Delete) operations and other operations such as upload, publish, flag, link DIAL code, etc.\n* The URL for Content Management API(s) is /content/v2.\n \n\nAPI tests", + "description": "The Content Management APIs allow you to create, manage and process content on the Sunbird platform. Content is the basic building block of the Knowledge Service. Some examples would be Videos, Audio, Pdfs, Html, ECML etc. The basic operations for this API include Create, Update, Read, Review, Publish.\n\n* Each of the endpoints serve a different purpose, so which one to use depends on what you want to do\n* The operations include CRUD (Create, Update, Read and Delete) operations and other operations such as upload, publish, flag, link DIAL code, etc.\n* The URL for Content Management API(s) is /content/v2.\n \n\nFor more details refer [here](https://knowlg.sunbird.org/learn/readme)\n\nAPI tests", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", "_exporter_id": "1419050" }, @@ -113,7 +113,7 @@ "create" ] }, - "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" }, "response": [ { @@ -891,11 +891,11 @@ "{{content_id}}" ] }, - "description": "This API is associated with updating content on the Sunbird Platform. Mandatory fields cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + "description": "This API is associated with updating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" }, "response": [ { - "name": "Content Update - 400 Bad Request", + "name": "Content Update - 200 OK", "originalRequest": { "method": "PATCH", "header": [ @@ -942,41 +942,45 @@ ] } }, - "status": "Bad Request", - "code": 400, + "status": "OK", + "code": 200, "_postman_previewlanguage": "json", "header": [ { "key": "Date", - "value": "Tue, 19 Jul 2022 06:38:11 GMT" + "value": "Tue, 19 Jul 2022 06:44:37 GMT" }, { "key": "Content-Type", "value": "application/json" }, { - "key": "Content-Length", - "value": "269" + "key": "Transfer-Encoding", + "value": "chunked" }, { "key": "Connection", "value": "keep-alive" }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, { "key": "X-RateLimit-Limit-hour", "value": "1000000" }, { "key": "X-RateLimit-Remaining-hour", - "value": "999997" + "value": "999995" }, { "key": "request-time", - "value": "33" + "value": "87" }, { "key": "x-envoy-upstream-service-time", - "value": "35" + "value": "88" }, { "key": "Access-Control-Allow-Origin", @@ -984,22 +988,26 @@ }, { "key": "X-Kong-Upstream-Latency", - "value": "38" + "value": "92" }, { "key": "X-Kong-Proxy-Latency", - "value": "12" + "value": "115" }, { "key": "Via", "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" } ], "cookie": [], - "body": "{\n \"id\": \"api.content.update\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:38:11ZZ\",\n \"params\": {\n \"resmsgid\": \"0237c6eb-9d37-474f-aed5-c83aee24116b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Invalid version Key\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": null\n }\n}" + "body": "{\n \"id\": \"api.content.update\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:44:37ZZ\",\n \"params\": {\n \"resmsgid\": \"767eada1-6342-4503-ad0d-b18aea711aab\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658213077381\"\n }\n}" }, { - "name": "Content Update - 404 Not Found", + "name": "Content Update - 400 Bad Request", "originalRequest": { "method": "PATCH", "header": [ @@ -1046,45 +1054,41 @@ ] } }, - "status": "Not Found", - "code": 404, + "status": "Bad Request", + "code": 400, "_postman_previewlanguage": "json", "header": [ { "key": "Date", - "value": "Tue, 19 Jul 2022 06:39:22 GMT" + "value": "Tue, 19 Jul 2022 06:38:11 GMT" }, { "key": "Content-Type", "value": "application/json" }, { - "key": "Transfer-Encoding", - "value": "chunked" + "key": "Content-Length", + "value": "269" }, { "key": "Connection", "value": "keep-alive" }, - { - "key": "Vary", - "value": "Accept-Encoding" - }, { "key": "X-RateLimit-Limit-hour", "value": "1000000" }, { "key": "X-RateLimit-Remaining-hour", - "value": "999996" + "value": "999997" }, { "key": "request-time", - "value": "12" + "value": "33" }, { "key": "x-envoy-upstream-service-time", - "value": "14" + "value": "35" }, { "key": "Access-Control-Allow-Origin", @@ -1092,26 +1096,22 @@ }, { "key": "X-Kong-Upstream-Latency", - "value": "18" + "value": "38" }, { "key": "X-Kong-Proxy-Latency", - "value": "116" + "value": "12" }, { "key": "Via", "value": "kong/0.14.1" - }, - { - "key": "Content-Encoding", - "value": "gzip" } ], "cookie": [], - "body": "{\n \"id\": \"api.content.update\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:39:22ZZ\",\n \"params\": {\n \"resmsgid\": \"e60a2a4d-c8f9-4f10-bc66-695e0f86d82c\",\n \"msgid\": null,\n \"err\": \"NOT_FOUND\",\n \"status\": \"failed\",\n \"errmsg\": \"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_213584064677732352111\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + "body": "{\n \"id\": \"api.content.update\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:38:11ZZ\",\n \"params\": {\n \"resmsgid\": \"0237c6eb-9d37-474f-aed5-c83aee24116b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Invalid version Key\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": null\n }\n}" }, { - "name": "Content Update - 200 OK", + "name": "Content Update - 404 Not Found", "originalRequest": { "method": "PATCH", "header": [ @@ -1158,13 +1158,13 @@ ] } }, - "status": "OK", - "code": 200, + "status": "Not Found", + "code": 404, "_postman_previewlanguage": "json", "header": [ { "key": "Date", - "value": "Tue, 19 Jul 2022 06:44:37 GMT" + "value": "Tue, 19 Jul 2022 06:39:22 GMT" }, { "key": "Content-Type", @@ -1188,15 +1188,15 @@ }, { "key": "X-RateLimit-Remaining-hour", - "value": "999995" + "value": "999996" }, { "key": "request-time", - "value": "87" + "value": "12" }, { "key": "x-envoy-upstream-service-time", - "value": "88" + "value": "14" }, { "key": "Access-Control-Allow-Origin", @@ -1204,11 +1204,11 @@ }, { "key": "X-Kong-Upstream-Latency", - "value": "92" + "value": "18" }, { "key": "X-Kong-Proxy-Latency", - "value": "115" + "value": "116" }, { "key": "Via", @@ -1220,7 +1220,7 @@ } ], "cookie": [], - "body": "{\n \"id\": \"api.content.update\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:44:37ZZ\",\n \"params\": {\n \"resmsgid\": \"767eada1-6342-4503-ad0d-b18aea711aab\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658213077381\"\n }\n}" + "body": "{\n \"id\": \"api.content.update\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:39:22ZZ\",\n \"params\": {\n \"resmsgid\": \"e60a2a4d-c8f9-4f10-bc66-695e0f86d82c\",\n \"msgid\": null,\n \"err\": \"NOT_FOUND\",\n \"status\": \"failed\",\n \"errmsg\": \"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_213584064677732352111\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" } ] } From 10c0026942c9572b131f2c16f20eccdfc0ab1546 Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Wed, 27 Jul 2022 09:01:18 +0530 Subject: [PATCH 055/105] Issue #SB-30119 test: Added the Collections and Reports folder. --- .../Collections}/Content V2 API Test.postman_collection.json | 0 .../Collections}/Content V2.postman_collection.json | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename content-api/{api-test => api-tests/Collections}/Content V2 API Test.postman_collection.json (100%) rename content-api/{api-test => api-tests/Collections}/Content V2.postman_collection.json (100%) diff --git a/content-api/api-test/Content V2 API Test.postman_collection.json b/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json similarity index 100% rename from content-api/api-test/Content V2 API Test.postman_collection.json rename to content-api/api-tests/Collections/Content V2 API Test.postman_collection.json diff --git a/content-api/api-test/Content V2.postman_collection.json b/content-api/api-tests/Collections/Content V2.postman_collection.json similarity index 100% rename from content-api/api-test/Content V2.postman_collection.json rename to content-api/api-tests/Collections/Content V2.postman_collection.json From 5f89777b163b3a59809073759acf00371b084aeb Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Wed, 27 Jul 2022 11:08:15 +0530 Subject: [PATCH 056/105] Issue #SB-30119 test: Added the Collections and Reports for content v2 APIs. --- ...ontent V2 API Test.postman_collection.json | 1044 +++++-- .../Content V2 API Test.postman_test_run.json | 2574 +++++++++++++++++ 2 files changed, 3395 insertions(+), 223 deletions(-) create mode 100644 content-api/api-tests/Reports/Content V2 API Test.postman_test_run.json diff --git a/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json b/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json index 77efae5c8..583e76895 100644 --- a/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json +++ b/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json @@ -14,7 +14,7 @@ "name": "Content Create ", "item": [ { - "name": "Content Create - with minimal required attribute", + "name": "200 - With minimal required attribute", "event": [ { "listen": "test", @@ -93,7 +93,174 @@ "response": [] }, { - "name": "Content Create - Special character in name", + "name": "200 - With identifier", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", + " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"id should be api.content.create\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", + "});", + "pm.test(\"ver should be 4.0\", function () {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "", + "// Result", + "pm.test(`identifier should be equal to ${JSON.parse(request.data).request.content.identifier}`, () => {", + " pm.expect(jsonResponse.result.identifier).to.eql(`${JSON.parse(request.data).request.content.identifier}`);", + "});", + "pm.test(`node_id should be equal to ${JSON.parse(request.data).request.content.identifier}`, () => {", + " pm.expect(jsonResponse.result.node_id).to.eql(`${JSON.parse(request.data).request.content.identifier}`);", + "});", + "", + "// Set global variable", + "pm.globals.set(\"content_id\", jsonResponse.result.identifier);", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"identifier\": \"some_identifier\",\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "200 - With external fields", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", + " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.create\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", + "});", + "pm.test(\"ver should be 4.0\", function () {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "", + "// Set global variable", + "pm.globals.set(\"content_id\", jsonResponse.result.identifier);", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\",\n \"body\": \"{\\\"key\\\":\\\"value\\\"}\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "200 - Special character in name", "event": [ { "listen": "test", @@ -177,7 +344,7 @@ "name": "Content Read", "item": [ { - "name": "Content Read", + "name": "200 - Get all data except external data", "event": [ { "listen": "test", @@ -267,7 +434,7 @@ "response": [] }, { - "name": "Content Read - fields query params", + "name": "200 - Get specific attributes by sending fields query params", "event": [ { "listen": "test", @@ -328,7 +495,7 @@ } ], "url": { - "raw": "{{host}}/api/content/v2/read/{{content_id}}?fields=name,primaryCategory", + "raw": "{{host}}/api/content/v2/read/{{content_id}}?fields=name,primaryCategory,body", "host": [ "{{host}}" ], @@ -342,7 +509,8 @@ "query": [ { "key": "fields", - "value": "name,primaryCategory" + "value": "name,primaryCategory,body", + "description": "Fields param is used to get the external data in response, by default read API doesn't return external data. Also fields can be used to get the specific data only in response instead of getting all the data." } ] }, @@ -376,7 +544,100 @@ "name": "Content Update", "item": [ { - "name": "Content Update", + "name": "200 - Update existing data or add new data", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", + " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", + "});", + "", + "//Validation", + "pm.test(\"id should be api.content.update\", () => {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "", + "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), () => {", + " pm.expect(jsonResponse.result.identifier).to.eql(pm.globals.get(\"content_id\"));", + "});", + "pm.test(\"node_id should be equal to \" + pm.globals.get(\"content_id\"), () => {", + " pm.expect(jsonResponse.result.node_id).to.eql(pm.globals.get(\"content_id\"));", + "});", + "", + "// Set global variable", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "// pm.globals.set('content_id');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "update", + "{{content_id}}" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "200 - Special character in name", "event": [ { "listen": "test", @@ -392,54 +653,498 @@ "});", "", "//Validation", - "pm.test(\"id should be api.content.update\", () => {", - " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", - "});", - "pm.test(\"ver should be 4.0\", () => {", - " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "pm.test(\"id should be api.content.update\", () => {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "", + "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), () => {", + " pm.expect(jsonResponse.result.identifier).to.eql(pm.globals.get(\"content_id\"));", + "});", + "pm.test(\"node_id should be equal to \" + pm.globals.get(\"content_id\"), () => {", + " pm.expect(jsonResponse.result.node_id).to.eql(pm.globals.get(\"content_id\"));", + "});", + "", + "// Set global variable", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"~`S!@#$%^&*()_+=:;\\\"'<,>.?/\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "update", + "{{content_id}}" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "//Verification", + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200)", + "});", + "//code name contains a string", + "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", + "", + "// pm.test(\"Content-Encoding header is present\", () => {", + "// pm.response.to.have.header(\"Content-Encoding\");", + "// });", + "// pm.test(\"Content-Encoding header is gzip\", () => {", + "// pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "// });", + "", + "pm.test(\"Verify keys and data type of the params in positive scenario\", () => {", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + "});", + "", + "pm.test(\"params.status should be \\\"successful\\\"\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});" + ] + } + } + ] + }, + { + "name": "Negative", + "item": [ + { + "name": "Content Create", + "item": [ + { + "name": "400 - missing channel", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata channel not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata channel not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - empty channel", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata channel not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata channel not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - missing name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - name: invalid datatype", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", "});", "", - "pm.test(\"identifier should be equal to \" + pm.globals.get(\"content_id\"), () => {", - " pm.expect(jsonResponse.result.identifier).to.eql(pm.globals.get(\"content_id\"));", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", "});", - "pm.test(\"node_id should be equal to \" + pm.globals.get(\"content_id\"), () => {", - " pm.expect(jsonResponse.result.node_id).to.eql(pm.globals.get(\"content_id\"));", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", "});", "", - "// Set global variable", - "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "// Result", + "pm.test(\"result body should include messages \\\"Metadata name should be a/an String value\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Metadata name should be a/an String value');", + "});", "" ], "type": "text/javascript" } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "// pm.globals.set('content_id');" - ], - "type": "text/javascript" - } } ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, "request": { - "method": "PATCH", + "method": "POST", "header": [ { "key": "Content-Type", - "value": "application/json", - "type": "text" + "value": "application/json" }, { "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}", - "type": "text" + "value": "{{keycloak_access_token}}" }, { "key": "Authorization", - "value": "{{kong_api_key}}", - "type": "text" + "value": "{{kong_api_key}}" }, { "key": "X-Channel-Id", @@ -449,10 +1154,10 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": 423432,\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/update/{{content_id}}", + "raw": "{{host}}/api/content/v2/create", "host": [ "{{host}}" ], @@ -460,16 +1165,15 @@ "api", "content", "v2", - "update", - "{{content_id}}" + "create" ] }, - "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." }, "response": [] }, { - "name": "Content Update - Special character in name", + "name": "400 - name empty", "event": [ { "listen": "test", @@ -478,64 +1182,36 @@ "let jsonResponse = pm.response.json()", "", "//Verification", - "pm.test(\"Status code is 404\", function () {", - " pm.response.to.have.status(404)", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400)", "});", "//code name contains a string", - "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", - "", - "pm.test(\"Content-Type header is present\", () => {", - " pm.response.to.have.header(\"Content-Type\");", - "});", - "pm.test(\"Content-Type header is application/json\", () => {", - " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", - "});", - "pm.test(\"Content-Encoding header should not present\", () => {", - " pm.response.to.have.header(\"Content-Encoding\");", - "});", - "pm.test(\"Content-Encoding header is gzip\", () => {", - " pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", - "});", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", "", "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", - " pm.expect(jsonResponse.id).to.be.a(\"string\");", - " pm.expect(jsonResponse.ver).to.be.a(\"string\");", - " pm.expect(jsonResponse.ts).to.be.a(\"string\");", - " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", - " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.a(\"string\");", " pm.expect(jsonResponse.result).to.be.an(\"object\");", " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.be.null;", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", "});", "", "//Validation", "// Response body", - "pm.test(\"id should be api.content.update\", () => {", - " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", - "});", - "pm.test(\"ver should be 4.0\", () => {", - " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", - "});", - "pm.test(\"params.err should be \\\"404\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"404\");", - "});", - "pm.test(\"params.status should be \\\"failed\\\"\", () => {", - " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", "});", - "pm.test(\"params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\");", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", "});", - "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", "});", - "pm.test(\"messages should be null\", () => {", - " pm.expect(jsonResponse.result.messages).to.eql(null);", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", "});", "" ], @@ -543,23 +1219,25 @@ } } ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, "request": { - "method": "PATCH", + "method": "POST", "header": [ { "key": "Content-Type", - "value": "application/json", - "type": "text" + "value": "application/json" }, { "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}", - "type": "text" + "value": "{{keycloak_access_token}}" }, { "key": "Authorization", - "value": "{{kong_api_key}}", - "type": "text" + "value": "{{kong_api_key}}" }, { "key": "X-Channel-Id", @@ -569,10 +1247,10 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"~`S!@#$%^&*()_+=:;\\\"'<,>.?/\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/update/{{content_id}}", + "raw": "{{host}}/api/content/v2/create", "host": [ "{{host}}" ], @@ -580,95 +1258,15 @@ "api", "content", "v2", - "update", - "{{content_id}}" + "create" ] }, - "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." }, "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } }, { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "let jsonResponse = pm.response.json();", - "", - "//Verification", - "pm.test(\"Status code is 200\", () => {", - " pm.response.to.have.status(200)", - "});", - "//code name contains a string", - "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", - "", - "// pm.test(\"Content-Encoding header is present\", () => {", - "// pm.response.to.have.header(\"Content-Encoding\");", - "// });", - "// pm.test(\"Content-Encoding header is gzip\", () => {", - "// pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", - "// });", - "", - "pm.test(\"Verify keys and data type of the params in positive scenario\", () => {", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.null;", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.null;", - "});", - "", - "pm.test(\"params.status should be \\\"successful\\\"\", () => {", - " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", - "});", - "pm.test(\"responseCode should be OK\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", - "});" - ] - } - } - ] - }, - { - "name": "Negative", - "item": [ - { - "name": "Content Create", - "item": [ - { - "name": "Content Create - 400 - missing name", + "name": "400 - missing code", "event": [ { "listen": "test", @@ -677,7 +1275,7 @@ "let jsonResponse = pm.response.json()", "", "//Verification", - "pm.test(\"Status code is 400\", () => {", + "pm.test(\"Status code is 400\", function () {", " pm.response.to.have.status(400)", "});", "//code name contains a string", @@ -704,9 +1302,9 @@ "});", "", "// Result", - "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", + "pm.test(\"result body should include messages \\\"Required Metadata code not set\\\"\", () => {", " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata code not set');", "});", "" ], @@ -742,7 +1340,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { "raw": "{{host}}/api/content/v2/create", @@ -761,7 +1359,7 @@ "response": [] }, { - "name": "Content Create - 400 - name empty", + "name": "400 - missing mimeType", "event": [ { "listen": "test", @@ -797,9 +1395,9 @@ "});", "", "// Result", - "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", + "pm.test(\"result body should include messages \\\"Required Metadata mimeType not set\\\"\", () => {", " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata mimeType not set');", "});", "" ], @@ -835,7 +1433,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { "raw": "{{host}}/api/content/v2/create", @@ -854,7 +1452,7 @@ "response": [] }, { - "name": "Content Create - 400 - missing code", + "name": "400 - invalid mimeType", "event": [ { "listen": "test", @@ -890,9 +1488,9 @@ "});", "", "// Result", - "pm.test(\"result body should include messages \\\"Required Metadata code not set\\\"\", () => {", + "pm.test(\"result body should include messages \\\"Metadata mimeType should be one of: [application/vnd.ekstep.ecml-archive, application/vnd.ekstep.html-archive, application/vnd.android.package-archive, application/vnd.ekstep.content-archive, application/vnd.ekstep.content-collection, application/vnd.ekstep.plugin-archive, application/vnd.ekstep.h5p-archive, application/epub, text/x-url, video/x-youtube, application/octet-stream, application/msword, application/pdf, image/jpeg, image/jpg, image/png, image/tiff, image/bmp, image/gif, image/svg+xml, video/avi, video/mpeg, video/quicktime, video/3gpp, video/mp4, video/ogg, video/webm, audio/mp3, audio/mp4, audio/mpeg, audio/ogg, audio/webm, audio/x-wav, audio/wav, application/json, application/quiz]\\\"\", () => {", " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Required Metadata code not set');", + " pm.expect(jsonResponse.result.messages).to.include('Metadata mimeType should be one of: [application/vnd.ekstep.ecml-archive, application/vnd.ekstep.html-archive, application/vnd.android.package-archive, application/vnd.ekstep.content-archive, application/vnd.ekstep.content-collection, application/vnd.ekstep.plugin-archive, application/vnd.ekstep.h5p-archive, application/epub, text/x-url, video/x-youtube, application/octet-stream, application/msword, application/pdf, image/jpeg, image/jpg, image/png, image/tiff, image/bmp, image/gif, image/svg+xml, video/avi, video/mpeg, video/quicktime, video/3gpp, video/mp4, video/ogg, video/webm, audio/mp3, audio/mp4, audio/mpeg, audio/ogg, audio/webm, audio/x-wav, audio/wav, application/json, application/quiz]');", "});", "" ], @@ -928,7 +1526,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"some-mimeType\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { "raw": "{{host}}/api/content/v2/create", @@ -947,7 +1545,7 @@ "response": [] }, { - "name": "Content Create - 400 - missing mimeType", + "name": "400 - missing primaryCategory", "event": [ { "listen": "test", @@ -956,7 +1554,7 @@ "let jsonResponse = pm.response.json()", "", "//Verification", - "pm.test(\"Status code is 400\", function () {", + "pm.test(\"Status code is 400\", () => {", " pm.response.to.have.status(400)", "});", "//code name contains a string", @@ -964,8 +1562,6 @@ "", "pm.test(\"Verify keys and data type of the response result\", () => {", " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.not.be.empty;", "});", "", "//Validation", @@ -975,17 +1571,17 @@ "});", "", "// Params", - "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "pm.test(\"params.err should be \\\"VALIDATION_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"VALIDATION_ERROR\");", "});", - "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "pm.test(\"params.errmsg should be \\\"primaryCategory is a mandatory parameter\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"primaryCategory is a mandatory parameter\");", "});", "", "// Result", - "pm.test(\"result body should include messages \\\"Required Metadata mimeType not set\\\"\", () => {", - " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Required Metadata mimeType not set');", + "pm.test(\"result body should be empty\", () => {", + " pm.expect(jsonResponse.result).to.eql({});", + " pm.expect(jsonResponse.result).to.be.empty;", "});", "" ], @@ -1021,7 +1617,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\"\n }\n }\n}" }, "url": { "raw": "{{host}}/api/content/v2/create", @@ -1040,7 +1636,7 @@ "response": [] }, { - "name": "Content Create - 400 - missing primaryCategory", + "name": "400 - Invalid subject", "event": [ { "listen": "test", @@ -1057,6 +1653,8 @@ "", "pm.test(\"Verify keys and data type of the response result\", () => {", " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", "});", "", "//Validation", @@ -1066,17 +1664,17 @@ "});", "", "// Params", - "pm.test(\"params.err should be \\\"VALIDATION_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"VALIDATION_ERROR\");", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", "});", - "pm.test(\"params.errmsg should be \\\"primaryCategory is a mandatory parameter\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"primaryCategory is a mandatory parameter\");", + "pm.test(\"params.errmsg should be \\\"Validation Errors.\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors.\");", "});", "", "// Result", - "pm.test(\"result body should be empty\", () => {", - " pm.expect(jsonResponse.result).to.eql({});", - " pm.expect(jsonResponse.result).to.be.empty;", + "pm.test(\"result body should include messages \\\"subject range data is empty from the given framework.\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('subject range data is empty from the given framework.');", "});", "" ], @@ -1112,7 +1710,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12-erwe\",\n \"subject\": [\"test\"],\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" }, "url": { "raw": "{{host}}/api/content/v2/create", @@ -1131,7 +1729,7 @@ "response": [] }, { - "name": "Content Create - 404 - Invalid primaryCategory", + "name": "404 - Invalid primaryCategory", "event": [ { "listen": "test", @@ -1254,7 +1852,7 @@ "name": "Content Read", "item": [ { - "name": "Content Read - 404 - Not Found", + "name": "404 - Not Found", "event": [ { "listen": "test", @@ -1374,7 +1972,7 @@ "name": "Content Update", "item": [ { - "name": "Content Update - 400 - Invalid versionKey", + "name": "400 - Invalid versionKey", "event": [ { "listen": "test", @@ -1429,7 +2027,7 @@ "listen": "prerequest", "script": { "exec": [ - "pm.globals.set('versionKey', '3534534543');", + "pm.globals.set('invalid-versionKey', '3534534543');", "// pm.globals.set(\"content_id\", '');" ], "type": "text/javascript" @@ -1462,7 +2060,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{invalid-versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" }, "url": { "raw": "{{host}}/api/content/v2/update/{{content_id}}", @@ -1482,7 +2080,7 @@ "response": [] }, { - "name": "Content Update - 400 - Empty name", + "name": "400 - Empty name", "event": [ { "listen": "test", @@ -1574,7 +2172,7 @@ "response": [] }, { - "name": "Content Update - 404 - Invalid content id", + "name": "404 - Invalid content id", "event": [ { "listen": "test", @@ -1605,8 +2203,8 @@ "pm.test(\"params.err should be NOT_FOUND\", () => {", " pm.expect(jsonResponse.params.err).to.eql(\"NOT_FOUND\");", "});", - "pm.test(`params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"content_id\")}\\\"`, () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(`Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"content_id\")}`);", + "pm.test(`params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"invalid_content_id\")}\\\"`, () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(`Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"invalid_content_id\")}`);", "});", "", "// Result", @@ -1622,7 +2220,7 @@ "listen": "prerequest", "script": { "exec": [ - "pm.globals.set(\"content_id\", 'do_21357909972698726412211');" + "pm.globals.set(\"invalid_content_id\", 'do_21357909972698726412211');" ], "type": "text/javascript" } @@ -1657,7 +2255,7 @@ "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/update/{{content_id}}", + "raw": "{{host}}/api/content/v2/update/{{invalid_content_id}}", "host": [ "{{host}}" ], @@ -1666,7 +2264,7 @@ "content", "v2", "update", - "{{content_id}}" + "{{invalid_content_id}}" ] }, "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." @@ -1674,7 +2272,7 @@ "response": [] }, { - "name": "Content Update - 404 - Invalid primaryCategory", + "name": "404 - Invalid primaryCategory", "event": [ { "listen": "test", diff --git a/content-api/api-tests/Reports/Content V2 API Test.postman_test_run.json b/content-api/api-tests/Reports/Content V2 API Test.postman_test_run.json new file mode 100644 index 000000000..aff0883c2 --- /dev/null +++ b/content-api/api-tests/Reports/Content V2 API Test.postman_test_run.json @@ -0,0 +1,2574 @@ +{ + "id": "489956f4-e5fd-4c92-8408-6a4598e10940", + "name": "Content V2 API Test", + "timestamp": "2022-07-27T05:30:40.864Z", + "collection_id": "1419050-58a713b4-b8bb-4885-9909-b23d253f8f31", + "folder_id": 0, + "environment_id": "1419050-b1be6ead-50b9-49a1-b0e2-95f479990dad", + "totalPass": 328, + "totalFail": 0, + "results": [ + { + "id": "2383265f-a48f-47dc-9538-e3c7a16b1d98", + "name": "200 - With minimal required attribute", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 229, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.create": true, + "ver should be 4.0": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 229 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.create": true, + "ver should be 4.0": true + } + ] + }, + { + "id": "fdb1f5bc-f5b3-4c3c-b622-bd86a8f92b40", + "name": "200 - With identifier", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 61, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "identifier should be equal to some_identifier": true, + "node_id should be equal to some_identifier": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "identifier should be equal to some_identifier": { + "pass": 1, + "fail": 0 + }, + "node_id should be equal to some_identifier": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 61 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "identifier should be equal to some_identifier": true, + "node_id should be equal to some_identifier": true + } + ] + }, + { + "id": "67644d61-7797-4f54-82cf-d4b7711b5282", + "name": "200 - With external fields", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 84, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.create": true, + "ver should be 4.0": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 84 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.create": true, + "ver should be 4.0": true + } + ] + }, + { + "id": "4fa811d0-1e33-493c-95fe-39bac77bae42", + "name": "200 - Special character in name", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 67, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.create": true, + "ver should be 4.0": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 67 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.create": true, + "ver should be 4.0": true + } + ] + }, + { + "id": "5f38fbf3-1dd6-4f5a-8796-6ca07d837d25", + "name": "200 - Get all data ecxept external data", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/read/do_2135897074718965761132", + "time": 111, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.read": true, + "ver should be 4.0": true, + "identifier should be equal to do_2135897074718965761132": true, + "objectType should be Content": true, + "visibility should be Default": true, + "compatibilityLevel should be 1": true, + "status should be Draft": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.read": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "identifier should be equal to do_2135897074718965761132": { + "pass": 1, + "fail": 0 + }, + "objectType should be Content": { + "pass": 1, + "fail": 0 + }, + "visibility should be Default": { + "pass": 1, + "fail": 0 + }, + "compatibilityLevel should be 1": { + "pass": 1, + "fail": 0 + }, + "status should be Draft": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 111 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.read": true, + "ver should be 4.0": true, + "identifier should be equal to do_2135897074718965761132": true, + "objectType should be Content": true, + "visibility should be Default": true, + "compatibilityLevel should be 1": true, + "status should be Draft": true + } + ] + }, + { + "id": "6cad6c08-f73b-4d00-9395-b8cbcb3cafe0", + "name": "200 - Get specific attributes by sending fields query params", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/read/do_2135897074718965761132?fields=name,primaryCategory,body", + "time": 69, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.read": true, + "ver should be 4.0": true, + "identifier should be equal to do_2135897074718965761132": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.read": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "identifier should be equal to do_2135897074718965761132": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 69 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.read": true, + "ver should be 4.0": true, + "identifier should be equal to do_2135897074718965761132": true + } + ] + }, + { + "id": "bcd0f26d-ca6b-4eb7-815a-e85c4044a829", + "name": "200 - Update existing data or add new data", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/update/do_2135897074718965761132", + "time": 558, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.update": true, + "ver should be 4.0": true, + "identifier should be equal to do_2135897074718965761132": true, + "node_id should be equal to do_2135897074718965761132": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.update": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "identifier should be equal to do_2135897074718965761132": { + "pass": 1, + "fail": 0 + }, + "node_id should be equal to do_2135897074718965761132": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 558 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.update": true, + "ver should be 4.0": true, + "identifier should be equal to do_2135897074718965761132": true, + "node_id should be equal to do_2135897074718965761132": true + } + ] + }, + { + "id": "1d43c4ab-ea8b-449c-8dca-aa7eda247bfa", + "name": "200 - Special character in name", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/update/do_2135897074718965761132", + "time": 575, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.update": true, + "ver should be 4.0": true, + "identifier should be equal to do_2135897074718965761132": true, + "node_id should be equal to do_2135897074718965761132": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.update": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "identifier should be equal to do_2135897074718965761132": { + "pass": 1, + "fail": 0 + }, + "node_id should be equal to do_2135897074718965761132": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 575 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true, + "Verify keys and data type of the response result": true, + "id should be api.content.update": true, + "ver should be 4.0": true, + "identifier should be equal to do_2135897074718965761132": true, + "node_id should be equal to do_2135897074718965761132": true + } + ] + }, + { + "id": "6d2a8074-8afe-40ba-9e29-2376fc3db053", + "name": "400 - missing channel", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 21, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata channel not set\"": true, + "Status code name has string \"Bad Request\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Validation Errors\"": { + "pass": 1, + "fail": 0 + }, + "result body should include messages \"Required Metadata channel not set\"": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Bad Request\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 21 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata channel not set\"": true, + "Status code name has string \"Bad Request\"": true + } + ] + }, + { + "id": "59690e87-ff4d-4d1d-b549-0156afa7611b", + "name": "400 - empty channel", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 71, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata channel not set\"": true, + "Status code name has string \"Bad Request\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Validation Errors\"": { + "pass": 1, + "fail": 0 + }, + "result body should include messages \"Required Metadata channel not set\"": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Bad Request\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 71 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata channel not set\"": true, + "Status code name has string \"Bad Request\"": true + } + ] + }, + { + "id": "dd956c1e-35b6-4525-baaf-0b2a8ab5ab57", + "name": "400 - missing name", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 69, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata name not set\"": true, + "Status code name has string \"Bad Request\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Validation Errors\"": { + "pass": 1, + "fail": 0 + }, + "result body should include messages \"Required Metadata name not set\"": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Bad Request\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 69 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata name not set\"": true, + "Status code name has string \"Bad Request\"": true + } + ] + }, + { + "id": "c6c1b7fd-a278-4ef3-9d2e-6c76a53d1c33", + "name": "400 - name: invalid datatype", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 49, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Metadata name should be a/an String value\"": true, + "Status code name has string \"Bad Request\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Validation Errors\"": { + "pass": 1, + "fail": 0 + }, + "result body should include messages \"Metadata name should be a/an String value\"": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Bad Request\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 49 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Metadata name should be a/an String value\"": true, + "Status code name has string \"Bad Request\"": true + } + ] + }, + { + "id": "a1ac9342-84c0-4395-aa52-b8248007722d", + "name": "400 - name empty", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 48, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata name not set\"": true, + "Status code name has string \"Bad Request\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Validation Errors\"": { + "pass": 1, + "fail": 0 + }, + "result body should include messages \"Required Metadata name not set\"": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Bad Request\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 48 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata name not set\"": true, + "Status code name has string \"Bad Request\"": true + } + ] + }, + { + "id": "37e04040-1676-4dca-a674-54210b5990e2", + "name": "400 - missing code", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 67, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata code not set\"": true, + "Status code name has string \"Bad Request\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Validation Errors\"": { + "pass": 1, + "fail": 0 + }, + "result body should include messages \"Required Metadata code not set\"": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Bad Request\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 67 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata code not set\"": true, + "Status code name has string \"Bad Request\"": true + } + ] + }, + { + "id": "077b803b-7fbb-4264-823c-c41c0bac597d", + "name": "400 - missing mimeType", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 45, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata mimeType not set\"": true, + "Status code name has string \"Bad Request\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Validation Errors\"": { + "pass": 1, + "fail": 0 + }, + "result body should include messages \"Required Metadata mimeType not set\"": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Bad Request\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 45 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata mimeType not set\"": true, + "Status code name has string \"Bad Request\"": true + } + ] + }, + { + "id": "6a365695-00de-4d90-ab6f-4726e59b1898", + "name": "400 - invalid mimeType", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 69, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Metadata mimeType should be one of: [application/vnd.ekstep.ecml-archive, application/vnd.ekstep.html-archive, application/vnd.android.package-archive, application/vnd.ekstep.content-archive, application/vnd.ekstep.content-collection, application/vnd.ekstep.plugin-archive, application/vnd.ekstep.h5p-archive, application/epub, text/x-url, video/x-youtube, application/octet-stream, application/msword, application/pdf, image/jpeg, image/jpg, image/png, image/tiff, image/bmp, image/gif, image/svg+xml, video/avi, video/mpeg, video/quicktime, video/3gpp, video/mp4, video/ogg, video/webm, audio/mp3, audio/mp4, audio/mpeg, audio/ogg, audio/webm, audio/x-wav, audio/wav, application/json, application/quiz]\"": true, + "Status code name has string \"Bad Request\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Validation Errors\"": { + "pass": 1, + "fail": 0 + }, + "result body should include messages \"Metadata mimeType should be one of: [application/vnd.ekstep.ecml-archive, application/vnd.ekstep.html-archive, application/vnd.android.package-archive, application/vnd.ekstep.content-archive, application/vnd.ekstep.content-collection, application/vnd.ekstep.plugin-archive, application/vnd.ekstep.h5p-archive, application/epub, text/x-url, video/x-youtube, application/octet-stream, application/msword, application/pdf, image/jpeg, image/jpg, image/png, image/tiff, image/bmp, image/gif, image/svg+xml, video/avi, video/mpeg, video/quicktime, video/3gpp, video/mp4, video/ogg, video/webm, audio/mp3, audio/mp4, audio/mpeg, audio/ogg, audio/webm, audio/x-wav, audio/wav, application/json, application/quiz]\"": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Bad Request\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 69 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Metadata mimeType should be one of: [application/vnd.ekstep.ecml-archive, application/vnd.ekstep.html-archive, application/vnd.android.package-archive, application/vnd.ekstep.content-archive, application/vnd.ekstep.content-collection, application/vnd.ekstep.plugin-archive, application/vnd.ekstep.h5p-archive, application/epub, text/x-url, video/x-youtube, application/octet-stream, application/msword, application/pdf, image/jpeg, image/jpg, image/png, image/tiff, image/bmp, image/gif, image/svg+xml, video/avi, video/mpeg, video/quicktime, video/3gpp, video/mp4, video/ogg, video/webm, audio/mp3, audio/mp4, audio/mpeg, audio/ogg, audio/webm, audio/x-wav, audio/wav, application/json, application/quiz]\"": true, + "Status code name has string \"Bad Request\"": true + } + ] + }, + { + "id": "174eb09b-0d2d-4ef4-9109-e74e75472d28", + "name": "400 - missing primaryCategory", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 48, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"VALIDATION_ERROR\"": true, + "params.errmsg should be \"primaryCategory is a mandatory parameter\"": true, + "result body should be empty": true, + "Status code name has string \"Bad Request\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"VALIDATION_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"primaryCategory is a mandatory parameter\"": { + "pass": 1, + "fail": 0 + }, + "result body should be empty": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Bad Request\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 48 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"VALIDATION_ERROR\"": true, + "params.errmsg should be \"primaryCategory is a mandatory parameter\"": true, + "result body should be empty": true, + "Status code name has string \"Bad Request\"": true + } + ] + }, + { + "id": "136c3218-e05b-418e-886a-d10129c996ba", + "name": "400 - Invalid subject", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 50, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors.\"": true, + "result body should include messages \"subject range data is empty from the given framework.\"": true, + "Status code name has string \"Bad Request\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Validation Errors.\"": { + "pass": 1, + "fail": 0 + }, + "result body should include messages \"subject range data is empty from the given framework.\"": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Bad Request\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 50 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors.\"": true, + "result body should include messages \"subject range data is empty from the given framework.\"": true, + "Status code name has string \"Bad Request\"": true + } + ] + }, + { + "id": "c4a3ef78-c5f3-4a82-ac3e-88ba8e2cc4b3", + "name": "404 - Invalid primaryCategory", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/create", + "time": 75, + "responseCode": { + "code": 404, + "name": "Not Found" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 404": true, + "Verify keys and data type of the response result": true, + "responseCode should be RESOURCE_NOT_FOUND": true, + "params.err should be \"404\"": true, + "params.errmsg should be \"Entry is not found in cassandra for content with identifier: obj-cat:aabaa_content_all {}\"": true, + "messages should be null": true, + "Status code name has string \"Not Found\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.create": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 404": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be RESOURCE_NOT_FOUND": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"404\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Entry is not found in cassandra for content with identifier: obj-cat:aabaa_content_all {}\"": { + "pass": 1, + "fail": 0 + }, + "messages should be null": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Not Found\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 75 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.create": true, + "ver should be 4.0": true, + "Status code is 404": true, + "Verify keys and data type of the response result": true, + "responseCode should be RESOURCE_NOT_FOUND": true, + "params.err should be \"404\"": true, + "params.errmsg should be \"Entry is not found in cassandra for content with identifier: obj-cat:aabaa_content_all {}\"": true, + "messages should be null": true, + "Status code name has string \"Not Found\"": true + } + ] + }, + { + "id": "59f831d2-df67-4297-9641-2304cea74637", + "name": "404 - Not Found", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/read/do_42353245436534", + "time": 65, + "responseCode": { + "code": 404, + "name": "Not Found" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 404": true, + "Test data type of the response and keys": true, + "id should be api.content.read": true, + "ver should be 4.0": true, + "responseCode should be RESOURCE_NOT_FOUND": true, + "params.err should be \"NOT_FOUND\"": true, + "params.errmsg should be \"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_42353245436534\"": true, + "messages should be null": true, + "Status code name has string \"Not Found\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 404": { + "pass": 1, + "fail": 0 + }, + "Test data type of the response and keys": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.read": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "responseCode should be RESOURCE_NOT_FOUND": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"NOT_FOUND\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_42353245436534\"": { + "pass": 1, + "fail": 0 + }, + "messages should be null": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Not Found\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 65 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 404": true, + "Test data type of the response and keys": true, + "id should be api.content.read": true, + "ver should be 4.0": true, + "responseCode should be RESOURCE_NOT_FOUND": true, + "params.err should be \"NOT_FOUND\"": true, + "params.errmsg should be \"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_42353245436534\"": true, + "messages should be null": true, + "Status code name has string \"Not Found\"": true + } + ] + }, + { + "id": "8be3bf77-e65e-4dab-9053-cf7400fd5aa5", + "name": "400 - Invalid versionKey", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/update/do_2135897074718965761132", + "time": 77, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.update": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Content-Encoding header should not present": true, + "Verify keys and data type of the response result": true, + "responseCode should be CLIENT_ERROR": true, + "params.err should be CLIENT_ERROR": true, + "params.status should be failed": true, + "params.errmsg should be \"Invalid version Key\"": true, + "messages should be null": true, + "Status code name has string Bad Request": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.update": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Content-Encoding header should not present": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be CLIENT_ERROR": { + "pass": 1, + "fail": 0 + }, + "params.err should be CLIENT_ERROR": { + "pass": 1, + "fail": 0 + }, + "params.status should be failed": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Invalid version Key\"": { + "pass": 1, + "fail": 0 + }, + "messages should be null": { + "pass": 1, + "fail": 0 + }, + "Status code name has string Bad Request": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 77 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.update": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Content-Encoding header should not present": true, + "Verify keys and data type of the response result": true, + "responseCode should be CLIENT_ERROR": true, + "params.err should be CLIENT_ERROR": true, + "params.status should be failed": true, + "params.errmsg should be \"Invalid version Key\"": true, + "messages should be null": true, + "Status code name has string Bad Request": true + } + ] + }, + { + "id": "d705cd83-e917-4be6-a755-e9c7d377c9c6", + "name": "400 - Empty name", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/update/do_2135897074718965761132", + "time": 42, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.update": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata name not set\"": true, + "Status code name has string \"Bad Request\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.update": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"CLIENT_ERROR\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Validation Errors\"": { + "pass": 1, + "fail": 0 + }, + "result body should include messages \"Required Metadata name not set\"": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Bad Request\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 42 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.update": true, + "ver should be 4.0": true, + "Status code is 400": true, + "Verify keys and data type of the response result": true, + "responseCode should be \"CLIENT_ERROR\"": true, + "params.err should be \"CLIENT_ERROR\"": true, + "params.errmsg should be \"Validation Errors\"": true, + "result body should include messages \"Required Metadata name not set\"": true, + "Status code name has string \"Bad Request\"": true + } + ] + }, + { + "id": "13158c62-e311-458c-a9ef-fabe24c065f6", + "name": "404 - Invalid content id", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/update/do_21357909972698726412211", + "time": 36, + "responseCode": { + "code": 404, + "name": "Not Found" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.update": true, + "ver should be 4.0": true, + "Status code is 404": true, + "Verify keys and data type of the response result": true, + "responseCode should be RESOURCE_NOT_FOUND": true, + "params.err should be NOT_FOUND": true, + "params.errmsg should be \"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_21357909972698726412211\"": true, + "messages should be null": true, + "Status code name has string \"Not Found\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.update": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 404": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be RESOURCE_NOT_FOUND": { + "pass": 1, + "fail": 0 + }, + "params.err should be NOT_FOUND": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_21357909972698726412211\"": { + "pass": 1, + "fail": 0 + }, + "messages should be null": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Not Found\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 36 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.update": true, + "ver should be 4.0": true, + "Status code is 404": true, + "Verify keys and data type of the response result": true, + "responseCode should be RESOURCE_NOT_FOUND": true, + "params.err should be NOT_FOUND": true, + "params.errmsg should be \"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: do_21357909972698726412211\"": true, + "messages should be null": true, + "Status code name has string \"Not Found\"": true + } + ] + }, + { + "id": "d05ba7e2-041f-4a54-9370-e5ecfd286a62", + "name": "404 - Invalid primaryCategory", + "url": "https://dev.knowlg.sunbird.org/api/content/v2/update/do_2135897074718965761132", + "time": 109, + "responseCode": { + "code": 404, + "name": "Not Found" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.update": true, + "ver should be 4.0": true, + "Status code is 404": true, + "Verify keys and data type of the response result": true, + "responseCode should be RESOURCE_NOT_FOUND": true, + "params.err should be \"404\"": true, + "params.errmsg should be \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"": true, + "messages should be null": true, + "Status code name has string \"Not Found\"": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "id should be api.content.update": { + "pass": 1, + "fail": 0 + }, + "ver should be 4.0": { + "pass": 1, + "fail": 0 + }, + "Status code is 404": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the response result": { + "pass": 1, + "fail": 0 + }, + "responseCode should be RESOURCE_NOT_FOUND": { + "pass": 1, + "fail": 0 + }, + "params.err should be \"404\"": { + "pass": 1, + "fail": 0 + }, + "params.errmsg should be \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"": { + "pass": 1, + "fail": 0 + }, + "messages should be null": { + "pass": 1, + "fail": 0 + }, + "Status code name has string \"Not Found\"": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 109 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "id should be api.content.update": true, + "ver should be 4.0": true, + "Status code is 404": true, + "Verify keys and data type of the response result": true, + "responseCode should be RESOURCE_NOT_FOUND": true, + "params.err should be \"404\"": true, + "params.errmsg should be \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"": true, + "messages should be null": true, + "Status code name has string \"Not Found\"": true + } + ] + } + ], + "count": 1, + "totalTime": 2695, + "collection": { + "requests": [ + { + "id": "2383265f-a48f-47dc-9538-e3c7a16b1d98", + "method": "POST" + }, + { + "id": "fdb1f5bc-f5b3-4c3c-b622-bd86a8f92b40", + "method": "POST" + }, + { + "id": "67644d61-7797-4f54-82cf-d4b7711b5282", + "method": "POST" + }, + { + "id": "4fa811d0-1e33-493c-95fe-39bac77bae42", + "method": "POST" + }, + { + "id": "5f38fbf3-1dd6-4f5a-8796-6ca07d837d25", + "method": "GET" + }, + { + "id": "6cad6c08-f73b-4d00-9395-b8cbcb3cafe0", + "method": "GET" + }, + { + "id": "bcd0f26d-ca6b-4eb7-815a-e85c4044a829", + "method": "PATCH" + }, + { + "id": "1d43c4ab-ea8b-449c-8dca-aa7eda247bfa", + "method": "PATCH" + }, + { + "id": "6d2a8074-8afe-40ba-9e29-2376fc3db053", + "method": "POST" + }, + { + "id": "59690e87-ff4d-4d1d-b549-0156afa7611b", + "method": "POST" + }, + { + "id": "dd956c1e-35b6-4525-baaf-0b2a8ab5ab57", + "method": "POST" + }, + { + "id": "c6c1b7fd-a278-4ef3-9d2e-6c76a53d1c33", + "method": "POST" + }, + { + "id": "a1ac9342-84c0-4395-aa52-b8248007722d", + "method": "POST" + }, + { + "id": "37e04040-1676-4dca-a674-54210b5990e2", + "method": "POST" + }, + { + "id": "077b803b-7fbb-4264-823c-c41c0bac597d", + "method": "POST" + }, + { + "id": "6a365695-00de-4d90-ab6f-4726e59b1898", + "method": "POST" + }, + { + "id": "174eb09b-0d2d-4ef4-9109-e74e75472d28", + "method": "POST" + }, + { + "id": "136c3218-e05b-418e-886a-d10129c996ba", + "method": "POST" + }, + { + "id": "c4a3ef78-c5f3-4a82-ac3e-88ba8e2cc4b3", + "method": "POST" + }, + { + "id": "59f831d2-df67-4297-9641-2304cea74637", + "method": "GET" + }, + { + "id": "8be3bf77-e65e-4dab-9053-cf7400fd5aa5", + "method": "PATCH" + }, + { + "id": "d705cd83-e917-4be6-a755-e9c7d377c9c6", + "method": "PATCH" + }, + { + "id": "13158c62-e311-458c-a9ef-fabe24c065f6", + "method": "PATCH" + }, + { + "id": "d05ba7e2-041f-4a54-9370-e5ecfd286a62", + "method": "PATCH" + } + ] + } +} \ No newline at end of file From a047461eae5f4ebf0396e9165842cc5e87ec3321 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 27 Jul 2022 12:19:50 +0530 Subject: [PATCH 057/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../src/main/scala/org/sunbird/content/dial/DIALManager.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index acbda5f8a..6af548049 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -392,7 +392,6 @@ object DIALManager { def getDIALReserveUpdateResponse(response: Response, count: Integer, contentId: String, node: Node): Response = { response.getResult.put(DIALConstants.COUNT, count) response.getResult.put(ContentConstants.NODE_ID, contentId) - response.getResult.put(DIALConstants.PROCESS_ID, node.getMetadata.get(DIALConstants.PROCESS_ID)) response.getResult.put(DIALConstants.RESERVED_DIALCODES, node.getMetadata.get(DIALConstants.RESERVED_DIALCODES)) response From 06aeee1c9951dec783f85daf98fc3b35b5ddafb0 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 29 Jul 2022 11:19:37 +0530 Subject: [PATCH 058/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../org/sunbird/content/dial/DIALManager.scala | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 6af548049..ab2b7405b 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -10,6 +10,7 @@ import org.sunbird.graph.dac.model.Node import org.sunbird.graph.nodes.DataNode import org.sunbird.graph.utils.ScalaJsonUtils import org.sunbird.managers.HierarchyManager +import org.sunbird.telemetry.logger.TelemetryManager import java.util import scala.collection.JavaConverters._ @@ -273,6 +274,7 @@ object DIALManager { } def reserve(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { + TelemetryManager.log("DIALManager:: reserve") val channelId: String = request.getContext.getOrDefault(DIALConstants.CHANNEL, "").asInstanceOf[String] val contentId: String = request.get(ContentConstants.IDENTIFIER).asInstanceOf[String] @@ -285,15 +287,15 @@ object DIALManager { req.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) DataNode.read(req).flatMap(rootNode => { val contentMetadata = rootNode.getMetadata - + TelemetryManager.log("DIALManager:: reserve:: contentMetadata: " + contentMetadata) validateChannel(contentMetadata.get(DIALConstants.CHANNEL).asInstanceOf[String], channelId) validateContentForReservedDialcodes(contentMetadata) validateCountForReservingDialCode(request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]]) validateContentStatus(contentMetadata) - + TelemetryManager.log("DIALManager:: reserve:: post validation: ") val reservedDialCodes = contentMetadata.getOrDefault(DIALConstants.DIALCODES, Map.empty[String, Integer]).asInstanceOf[Map[String, Integer]] val updateDialCodes = getUpdateDIALCodes(reservedDialCodes, request, channelId, contentId) - + TelemetryManager.log("DIALManager:: reserve:: updateDialCodes: " + updateDialCodes) if(updateDialCodes.size > reservedDialCodes.size) { val updateReq = getDIALReserveUpdateRequest(req, request, rootNode, updateDialCodes) DataNode.update(updateReq).map(updatedNode => { @@ -378,14 +380,8 @@ object DIALManager { updateReq.setContext(request.getContext) updateReq.getContext.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) - val rootNodeMetadata = rootNode.getMetadata - rootNodeMetadata.remove(DIALConstants.DISCUSSION_FORUM) - rootNodeMetadata.remove(DIALConstants.CREDENTIALS) - rootNodeMetadata.remove(DIALConstants.TRACKABLE) - + updateReq.put(DIALConstants.VERSION_KEY,rootNode.getMetadata.get("versionKey")) updateReq.put(DIALConstants.RESERVED_DIALCODES, updateDialCodes.asJava) - updateReq.getRequest.putAll(rootNodeMetadata) - updateReq } From 4d615690b0df4e2701a4d3ea3d0b438203a72c43 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 29 Jul 2022 11:22:57 +0530 Subject: [PATCH 059/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../main/scala/org/sunbird/content/dial/DIALManager.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index ab2b7405b..2bc4073fd 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -287,15 +287,15 @@ object DIALManager { req.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) DataNode.read(req).flatMap(rootNode => { val contentMetadata = rootNode.getMetadata - TelemetryManager.log("DIALManager:: reserve:: contentMetadata: " + contentMetadata) + validateChannel(contentMetadata.get(DIALConstants.CHANNEL).asInstanceOf[String], channelId) validateContentForReservedDialcodes(contentMetadata) validateCountForReservingDialCode(request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]]) validateContentStatus(contentMetadata) - TelemetryManager.log("DIALManager:: reserve:: post validation: ") + val reservedDialCodes = contentMetadata.getOrDefault(DIALConstants.DIALCODES, Map.empty[String, Integer]).asInstanceOf[Map[String, Integer]] val updateDialCodes = getUpdateDIALCodes(reservedDialCodes, request, channelId, contentId) - TelemetryManager.log("DIALManager:: reserve:: updateDialCodes: " + updateDialCodes) + if(updateDialCodes.size > reservedDialCodes.size) { val updateReq = getDIALReserveUpdateRequest(req, request, rootNode, updateDialCodes) DataNode.update(updateReq).map(updatedNode => { From ed4c4f6772e2328d7cbd9156ac023e80489c8384 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 29 Jul 2022 11:26:08 +0530 Subject: [PATCH 060/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../src/main/scala/org/sunbird/content/dial/DIALManager.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 2bc4073fd..430a91fd4 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -274,7 +274,6 @@ object DIALManager { } def reserve(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - TelemetryManager.log("DIALManager:: reserve") val channelId: String = request.getContext.getOrDefault(DIALConstants.CHANNEL, "").asInstanceOf[String] val contentId: String = request.get(ContentConstants.IDENTIFIER).asInstanceOf[String] From 2d23d69931a6b8f63a6095abd1e344575c829e64 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 29 Jul 2022 11:26:49 +0530 Subject: [PATCH 061/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../src/main/scala/org/sunbird/content/dial/DIALManager.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 430a91fd4..9179f10bf 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -10,7 +10,6 @@ import org.sunbird.graph.dac.model.Node import org.sunbird.graph.nodes.DataNode import org.sunbird.graph.utils.ScalaJsonUtils import org.sunbird.managers.HierarchyManager -import org.sunbird.telemetry.logger.TelemetryManager import java.util import scala.collection.JavaConverters._ From 08133c31f22a0359335c2a87f08fda849f7aa252 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 29 Jul 2022 17:15:48 +0530 Subject: [PATCH 062/105] Issue #SB-28316 feat: DIAL code reserve API refactor. --- .../src/main/scala/org/sunbird/content/dial/DIALManager.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 9179f10bf..8fc4cb598 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -291,7 +291,7 @@ object DIALManager { validateCountForReservingDialCode(request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]]) validateContentStatus(contentMetadata) - val reservedDialCodes = contentMetadata.getOrDefault(DIALConstants.DIALCODES, Map.empty[String, Integer]).asInstanceOf[Map[String, Integer]] + val reservedDialCodes = if(contentMetadata.containsKey(DIALConstants.RESERVED_DIALCODES)) ScalaJsonUtils.deserialize[Map[String, Integer]](contentMetadata.get(DIALConstants.RESERVED_DIALCODES).asInstanceOf[String]) else Map.empty[String, Integer] val updateDialCodes = getUpdateDIALCodes(reservedDialCodes, request, channelId, contentId) if(updateDialCodes.size > reservedDialCodes.size) { From bf15edcd5f6a49ff0d0e622aeee7b1b45b145ca4 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 2 Aug 2022 16:10:04 +0530 Subject: [PATCH 063/105] Issue #SB-30154 feat: DIAL code link API refactor. --- .../scala/org/sunbird/content/dial/DIALManager.scala | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 8fc4cb598..fa7385d17 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -175,21 +175,13 @@ object DIALManager { def getLinkUpdateRequest(req: Request, rootNode: Node, requestMap: Map[String, List[String]], objectId: String): Request = { val updateReq = new Request(req) updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) - val rootNodeMetadata = rootNode.getMetadata - rootNodeMetadata.remove(DIALConstants.DISCUSSION_FORUM) - rootNodeMetadata.remove(DIALConstants.CREDENTIALS) - rootNodeMetadata.remove(DIALConstants.TRACKABLE) - rootNodeMetadata.remove(DIALConstants.RESERVED_DIALCODES) - - if(rootNodeMetadata.containsKey(DIALConstants.DIALCODES)) - rootNodeMetadata.remove(DIALConstants.DIALCODES) + updateReq.put(DIALConstants.VERSION_KEY,rootNode.getMetadata.get("versionKey")) if(requestMap(objectId).isEmpty) updateReq.put(DIALConstants.DIALCODES, null) else updateReq.put(DIALConstants.DIALCODES, requestMap(objectId).toArray[String]) - updateReq.getRequest.putAll(rootNodeMetadata) updateReq } From c1371c10b4a9ddce1d60325309e8149bef768719 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 5 Aug 2022 17:42:08 +0530 Subject: [PATCH 064/105] Issue #KN-9 feat: Content Publish API refactor. --- .../sunbird/content/actors/ContentActor.scala | 22 +++++ .../content/publish/mgr/PublishManager.scala | 91 +++++++++++++++++++ .../content/util/ContentConstants.scala | 15 +++ .../src/test/resources/application.conf | 1 + .../controllers/v3/ContentController.scala | 30 ++++-- .../controllers/v4/CollectionController.scala | 24 +++++ .../controllers/v4/ContentController.scala | 24 +++++ .../app/controllers/v4/EventController.scala | 2 +- .../controllers/v4/EventSetController.scala | 2 +- .../content-service/app/utils/ApiId.scala | 1 + .../content-service/conf/application.conf | 1 + content-api/content-service/conf/routes | 7 +- .../mimetype/mgr/BaseMimeTypeManager.scala | 4 + .../mimetype/mgr/MimeTypeManager.scala | 3 + .../mgr/impl/ApkMimeTypeMgrImpl.scala | 4 + .../mgr/impl/AssetMimeTypeMgrImpl.scala | 3 + .../mgr/impl/CollectionMimeTypeMgrImpl.scala | 4 + .../mgr/impl/DefaultMimeTypeMgrImpl.scala | 5 + .../mgr/impl/DocumentMimeTypeMgrImpl.scala | 4 + .../mgr/impl/EcmlMimeTypeMgrImpl.scala | 8 ++ .../mgr/impl/H5PMimeTypeMgrImpl.scala | 5 + .../mgr/impl/HtmlMimeTypeMgrImpl.scala | 6 ++ .../mgr/impl/PluginMimeTypeMgrImpl.scala | 6 ++ .../mgr/impl/YouTubeMimeTypeMgrImpl.scala | 8 ++ 24 files changed, 267 insertions(+), 13 deletions(-) create mode 100644 content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala index e3925113f..c6e5d2fa4 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala @@ -4,6 +4,7 @@ import java.util import java.util.concurrent.CompletionException import java.io.File import org.apache.commons.io.FilenameUtils + import javax.inject.Inject import org.apache.commons.lang3.StringUtils import org.sunbird.`object`.importer.{ImportConfig, ImportManager} @@ -15,6 +16,7 @@ import org.sunbird.common.{ContentParams, Platform, Slug} import org.sunbird.common.dto.{Request, Response, ResponseHandler} import org.sunbird.common.exception.ClientException import org.sunbird.content.dial.DIALManager +import org.sunbird.content.publish.mgr.PublishManager import org.sunbird.content.review.mgr.ReviewManager import org.sunbird.util.RequestUtil import org.sunbird.content.upload.mgr.UploadManager @@ -54,6 +56,7 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe case "systemUpdate" => systemUpdate(request) case "reviewContent" => reviewContent(request) case "rejectContent" => rejectContent(request) + case "publishContent" => publishContent(request) case _ => ERROR(request.getOperation) } } @@ -195,6 +198,25 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe }).flatMap(f => f) } + def publishContent(request: Request): Future[Response] = { + val identifier: String = request.getContext.getOrDefault("identifier", "").asInstanceOf[String] + val publisher: String = request.getRequest.getOrDefault("lastPublishedBy", "").asInstanceOf[String] + + if(publisher.isBlank) throw new ClientException("ERR_CONTENT_BLANK_PUBLISHER", "Publisher User Id is blank") + + val readReq = new Request(request) + readReq.put("identifier", identifier) + readReq.put("mode", "edit") + DataNode.read(readReq).map(node => { + if (null != node & StringUtils.isNotBlank(node.getObjectType)) + request.getContext.put("schemaName", node.getObjectType.toLowerCase()) + if (StringUtils.equalsAnyIgnoreCase("Processing", node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) + throw new ClientException("ERR_NODE_ACCESS_DENIED", "Publish Operation Can't Be Applied On Node Under Processing State") + node.getMetadata.put("lastPublishedBy", publisher) + PublishManager.publish(request, node) + }).flatMap(f => f) + } + def populateDefaultersForCreation(request: Request) = { setDefaultsBasedOnMimeType(request, ContentParams.create.name) setDefaultLicense(request) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala new file mode 100644 index 000000000..e365bb885 --- /dev/null +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala @@ -0,0 +1,91 @@ +package org.sunbird.content.publish.mgr + +import org.apache.commons.lang3.StringUtils +import org.sunbird.common.Platform +import org.sunbird.common.dto.ResponseParams.StatusType +import org.sunbird.common.dto.{Request, Response, ResponseParams} +import org.sunbird.common.exception.ClientException +import org.sunbird.content.util.ContentConstants +import org.sunbird.graph.OntologyEngineContext +import org.sunbird.graph.dac.model.Node +import org.sunbird.kafka.client.KafkaClient +import org.sunbird.mimetype.factory.MimeTypeManagerFactory +import org.sunbird.telemetry.util.LogTelemetryEventUtil + +import java.util +import scala.concurrent.{ExecutionContext, Future} + +object PublishManager { + + private val kfClient = new KafkaClient + + def publish(request: Request, node: Node)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { + val identifier: String = node.getIdentifier + val mimeType = node.getMetadata.getOrDefault(ContentConstants.MIME_TYPE, "").asInstanceOf[String] + val mgr = MimeTypeManagerFactory.getManager(node.getObjectType, mimeType) + + val publishCheckList = request.getContext.getOrDefault(ContentConstants.PUBLIC_CHECK_LIST, List.empty[String]).asInstanceOf[List[String]] + if (publishCheckList.isEmpty) node.getMetadata.put(ContentConstants.PUBLIC_CHECK_LIST, null) + + val publishType = request.getContext.getOrDefault(ContentConstants.PUBLISH_TYPE, "").asInstanceOf[String] + node.getMetadata.put(ContentConstants.PUBLISH_TYPE, publishType) + + val publishFuture: Future[scala.collection.Map[String, AnyRef]] = mgr.publish(identifier, node) + publishFuture.map(result => { + // Push Instruction Event - Learning code has logic to send publish instruction to different topics based on mimeTypes. That logic is not implemented here due to deprecation of samza jobs. + pushInstructionEvent(identifier, node) + + val response = new Response + val param = new ResponseParams + param.setStatus(StatusType.successful.name) + response.setParams(param) + response.put(ContentConstants.PUBLISH_STATUS, "Publish Event for Content Id '" + node.getIdentifier + "' is pushed Successfully!") + response.put(ContentConstants.NODE_ID, node.getIdentifier) + + Future(response) + }).flatMap(f => f) + } + + @throws[Exception] + private def pushInstructionEvent(identifier: String, node: Node): Unit = { + val actor: util.Map[String, AnyRef] = new util.HashMap[String, AnyRef] + val context: util.Map[String, AnyRef] = new util.HashMap[String, AnyRef] + val objectData: util.Map[String, AnyRef] = new util.HashMap[String, AnyRef] + val edata: util.Map[String, AnyRef] = new util.HashMap[String, AnyRef] + generateInstructionEventMetadata(actor, context, objectData, edata, node, identifier) + val beJobRequestEvent: String = LogTelemetryEventUtil.logInstructionEvent(actor, context, objectData, edata) + val topic: String = Platform.getString(ContentConstants.KAFKA_PUBLISH_TOPIC,"sunbirddev.publish.job.request") + if (StringUtils.isBlank(beJobRequestEvent)) throw new ClientException("BE_JOB_REQUEST_EXCEPTION", "Event is not generated properly.") + kfClient.send(beJobRequestEvent, topic) + } + + private def generateInstructionEventMetadata(actor: util.Map[String, AnyRef], context: util.Map[String, AnyRef], objectData: util.Map[String, AnyRef], edata: util.Map[String, AnyRef], node: Node, identifier: String): Unit = { + val metadata: util.Map[String, AnyRef] = node.getMetadata + val instructionEventMetadata = new util.HashMap[String, AnyRef] + + actor.put(ContentConstants.ID, node.getObjectType.toLowerCase() + "-publish") + actor.put(ContentConstants.TYPE, ContentConstants.SYSTEM) + context.put(ContentConstants.CHANNEL, metadata.get(ContentConstants.CHANNEL)) + context.put(ContentConstants.P_DATA, new util.HashMap[String, AnyRef]() {{ + put(ContentConstants.ID, ContentConstants.SUNBIRD_PLATFORM) + put(ContentConstants.VER, ContentConstants.SCHEMA_VERSION) + }}) + if (Platform.config.hasPath("cloud_storage.env")) { + val env: String = Platform.getString("cloud_storage.env", "dev") + context.put(ContentConstants.ENV, env) + } + objectData.put(ContentConstants.ID, identifier) + objectData.put(ContentConstants.VER, metadata.get(ContentConstants.VERSION_KEY)) + edata.put(ContentConstants.PUBLISH_TYPE, metadata.get(ContentConstants.PUBLISH_TYPE)) + instructionEventMetadata.put(ContentConstants.PACKAGE_VERSION, metadata.getOrDefault(ContentConstants.PACKAGE_VERSION,0.asInstanceOf[AnyRef])) + instructionEventMetadata.put(ContentConstants.MIME_TYPE, metadata.get(ContentConstants.MIME_TYPE)) + instructionEventMetadata.put(ContentConstants.LAST_PUBLISHED_BY, metadata.get(ContentConstants.LAST_PUBLISHED_BY)) + instructionEventMetadata.put(ContentConstants.IDENTIFIER, identifier) + instructionEventMetadata.put(ContentConstants.OBJECT_TYPE, node.getObjectType) + edata.put(ContentConstants.METADATA, instructionEventMetadata) + edata.put(ContentConstants.ACTION, ContentConstants.PUBLISH) + edata.put(ContentConstants.CONTENT_TYPE, metadata.get(ContentConstants.CONTENT_TYPE)) + } +} + + diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala index 622011222..070fb692e 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala @@ -59,4 +59,19 @@ object ContentConstants { val PARENT: String = "Parent" val BEARER: String = "Bearer " val OK_RESPONSE_CODE: String = "OK" + val PUBLIC_CHECK_LIST: String = "publishChecklist" + val PUBLISH_TYPE: String = "publish_type" + val PUBLISH_STATUS: String = "publishStatus" + val ID: String = "id" + val TYPE: String = "type" + val SYSTEM: String = "System" + val P_DATA: String = "pdata" + val SUNBIRD_PLATFORM: String = "org.sunbird.platform" + val VER: String = "ver" + val LAST_PUBLISHED_BY: String = "lastPublishedBy" + val OBJECT_TYPE: String = "objectType" + val ACTION: String = "action" + val PUBLISH: String = "publish" + val ENV: String = "env" + val KAFKA_PUBLISH_TOPIC = "kafka.publish.request.topic" } diff --git a/content-api/content-actors/src/test/resources/application.conf b/content-api/content-actors/src/test/resources/application.conf index 837e732ba..bacdabc13 100644 --- a/content-api/content-actors/src/test/resources/application.conf +++ b/content-api/content-actors/src/test/resources/application.conf @@ -394,6 +394,7 @@ channel.fetch.suggested_frameworks=true # Kafka configuration details kafka.topics.instruction="local.learning.job.request" +kafka.publish.request.topic = "local.publish.job.request" kafka.urls="localhost:9092" #Youtube Standard Licence Validation diff --git a/content-api/content-service/app/controllers/v3/ContentController.scala b/content-api/content-service/app/controllers/v3/ContentController.scala index ab3538098..ee6c425f5 100644 --- a/content-api/content-service/app/controllers/v3/ContentController.scala +++ b/content-api/content-service/app/controllers/v3/ContentController.scala @@ -148,9 +148,27 @@ class ContentController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentActor: } def publish(identifier: String) = Action.async { implicit request => - val result = ResponseHandler.OK() - val response = JavaJsonUtils.serialize(result) - Future(Ok(response).as("application/json")) + val headers = commonHeaders() + val body = requestBody() + val content = body.getOrDefault("content", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; + content.putAll(headers) + val contentRequest = getRequest(content, headers, "publishContent") + setRequestContext(contentRequest, version, objectType, schemaName) + contentRequest.getContext.put("identifier", identifier); + contentRequest.getContext.put("publish_type", "public"); + getResult(ApiId.PUBLISH_CONTENT, contentActor, contentRequest) + } + + def publishUnlisted(identifier: String) = Action.async { implicit request => + val headers = commonHeaders() + val body = requestBody() + val content = body.getOrDefault("content", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; + content.putAll(headers) + val contentRequest = getRequest(content, headers, "publishContent") + setRequestContext(contentRequest, version, objectType, schemaName) + contentRequest.getContext.put("identifier", identifier); + contentRequest.getContext.put("publish_type", "unlisted"); + getResult(ApiId.PUBLISH_CONTENT, contentActor, contentRequest) } def review(identifier: String) = Action.async { implicit request => @@ -221,12 +239,6 @@ class ContentController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentActor: Future(Ok(response).as("application/json")) } - def publishUnlisted(identifier: String) = Action.async { implicit request => - val result = ResponseHandler.OK() - val response = JavaJsonUtils.serialize(result) - Future(Ok(response).as("application/json")) - } - def upload(identifier: String, fileFormat: Option[String], validation: Option[String]) = Action.async { implicit request => val headers = commonHeaders() val content = requestFormData(identifier) diff --git a/content-api/content-service/app/controllers/v4/CollectionController.scala b/content-api/content-service/app/controllers/v4/CollectionController.scala index 4dfd17829..34d5ba35a 100644 --- a/content-api/content-service/app/controllers/v4/CollectionController.scala +++ b/content-api/content-service/app/controllers/v4/CollectionController.scala @@ -264,5 +264,29 @@ class CollectionController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentAc getResult(ApiId.REVIEW_COLLECTION, contentActor, contentRequest, version = apiVersion) } + def publish(identifier: String) = Action.async { implicit request => + val headers = commonHeaders() + val body = requestBody() + val content = body.getOrDefault("content", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; + content.putAll(headers) + val contentRequest = getRequest(content, headers, "publishContent") + setRequestContext(contentRequest, version, objectType, schemaName) + contentRequest.getContext.put("identifier", identifier); + contentRequest.getContext.put("publish_type", "public"); + getResult(ApiId.PUBLISH_CONTENT, contentActor, contentRequest) + } + + def publishUnlisted(identifier: String) = Action.async { implicit request => + val headers = commonHeaders() + val body = requestBody() + val content = body.getOrDefault("content", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; + content.putAll(headers) + val contentRequest = getRequest(content, headers, "publishContent") + setRequestContext(contentRequest, version, objectType, schemaName) + contentRequest.getContext.put("identifier", identifier); + contentRequest.getContext.put("publish_type", "unlisted"); + getResult(ApiId.PUBLISH_CONTENT, contentActor, contentRequest) + } + } diff --git a/content-api/content-service/app/controllers/v4/ContentController.scala b/content-api/content-service/app/controllers/v4/ContentController.scala index f5a25d0fe..98594df34 100644 --- a/content-api/content-service/app/controllers/v4/ContentController.scala +++ b/content-api/content-service/app/controllers/v4/ContentController.scala @@ -218,4 +218,28 @@ class ContentController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentActor: getResult(ApiId.REJECT_CONTENT, contentActor, contentRequest, version = apiVersion) } + def publish(identifier: String) = Action.async { implicit request => + val headers = commonHeaders() + val body = requestBody() + val content = body.getOrDefault("content", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; + content.putAll(headers) + val contentRequest = getRequest(content, headers, "publishContent") + setRequestContext(contentRequest, version, objectType, schemaName) + contentRequest.getContext.put("identifier", identifier); + contentRequest.getContext.put("publish_type", "public"); + getResult(ApiId.PUBLISH_CONTENT, contentActor, contentRequest) + } + + def publishUnlisted(identifier: String) = Action.async { implicit request => + val headers = commonHeaders() + val body = requestBody() + val content = body.getOrDefault("content", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]]; + content.putAll(headers) + val contentRequest = getRequest(content, headers, "publishContent") + setRequestContext(contentRequest, version, objectType, schemaName) + contentRequest.getContext.put("identifier", identifier); + contentRequest.getContext.put("publish_type", "unlisted"); + getResult(ApiId.PUBLISH_CONTENT, contentActor, contentRequest) + } + } diff --git a/content-api/content-service/app/controllers/v4/EventController.scala b/content-api/content-service/app/controllers/v4/EventController.scala index 3b609d32b..1c5f2cc86 100644 --- a/content-api/content-service/app/controllers/v4/EventController.scala +++ b/content-api/content-service/app/controllers/v4/EventController.scala @@ -55,7 +55,7 @@ class EventController @Inject()(@Named(ActorNames.EVENT_ACTOR) eventActor: Actor } } - def publish(identifier: String): Action[AnyContent] = Action.async { implicit request => + override def publish(identifier: String): Action[AnyContent] = Action.async { implicit request => val headers = commonHeaders() val content = new java.util.HashMap[String, Object]() content.put("status", "Live") diff --git a/content-api/content-service/app/controllers/v4/EventSetController.scala b/content-api/content-service/app/controllers/v4/EventSetController.scala index e6729fae4..c1dd509c3 100644 --- a/content-api/content-service/app/controllers/v4/EventSetController.scala +++ b/content-api/content-service/app/controllers/v4/EventSetController.scala @@ -64,7 +64,7 @@ class EventSetController @Inject()(@Named(ActorNames.EVENT_SET_ACTOR) eventSetAc } } - def publish(identifier: String): Action[AnyContent] = Action.async { implicit request => + override def publish(identifier: String): Action[AnyContent] = Action.async { implicit request => val headers = commonHeaders() val content = new java.util.HashMap[String, Object]() content.put("identifier", identifier) diff --git a/content-api/content-service/app/utils/ApiId.scala b/content-api/content-service/app/utils/ApiId.scala index 8b5afe44f..804aa87c6 100644 --- a/content-api/content-service/app/utils/ApiId.scala +++ b/content-api/content-service/app/utils/ApiId.scala @@ -22,6 +22,7 @@ object ApiId { val SYSTEM_UPDATE_CONTENT = "api.content.system.update" val REVIEW_CONTENT = "api.content.review" val REJECT_CONTENT = "api.content.review.reject" + val PUBLISH_CONTENT = "api.content.publish" // Collection APIs val ADD_HIERARCHY = "api.content.hierarchy.add" diff --git a/content-api/content-service/conf/application.conf b/content-api/content-service/conf/application.conf index b969a73eb..910dd9406 100644 --- a/content-api/content-service/conf/application.conf +++ b/content-api/content-service/conf/application.conf @@ -595,6 +595,7 @@ channel.fetch.suggested_frameworks=true content.h5p.library.path="https://s3.ap-south-1.amazonaws.com/ekstep-public-prod/content/templates/h5p-library-v2.zip" kafka.topics.graph.event="sunbirddev.learning.graph.events" +kafka.publish.request.topic = "sunbirddev.publish.job.request" content.discard.status=["Draft","FlagDraft"] content.discard.remove_publish_data=["compatibilityLevel", "lastPublishedOn", "pkgVersion", "leafNodesCount", "downloadUrl", "variants"] diff --git a/content-api/content-service/conf/routes b/content-api/content-service/conf/routes index 17b4e3059..baad416e0 100644 --- a/content-api/content-service/conf/routes +++ b/content-api/content-service/conf/routes @@ -20,7 +20,6 @@ POST /content/v3/bundle controllers.v3.ContentController POST /content/v3/flag/accept/:identifier controllers.v3.ContentController.acceptFlag(identifier:String) POST /content/v3/flag/reject/:identifier controllers.v3.ContentController.rejectFlag(identifier:String) POST /content/v3/publish/:identifier controllers.v3.ContentController.publish(identifier:String) -POST /content/v3/public/publish/:identifier controllers.v3.ContentController.publish(identifier:String) POST /content/v3/review/:identifier controllers.v3.ContentController.review(identifier:String) DELETE /content/v3/discard/:identifier controllers.v3.ContentController.discard(identifier:String) DELETE /content/v3/retire/:identifier controllers.v3.ContentController.retire(identifier:String) @@ -80,7 +79,9 @@ GET /collection/v4/hierarchy/:identifier/:bookmarkId controllers.v4.Coll POST /collection/v4/dialcode/link/:identifier controllers.v4.CollectionController.collectionLinkDialCode(identifier:String) POST /collection/v4/copy/:identifier controllers.v4.CollectionController.copy(identifier:String, mode:Option[String], type:String ?= "deep") PATCH /collection/v4/system/update/:identifier controllers.v4.CollectionController.systemUpdate(identifier:String) -POST /collection/v4/reject/:identifier controllers.v4.CollectionController.reviewReject(identifier:String) +POST /collection/v4/reject/:identifier controllers.v4.CollectionController.reviewReject(identifier:String) +POST /collection/v4/publish/:identifier controllers.v4.CollectionController.publish(identifier:String) +POST /collection/v4/unlisted/publish/:identifier controllers.v4.CollectionController.publishUnlisted(identifier:String) # Content v4 APIs POST /content/v4/create controllers.v4.ContentController.create @@ -100,6 +101,8 @@ PATCH /content/v4/system/update/:identifier controllers.v4.ContentControl POST /content/v4/review/:identifier controllers.v4.ContentController.review(identifier:String) POST /content/v4/reject/:identifier controllers.v4.ContentController.reviewReject(identifier:String) POST /content/v4/dialcode/reserve/:identifier controllers.v4.ContentController.reserveDialCode(identifier:String) +POST /content/v4/publish/:identifier controllers.v4.ContentController.publish(identifier:String) +POST /content/v4/unlisted/publish/:identifier controllers.v4.ContentController.publishUnlisted(identifier:String) # App v4 APIs POST /app/v4/register controllers.v4.AppController.register diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/BaseMimeTypeManager.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/BaseMimeTypeManager.scala index 0d53fdbf1..94f9d2368 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/BaseMimeTypeManager.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/BaseMimeTypeManager.scala @@ -289,5 +289,9 @@ class BaseMimeTypeManager(implicit ss: StorageService) { Map("lastSubmittedOn"-> DateUtils.formatCurrentDate(), "reviewError" -> null, "status" -> newStatus) } + def getEnrichedPublishMetadata(status: String): Map[String, AnyRef] = { + Map("lastPublishedOn"-> DateUtils.formatCurrentDate(), "rejectReasons" -> null, "rejectComment" -> null, "publishError" -> null, "importError" -> null) + } + } diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/MimeTypeManager.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/MimeTypeManager.scala index 3f3345074..5324fbe84 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/MimeTypeManager.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/MimeTypeManager.scala @@ -18,4 +18,7 @@ trait MimeTypeManager { @throws[Exception] def review(objectId: String, node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext): Future[Map[String, AnyRef]] + + @throws[Exception] + def publish(objectId: String, node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext): Future[Map[String, AnyRef]] } diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/ApkMimeTypeMgrImpl.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/ApkMimeTypeMgrImpl.scala index ff19edd12..67f39cbfe 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/ApkMimeTypeMgrImpl.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/ApkMimeTypeMgrImpl.scala @@ -34,4 +34,8 @@ class ApkMimeTypeMgrImpl(implicit ss: StorageService) extends BaseMimeTypeManage Future(getEnrichedMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) } + override def publish(objectId: String, node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext): Future[Map[String, AnyRef]] = { + validate(node, " |[APK file should be uploaded for further processing!]") + Future(getEnrichedPublishMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) + } } diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/AssetMimeTypeMgrImpl.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/AssetMimeTypeMgrImpl.scala index ab1f9055c..aebf4c9c8 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/AssetMimeTypeMgrImpl.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/AssetMimeTypeMgrImpl.scala @@ -38,4 +38,7 @@ class AssetMimeTypeMgrImpl(implicit ss: StorageService) extends BaseMimeTypeMana Future(getEnrichedMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) } + override def publish(objectId: String, node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext): Future[Map[String, AnyRef]] = { + Future(getEnrichedPublishMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) + } } diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/CollectionMimeTypeMgrImpl.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/CollectionMimeTypeMgrImpl.scala index 597e4201b..0f833977d 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/CollectionMimeTypeMgrImpl.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/CollectionMimeTypeMgrImpl.scala @@ -34,6 +34,10 @@ class CollectionMimeTypeMgrImpl(implicit ss: StorageService) extends BaseMimeTyp validate(node).map(res => getEnrichedMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) } + override def publish(objectId: String, node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext): Future[Map[String, AnyRef]] = { + validate(node).map(res => getEnrichedPublishMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) + } + def validate(node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext) = { val req = new Request() req.setContext(Map[String, AnyRef]("schemaName" -> node.getObjectType.toLowerCase.replaceAll("image", ""), "version"->"1.0").asJava) diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/DefaultMimeTypeMgrImpl.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/DefaultMimeTypeMgrImpl.scala index c9f47e256..3e2cc01cf 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/DefaultMimeTypeMgrImpl.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/DefaultMimeTypeMgrImpl.scala @@ -40,4 +40,9 @@ class DefaultMimeTypeMgrImpl(implicit ss: StorageService) extends BaseMimeTypeMa validate(node, " | [Either artifactUrl is missing or invalid!]") Future(getEnrichedMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) } + + override def publish(objectId: String, node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext): Future[Map[String, AnyRef]] = { + validate(node, " | [Either artifactUrl is missing or invalid!]") + Future(getEnrichedPublishMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) + } } diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/DocumentMimeTypeMgrImpl.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/DocumentMimeTypeMgrImpl.scala index 30442b670..e2ffe0612 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/DocumentMimeTypeMgrImpl.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/DocumentMimeTypeMgrImpl.scala @@ -92,4 +92,8 @@ class DocumentMimeTypeMgrImpl(implicit ss: StorageService) extends BaseMimeTypeM Future(getEnrichedMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) } + override def publish(objectId: String, node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext): Future[Map[String, AnyRef]] = { + validate(node, " | [Either artifactUrl is missing or invalid!]") + Future(getEnrichedPublishMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) + } } diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/EcmlMimeTypeMgrImpl.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/EcmlMimeTypeMgrImpl.scala index f44c3e0e5..773ca2842 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/EcmlMimeTypeMgrImpl.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/EcmlMimeTypeMgrImpl.scala @@ -108,6 +108,14 @@ class EcmlMimeTypeMgrImpl(implicit ss: StorageService) extends BaseMimeTypeManag }) } + override def publish(objectId: String, node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext): Future[Map[String, AnyRef]] = { + validate(node).map(result => { + if(result) { + getEnrichedPublishMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String]) + } else throw new ServerException("ERR_NODE_REVIEW", "Something Went Wrong While Applying Review On Node Having Identifier : "+objectId) + }) + } + def validate(node: Node)(implicit ec: ExecutionContext, oec: OntologyEngineContext): Future[Boolean] = { val artifactUrl = node.getMetadata.getOrDefault("artifactUrl", "").asInstanceOf[String] val req = new Request() diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/H5PMimeTypeMgrImpl.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/H5PMimeTypeMgrImpl.scala index bea9318f2..5cb004f48 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/H5PMimeTypeMgrImpl.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/H5PMimeTypeMgrImpl.scala @@ -91,4 +91,9 @@ class H5PMimeTypeMgrImpl(implicit ss: StorageService) extends BaseMimeTypeManage validate(node, "| [H5P file should be uploaded for further processing!]") Future(getEnrichedMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) } + + override def publish(objectId: String, node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext): Future[Map[String, AnyRef]] = { + validate(node, "| [H5P file should be uploaded for further processing!]") + Future(getEnrichedPublishMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) + } } diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/HtmlMimeTypeMgrImpl.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/HtmlMimeTypeMgrImpl.scala index 34014ebf3..4e3e35b57 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/HtmlMimeTypeMgrImpl.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/HtmlMimeTypeMgrImpl.scala @@ -42,4 +42,10 @@ class HtmlMimeTypeMgrImpl(implicit ss: StorageService) extends BaseMimeTypeManag validate(node, " | [HTML archive should be uploaded for further processing!]") Future(getEnrichedMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) } + + override def publish(objectId: String, node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext): Future[Map[String, AnyRef]] = { + validate(node, " | [HTML archive should be uploaded for further processing!]") + Future(getEnrichedPublishMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) + } + } diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/PluginMimeTypeMgrImpl.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/PluginMimeTypeMgrImpl.scala index ccda298b9..2fb9215e9 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/PluginMimeTypeMgrImpl.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/PluginMimeTypeMgrImpl.scala @@ -65,4 +65,10 @@ class PluginMimeTypeMgrImpl(implicit ss: StorageService) extends BaseMimeTypeMan throw new ClientException("VALIDATOR_ERROR", MISSING_REQUIRED_FIELDS + " | [Either artifactUrl is missing or invalid!]") Future(getEnrichedMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) } + + override def publish(objectId: String, node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext): Future[Map[String, AnyRef]] = { + if(!isValidArtifact(node)) + throw new ClientException("VALIDATOR_ERROR", MISSING_REQUIRED_FIELDS + " | [Either artifactUrl is missing or invalid!]") + Future(getEnrichedPublishMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) + } } diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/YouTubeMimeTypeMgrImpl.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/YouTubeMimeTypeMgrImpl.scala index 36c0e0015..82576823c 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/YouTubeMimeTypeMgrImpl.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/mimetype/mgr/impl/YouTubeMimeTypeMgrImpl.scala @@ -36,6 +36,14 @@ class YouTubeMimeTypeMgrImpl(implicit ss: StorageService) extends BaseMimeTypeMa Future(data ++ licenseData) } + override def publish(objectId: String, node: Node)(implicit ec: ExecutionContext, ontologyEngineContext: OntologyEngineContext): Future[Map[String, AnyRef]] = { + validate(node) + val license = node.getMetadata.getOrDefault("license", "").asInstanceOf[String] + val licenseData = if(StringUtils.isBlank(license)) validateAndGetLicense(node) else Map() + val data = getEnrichedPublishMetadata(node.getMetadata.getOrDefault("status", "").asInstanceOf[String]) + Future(data ++ licenseData) + } + def validate(node: Node): Unit = { if(isValidArtifact(node)) { val isValidYouTubeUrl = Pattern.matches(YOUTUBE_REGEX, node.getMetadata.get("artifactUrl").toString) From 71eb4585e0f1daf4976af55b6cebd600ac79ca98 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Mon, 8 Aug 2022 13:23:27 +0530 Subject: [PATCH 065/105] Issue #KN-9 feat: Content Publish API refactor. --- .../content/actors/TestContentActor.scala | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala index 40778e99f..1c3535917 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala @@ -626,6 +626,66 @@ class TestContentActor extends BaseSpec with MockFactory { node } + it should "return success response for 'publishContent' for document mimeType" in { + implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] + val graphDB = mock[GraphService] + implicit val ss = mock[StorageService] + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + val node = getNodeForReview("do_123", "application/pdf", "LearningResource", "Content", "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11316726916397465612760/artifact/sample.pdf") + node.getMetadata.put("contentType", "Resource") + node.getMetadata.put("organisationBoardIds", new util.ArrayList[String](){{add("ncf_board_cbse")}}) + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() + val nodes: util.List[Node] = getCategoryNode() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + val request = getContentRequest() + request.getContext.put("identifier", "do_123") + request.getRequest.put("lastPublishedBy", "Support Team") + request.setOperation("publishContent") + val response = callActor(request, Props(new ContentActor())) + assert("successful".equals(response.getParams.getStatus)) + } + + it should "through client exception for publish operation if node is under processing" in { + implicit val ss = mock[StorageService] + implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] + val graphDB = mock[GraphService] + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + val node = getNodeForReview("do_123", "application/pdf", "LearningResource", "Content", "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11316726916397465612760/artifact/sample.pdf") + node.getMetadata.put("contentType", "Resource") + node.getMetadata.put("status", "Processing") + node.getMetadata.put("organisationBoardIds", new util.ArrayList[String](){{add("ncf_board_cbse")}}) + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() + val request = getContentRequest() + request.getContext.put("identifier", "do_123") + request.getRequest.put("lastPublishedBy", "Support Team") + request.setOperation("publishContent") + val response = callActor(request, Props(new ContentActor())) + assert(response.getResponseCode == ResponseCode.CLIENT_ERROR) + assert(response.getParams.getErr == "ERR_NODE_ACCESS_DENIED") + assert(response.getParams.getErrmsg == "Publish Operation Can't Be Applied On Node Under Processing State") + } + + it should "through client exception for publish operation if published by is not passed" in { + implicit val ss = mock[StorageService] + implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] + val graphDB = mock[GraphService] + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + val node = getNodeForReview("do_123", "application/pdf", "LearningResource", "Content", "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11316726916397465612760/artifact/sample.pdf") + node.getMetadata.put("contentType", "Resource") + node.getMetadata.put("status", "Review") + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() + val request = getContentRequest() + request.getContext.put("identifier", "do_123") + request.setOperation("publishContent") + val response = callActor(request, Props(new ContentActor())) + assert(response.getResponseCode == ResponseCode.CLIENT_ERROR) + assert(response.getParams.getErr == "ERR_CONTENT_BLANK_PUBLISHER") + assert(response.getParams.getErrmsg == "Publisher User Id is blank") + } + private def getNode(): Node = { val node = new Node() node.setIdentifier("do_1234") From a3da6afd8db2014ff1aef5cdbf59ad9d8db56cea Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Mon, 8 Aug 2022 14:54:24 +0530 Subject: [PATCH 066/105] Issue #KN-9 feat: Content Publish API refactor. --- .../content/actors/TestContentActor.scala | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala index 1c3535917..9449943cf 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala @@ -646,6 +646,106 @@ class TestContentActor extends BaseSpec with MockFactory { assert("successful".equals(response.getParams.getStatus)) } + it should "return success response for 'publishContent' for youtube mimeType" in { + implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] + val graphDB = mock[GraphService] + implicit val ss = mock[StorageService] + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + val node = getNodeForReview("do_123", "video/x-youtube", "LearningResource", "Content", "https://www.youtube.com/watch?v=EtYU11qNciQ&t=612s") + node.getMetadata.put("contentType", "Resource") + node.getMetadata.put("organisationBoardIds", new util.ArrayList[String](){{add("ncf_board_cbse")}}) + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() + val nodes: util.List[Node] = getCategoryNode() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + val request = getContentRequest() + request.getContext.put("identifier", "do_123") + request.getRequest.put("lastPublishedBy", "Support Team") + request.setOperation("publishContent") + val response = callActor(request, Props(new ContentActor())) + assert("successful".equals(response.getParams.getStatus)) + } + + it should "return success response for 'publishContent' for video mimeType" in { + implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] + val graphDB = mock[GraphService] + implicit val ss = mock[StorageService] + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + val node = getNodeForReview("do_123", "video/mp4", "LearningResource", "Content", "https://ekstep-public-prod.s3-ap-south-1.amazonaws.com/content/do_312293067955650560231/artifact/itemupload_1500618666256.mp4") + node.getMetadata.put("contentType", "Resource") + node.getMetadata.put("organisationBoardIds", new util.ArrayList[String](){{add("ncf_board_cbse")}}) + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() + val nodes: util.List[Node] = getCategoryNode() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + val request = getContentRequest() + request.getContext.put("identifier", "do_123") + request.getRequest.put("lastPublishedBy", "Support Team") + request.setOperation("publishContent") + val response = callActor(request, Props(new ContentActor())) + assert("successful".equals(response.getParams.getStatus)) + } + + it should "return success response for 'publishContent' for HTML mimeType" in { + implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] + val graphDB = mock[GraphService] + implicit val ss = mock[StorageService] + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + val node = getNodeForReview("do_123", "application/vnd.ekstep.html-archive", "LearningResource", "Content", "https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/do_21357841995316428811795/artifact/2.-ekiikrnn-kii-prkrti-output-3_1657521986480_1657522093104.zip") + node.getMetadata.put("contentType", "Resource") + node.getMetadata.put("organisationBoardIds", new util.ArrayList[String](){{add("ncf_board_cbse")}}) + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() + val nodes: util.List[Node] = getCategoryNode() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + val request = getContentRequest() + request.getContext.put("identifier", "do_123") + request.getRequest.put("lastPublishedBy", "Support Team") + request.setOperation("publishContent") + val response = callActor(request, Props(new ContentActor())) + assert("successful".equals(response.getParams.getStatus)) + } + + it should "return success response for 'publishContent' for H5P mimeType" in { + implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] + val graphDB = mock[GraphService] + implicit val ss = mock[StorageService] + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + val node = getNodeForReview("do_123", "application/vnd.ekstep.h5p-archive", "LearningResource", "Content", "https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/do_2135971978057482241406/artifact/1659814186163_do_2135971978057482241406.zip") + node.getMetadata.put("contentType", "Resource") + node.getMetadata.put("organisationBoardIds", new util.ArrayList[String](){{add("ncf_board_cbse")}}) + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() + val nodes: util.List[Node] = getCategoryNode() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + val request = getContentRequest() + request.getContext.put("identifier", "do_123") + request.getRequest.put("lastPublishedBy", "Support Team") + request.setOperation("publishContent") + val response = callActor(request, Props(new ContentActor())) + assert("successful".equals(response.getParams.getStatus)) + } + + it should "return success response for 'publishContent' for Plugin mimeType" in { + implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] + val graphDB = mock[GraphService] + implicit val ss = mock[StorageService] + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + val node = getNodeForReview("do_123", "application/vnd.ekstep.plugin-archive", "LearningResource", "Content", "https://ntpproductionall.blob.core.windows.net/ntp-content-production/content/org.ekstep.summary/artifact/org.ekstep.summary-1.0-1_1574060894628.zip") + node.getMetadata.put("contentType", "Resource") + node.getMetadata.put("organisationBoardIds", new util.ArrayList[String](){{add("ncf_board_cbse")}}) + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() + val nodes: util.List[Node] = getCategoryNode() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + val request = getContentRequest() + request.getContext.put("identifier", "do_123") + request.getRequest.put("lastPublishedBy", "Support Team") + request.setOperation("publishContent") + val response = callActor(request, Props(new ContentActor())) + assert("successful".equals(response.getParams.getStatus)) + } + it should "through client exception for publish operation if node is under processing" in { implicit val ss = mock[StorageService] implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] From a26987cb2d27c3e12a152683dec1468a2d7db422 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 9 Aug 2022 11:15:36 +0530 Subject: [PATCH 067/105] Issue #KN-9 feat: Content Publish API refactor. --- .../content/actors/TestContentActor.scala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala index 9449943cf..6cb3582c7 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala @@ -746,6 +746,24 @@ class TestContentActor extends BaseSpec with MockFactory { assert("successful".equals(response.getParams.getStatus)) } + it should "return success response for 'publishContent' for Collection mimeType" in { + implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] + val graphDB = mock[GraphService] + implicit val ss = mock[StorageService] + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + val node = getValidNode() + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(node)).anyNumberOfTimes() + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(new Response())).anyNumberOfTimes() + val nodes: util.List[Node] = getCategoryNode() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + val request = getContentRequest() + request.getContext.put("identifier", "do_1234") + request.getRequest.put("lastPublishedBy", "Support Team") + request.setOperation("publishContent") + val response = callActor(request, Props(new ContentActor())) + assert("successful".equals(response.getParams.getStatus)) + } + it should "through client exception for publish operation if node is under processing" in { implicit val ss = mock[StorageService] implicit val oec: OntologyEngineContext = mock[OntologyEngineContext] From f1b59977b39a7db925e4b7187236820dd0ccaf02 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 12 Aug 2022 11:38:25 +0530 Subject: [PATCH 068/105] Issue #KN-9 feat: Content Publish API refactor. --- .../sunbird/content/actors/ContentActor.scala | 54 +++++++++---------- .../content/publish/mgr/PublishManager.scala | 2 +- .../content/util/ContentConstants.scala | 3 +- .../controllers/v3/ContentController.scala | 4 +- .../controllers/v4/CollectionController.scala | 4 +- .../controllers/v4/ContentController.scala | 4 +- .../content-service/app/utils/ApiId.scala | 3 +- 7 files changed, 38 insertions(+), 36 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala index c6e5d2fa4..4f2fd92ac 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala @@ -65,7 +65,7 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe populateDefaultersForCreation(request) RequestUtil.restrictProperties(request) DataNode.create(request, dataModifier).map(node => { - ResponseHandler.OK.put("identifier", node.getIdentifier).put("node_id", node.getIdentifier) + ResponseHandler.OK.put(ContentConstants.IDENTIFIER, node.getIdentifier).put("node_id", node.getIdentifier) .put("versionKey", node.getMetadata.get("versionKey")) }) } @@ -76,7 +76,7 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe request.getRequest.put("fields", fields) DataNode.read(request).map(node => { val metadata: util.Map[String, AnyRef] = NodeUtil.serialize(node, fields, node.getObjectType.toLowerCase.replace("image", ""), request.getContext.get("version").asInstanceOf[String]) - metadata.put("identifier", node.getIdentifier.replace(".img", "")) + metadata.put(ContentConstants.IDENTIFIER, node.getIdentifier.replace(".img", "")) val response: Response = ResponseHandler.OK if (responseSchemaName.isEmpty) { response.put("content", metadata) @@ -100,7 +100,7 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe if (StringUtils.isBlank(request.getRequest.getOrDefault("channel", "").asInstanceOf[String])) throw new ClientException("ERR_INVALID_CHANNEL", "Please Provide Channel!") DataNode.read(request).map(node => { val metadata: util.Map[String, AnyRef] = NodeUtil.serialize(node, fields, node.getObjectType.toLowerCase.replace("image", ""), request.getContext.get("version").asInstanceOf[String]) - metadata.put("identifier", node.getIdentifier.replace(".img", "")) + metadata.put(ContentConstants.IDENTIFIER, node.getIdentifier.replace(".img", "")) val response: Response = ResponseHandler.OK if (StringUtils.equalsIgnoreCase(metadata.getOrDefault("channel", "").asInstanceOf[String],request.getRequest.getOrDefault("channel", "").asInstanceOf[String])) { if (responseSchemaName.isEmpty) { @@ -123,19 +123,19 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe RequestUtil.restrictProperties(request) DataNode.update(request, dataModifier).map(node => { val identifier: String = node.getIdentifier.replace(".img", "") - ResponseHandler.OK.put("node_id", identifier).put("identifier", identifier) + ResponseHandler.OK.put("node_id", identifier).put(ContentConstants.IDENTIFIER, identifier) .put("versionKey", node.getMetadata.get("versionKey")) }) } def upload(request: Request): Future[Response] = { - val identifier: String = request.getContext.getOrDefault("identifier", "").asInstanceOf[String] + val identifier: String = request.getContext.getOrDefault(ContentConstants.IDENTIFIER, "").asInstanceOf[String] val readReq = new Request(request) - readReq.put("identifier", identifier) + readReq.put(ContentConstants.IDENTIFIER, identifier) readReq.put("fields", new util.ArrayList[String]) DataNode.read(readReq).map(node => { if (null != node & StringUtils.isNotBlank(node.getObjectType)) - request.getContext.put("schemaName", node.getObjectType.toLowerCase()) + request.getContext.put(ContentConstants.SCHEMA_NAME, node.getObjectType.toLowerCase()) UploadManager.upload(request, node) }).flatMap(f => f) } @@ -150,14 +150,14 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe val fileName: String = request.get("fileName").asInstanceOf[String] val filePath: String = request.getRequest.getOrDefault("filePath","").asInstanceOf[String] .replaceAll("^/+|/+$", "") - val identifier: String = request.get("identifier").asInstanceOf[String] + val identifier: String = request.get(ContentConstants.IDENTIFIER).asInstanceOf[String] validatePreSignedUrlRequest(`type`, fileName, filePath) DataNode.read(request).map(node => { val objectKey = if (StringUtils.isEmpty(filePath)) "content" + File.separator + `type` + File.separator + identifier + File.separator + Slug.makeSlug(fileName, true) else filePath + File.separator + "content" + File.separator + `type` + File.separator + identifier + File.separator + Slug.makeSlug(fileName, true) val expiry = Platform.config.getString("cloud_storage.upload.url.ttl") val preSignedURL = ss.getSignedURL(objectKey, Option.apply(expiry.toInt), Option.apply("w")) - ResponseHandler.OK().put("identifier", identifier).put("pre_signed_url", preSignedURL) + ResponseHandler.OK().put(ContentConstants.IDENTIFIER, identifier).put("pre_signed_url", preSignedURL) .put("url_expiry", expiry) }) recoverWith { case e: CompletionException => throw e.getCause } } @@ -185,34 +185,34 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe def importContent(request: Request): Future[Response] = importMgr.importObject(request) def reviewContent(request: Request): Future[Response] = { - val identifier: String = request.getContext.getOrDefault("identifier", "").asInstanceOf[String] + val identifier: String = request.getContext.getOrDefault(ContentConstants.IDENTIFIER, "").asInstanceOf[String] val readReq = new Request(request) - readReq.put("identifier", identifier) - readReq.put("mode", "edit") + readReq.put(ContentConstants.IDENTIFIER, identifier) + readReq.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) DataNode.read(readReq).map(node => { if (null != node & StringUtils.isNotBlank(node.getObjectType)) - request.getContext.put("schemaName", node.getObjectType.toLowerCase()) - if (StringUtils.equalsAnyIgnoreCase("Processing", node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) + request.getContext.put(ContentConstants.SCHEMA_NAME, node.getObjectType.toLowerCase()) + if (StringUtils.equalsAnyIgnoreCase(ContentConstants.PROCESSING, node.getMetadata.getOrDefault(ContentConstants.STATUS, "").asInstanceOf[String])) throw new ClientException("ERR_NODE_ACCESS_DENIED", "Review Operation Can't Be Applied On Node Under Processing State") else ReviewManager.review(request, node) }).flatMap(f => f) } def publishContent(request: Request): Future[Response] = { - val identifier: String = request.getContext.getOrDefault("identifier", "").asInstanceOf[String] - val publisher: String = request.getRequest.getOrDefault("lastPublishedBy", "").asInstanceOf[String] + val identifier: String = request.getContext.getOrDefault(ContentConstants.IDENTIFIER, "").asInstanceOf[String] + val publisher: String = request.getRequest.getOrDefault(ContentConstants.LAST_PUBLISHED_BY, "").asInstanceOf[String] if(publisher.isBlank) throw new ClientException("ERR_CONTENT_BLANK_PUBLISHER", "Publisher User Id is blank") val readReq = new Request(request) - readReq.put("identifier", identifier) - readReq.put("mode", "edit") + readReq.put(ContentConstants.IDENTIFIER, identifier) + readReq.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) DataNode.read(readReq).map(node => { if (null != node & StringUtils.isNotBlank(node.getObjectType)) - request.getContext.put("schemaName", node.getObjectType.toLowerCase()) - if (StringUtils.equalsAnyIgnoreCase("Processing", node.getMetadata.getOrDefault("status", "").asInstanceOf[String])) + request.getContext.put(ContentConstants.SCHEMA_NAME, node.getObjectType.toLowerCase()) + if (StringUtils.equalsAnyIgnoreCase(ContentConstants.PROCESSING, node.getMetadata.getOrDefault(ContentConstants.STATUS, "").asInstanceOf[String])) throw new ClientException("ERR_NODE_ACCESS_DENIED", "Publish Operation Can't Be Applied On Node Under Processing State") - node.getMetadata.put("lastPublishedBy", publisher) + node.getMetadata.put(ContentConstants.LAST_PUBLISHED_BY, publisher) PublishManager.publish(request, node) }).flatMap(f => f) } @@ -287,7 +287,7 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe } def systemUpdate(request: Request): Future[Response] = { - val identifier = request.getContext.get("identifier").asInstanceOf[String] + val identifier = request.getContext.get(ContentConstants.IDENTIFIER).asInstanceOf[String] RequestUtil.validateRequest(request) RedisCache.delete(hierarchyPrefix + request.get("rootId")) @@ -305,21 +305,21 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe else DataNode.systemUpdate(request, response,"", None) }).map(node => { - ResponseHandler.OK.put("identifier", identifier).put("status", "success") + ResponseHandler.OK.put(ContentConstants.IDENTIFIER, identifier).put(ContentConstants.STATUS, "success") }) } def rejectContent(request: Request): Future[Response] = { RequestUtil.validateRequest(request) DataNode.read(request).map(node => { - val status = node.getMetadata.get("status").asInstanceOf[String] + val status = node.getMetadata.get(ContentConstants.STATUS).asInstanceOf[String] if (StringUtils.isBlank(status)) throw new ClientException("ERR_METADATA_ISSUE", "Content metadata error, status is blank for identifier:" + node.getIdentifier) if (StringUtils.equals("Review", status)) { - request.getRequest.put("status", "Draft") + request.getRequest.put(ContentConstants.STATUS, "Draft") request.getRequest.put("prevStatus", "Review") } else if (StringUtils.equals("FlagReview", status)) { - request.getRequest.put("status", "FlagDraft") + request.getRequest.put(ContentConstants.STATUS, "FlagDraft") request.getRequest.put("prevStatus", "FlagReview") } else new ClientException("ERR_INVALID_REQUEST", "Content not in Review status.") @@ -330,7 +330,7 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe RequestUtil.restrictProperties(request) DataNode.update(request).map(node => { val identifier: String = node.getIdentifier.replace(".img", "") - ResponseHandler.OK.put("node_id", identifier).put("identifier", identifier) + ResponseHandler.OK.put("node_id", identifier).put(ContentConstants.IDENTIFIER, identifier) }) }).flatMap(f => f) } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala index e365bb885..ed25c8a85 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala @@ -39,7 +39,7 @@ object PublishManager { val param = new ResponseParams param.setStatus(StatusType.successful.name) response.setParams(param) - response.put(ContentConstants.PUBLISH_STATUS, "Publish Event for Content Id '" + node.getIdentifier + "' is pushed Successfully!") + response.put(ContentConstants.PUBLISH_STATUS, s"Publish Event for Content Id '${node.getIdentifier}' is pushed Successfully!") response.put(ContentConstants.NODE_ID, node.getIdentifier) Future(response) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala index 070fb692e..ffc31a8d2 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala @@ -73,5 +73,6 @@ object ContentConstants { val ACTION: String = "action" val PUBLISH: String = "publish" val ENV: String = "env" - val KAFKA_PUBLISH_TOPIC = "kafka.publish.request.topic" + val KAFKA_PUBLISH_TOPIC: String = "kafka.publish.request.topic" + val PROCESSING: String = "Processing" } diff --git a/content-api/content-service/app/controllers/v3/ContentController.scala b/content-api/content-service/app/controllers/v3/ContentController.scala index ee6c425f5..f366793da 100644 --- a/content-api/content-service/app/controllers/v3/ContentController.scala +++ b/content-api/content-service/app/controllers/v3/ContentController.scala @@ -156,7 +156,7 @@ class ContentController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentActor: setRequestContext(contentRequest, version, objectType, schemaName) contentRequest.getContext.put("identifier", identifier); contentRequest.getContext.put("publish_type", "public"); - getResult(ApiId.PUBLISH_CONTENT, contentActor, contentRequest) + getResult(ApiId.PUBLISH_CONTENT_PUBLIC, contentActor, contentRequest) } def publishUnlisted(identifier: String) = Action.async { implicit request => @@ -168,7 +168,7 @@ class ContentController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentActor: setRequestContext(contentRequest, version, objectType, schemaName) contentRequest.getContext.put("identifier", identifier); contentRequest.getContext.put("publish_type", "unlisted"); - getResult(ApiId.PUBLISH_CONTENT, contentActor, contentRequest) + getResult(ApiId.PUBLISH_CONTENT_UNLSTED, contentActor, contentRequest) } def review(identifier: String) = Action.async { implicit request => diff --git a/content-api/content-service/app/controllers/v4/CollectionController.scala b/content-api/content-service/app/controllers/v4/CollectionController.scala index 34d5ba35a..7b4647f61 100644 --- a/content-api/content-service/app/controllers/v4/CollectionController.scala +++ b/content-api/content-service/app/controllers/v4/CollectionController.scala @@ -273,7 +273,7 @@ class CollectionController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentAc setRequestContext(contentRequest, version, objectType, schemaName) contentRequest.getContext.put("identifier", identifier); contentRequest.getContext.put("publish_type", "public"); - getResult(ApiId.PUBLISH_CONTENT, contentActor, contentRequest) + getResult(ApiId.PUBLISH_CONTENT_PUBLIC, contentActor, contentRequest, version = apiVersion) } def publishUnlisted(identifier: String) = Action.async { implicit request => @@ -285,7 +285,7 @@ class CollectionController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentAc setRequestContext(contentRequest, version, objectType, schemaName) contentRequest.getContext.put("identifier", identifier); contentRequest.getContext.put("publish_type", "unlisted"); - getResult(ApiId.PUBLISH_CONTENT, contentActor, contentRequest) + getResult(ApiId.PUBLISH_CONTENT_UNLSTED, contentActor, contentRequest, version = apiVersion) } diff --git a/content-api/content-service/app/controllers/v4/ContentController.scala b/content-api/content-service/app/controllers/v4/ContentController.scala index 98594df34..78d717f13 100644 --- a/content-api/content-service/app/controllers/v4/ContentController.scala +++ b/content-api/content-service/app/controllers/v4/ContentController.scala @@ -227,7 +227,7 @@ class ContentController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentActor: setRequestContext(contentRequest, version, objectType, schemaName) contentRequest.getContext.put("identifier", identifier); contentRequest.getContext.put("publish_type", "public"); - getResult(ApiId.PUBLISH_CONTENT, contentActor, contentRequest) + getResult(ApiId.PUBLISH_CONTENT_PUBLIC, contentActor, contentRequest, version = apiVersion) } def publishUnlisted(identifier: String) = Action.async { implicit request => @@ -239,7 +239,7 @@ class ContentController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentActor: setRequestContext(contentRequest, version, objectType, schemaName) contentRequest.getContext.put("identifier", identifier); contentRequest.getContext.put("publish_type", "unlisted"); - getResult(ApiId.PUBLISH_CONTENT, contentActor, contentRequest) + getResult(ApiId.PUBLISH_CONTENT_UNLSTED, contentActor, contentRequest, version = apiVersion) } } diff --git a/content-api/content-service/app/utils/ApiId.scala b/content-api/content-service/app/utils/ApiId.scala index 804aa87c6..f69ae6c49 100644 --- a/content-api/content-service/app/utils/ApiId.scala +++ b/content-api/content-service/app/utils/ApiId.scala @@ -22,7 +22,8 @@ object ApiId { val SYSTEM_UPDATE_CONTENT = "api.content.system.update" val REVIEW_CONTENT = "api.content.review" val REJECT_CONTENT = "api.content.review.reject" - val PUBLISH_CONTENT = "api.content.publish" + val PUBLISH_CONTENT_PUBLIC = "api.content.publish.public" + val PUBLISH_CONTENT_UNLSTED = "api.content.publish.unlisted" // Collection APIs val ADD_HIERARCHY = "api.content.hierarchy.add" From a28e205108b426aa6663d7349902e7752aa3d812 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 12 Aug 2022 11:42:40 +0530 Subject: [PATCH 069/105] Issue #KN-9 feat: Content Publish API refactor. --- .../org/sunbird/content/publish/mgr/PublishManager.scala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala index ed25c8a85..8786883c5 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala @@ -61,7 +61,6 @@ object PublishManager { private def generateInstructionEventMetadata(actor: util.Map[String, AnyRef], context: util.Map[String, AnyRef], objectData: util.Map[String, AnyRef], edata: util.Map[String, AnyRef], node: Node, identifier: String): Unit = { val metadata: util.Map[String, AnyRef] = node.getMetadata - val instructionEventMetadata = new util.HashMap[String, AnyRef] actor.put(ContentConstants.ID, node.getObjectType.toLowerCase() + "-publish") actor.put(ContentConstants.TYPE, ContentConstants.SYSTEM) @@ -76,12 +75,17 @@ object PublishManager { } objectData.put(ContentConstants.ID, identifier) objectData.put(ContentConstants.VER, metadata.get(ContentConstants.VERSION_KEY)) + getEData(metadata, edata, identifier, node.getObjectType) + } + + private def getEData(metadata: util.Map[String, AnyRef], edata: util.Map[String, AnyRef], identifier: String, objectType: String): Unit = { + val instructionEventMetadata = new util.HashMap[String, AnyRef] edata.put(ContentConstants.PUBLISH_TYPE, metadata.get(ContentConstants.PUBLISH_TYPE)) instructionEventMetadata.put(ContentConstants.PACKAGE_VERSION, metadata.getOrDefault(ContentConstants.PACKAGE_VERSION,0.asInstanceOf[AnyRef])) instructionEventMetadata.put(ContentConstants.MIME_TYPE, metadata.get(ContentConstants.MIME_TYPE)) instructionEventMetadata.put(ContentConstants.LAST_PUBLISHED_BY, metadata.get(ContentConstants.LAST_PUBLISHED_BY)) instructionEventMetadata.put(ContentConstants.IDENTIFIER, identifier) - instructionEventMetadata.put(ContentConstants.OBJECT_TYPE, node.getObjectType) + instructionEventMetadata.put(ContentConstants.OBJECT_TYPE, objectType) edata.put(ContentConstants.METADATA, instructionEventMetadata) edata.put(ContentConstants.ACTION, ContentConstants.PUBLISH) edata.put(ContentConstants.CONTENT_TYPE, metadata.get(ContentConstants.CONTENT_TYPE)) From c461aa2679003276b9777b9559a81865508e3085 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 12 Aug 2022 11:43:42 +0530 Subject: [PATCH 070/105] Issue #KN-9 feat: Content Publish API refactor. --- .../org/sunbird/content/publish/mgr/PublishManager.scala | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala index 8786883c5..16a4e2f71 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/publish/mgr/PublishManager.scala @@ -62,8 +62,11 @@ object PublishManager { private def generateInstructionEventMetadata(actor: util.Map[String, AnyRef], context: util.Map[String, AnyRef], objectData: util.Map[String, AnyRef], edata: util.Map[String, AnyRef], node: Node, identifier: String): Unit = { val metadata: util.Map[String, AnyRef] = node.getMetadata + // actor actor.put(ContentConstants.ID, node.getObjectType.toLowerCase() + "-publish") actor.put(ContentConstants.TYPE, ContentConstants.SYSTEM) + + //context context.put(ContentConstants.CHANNEL, metadata.get(ContentConstants.CHANNEL)) context.put(ContentConstants.P_DATA, new util.HashMap[String, AnyRef]() {{ put(ContentConstants.ID, ContentConstants.SUNBIRD_PLATFORM) @@ -73,8 +76,12 @@ object PublishManager { val env: String = Platform.getString("cloud_storage.env", "dev") context.put(ContentConstants.ENV, env) } + + //objectData objectData.put(ContentConstants.ID, identifier) objectData.put(ContentConstants.VER, metadata.get(ContentConstants.VERSION_KEY)) + + //edata getEData(metadata, edata, identifier, node.getObjectType) } From b66079d36e26d6eff09c4c9369b7e4169b23d022 Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Fri, 19 Aug 2022 13:32:51 +0530 Subject: [PATCH 071/105] Issue #KN-231 feat: Added the support for google-cloud. --- platform-modules/mimetype-manager/pom.xml | 2 +- .../sunbird/cloudstore/StorageService.scala | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/platform-modules/mimetype-manager/pom.xml b/platform-modules/mimetype-manager/pom.xml index eb25c58f1..c97b9bbd2 100644 --- a/platform-modules/mimetype-manager/pom.xml +++ b/platform-modules/mimetype-manager/pom.xml @@ -30,7 +30,7 @@ org.sunbird cloud-store-sdk - 1.3.0 + 1.4.0 org.scala-lang diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala index 83fabffc8..0045caf82 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala @@ -28,14 +28,17 @@ class StorageService { val storageKey = Platform.config.getString("aws_storage_key") val storageSecret = Platform.config.getString("aws_storage_secret") storageService = StorageServiceFactory.getStorageService(new StorageConfig(storageType, storageKey, storageSecret)) + } else if (StringUtils.equalsIgnoreCase(storageType, "gcloud")) { + val storageKey = Platform.config.getString("gcloud_client_key") + val storageSecret = Platform.config.getString("gcloud_private_secret") + storageService = StorageServiceFactory.getStorageService(new StorageConfig(storageType, storageKey, storageSecret)) } - else if (StringUtils.equalsIgnoreCase(storageType, "cephs3")) { - val storageKey = Platform.config.getString("cephs3_storage_key") - val storageSecret = Platform.config.getString("cephs3_storage_secret") - val endpoint = Platform.config.getString("cephs3_storage_endpoint") - storageService = StorageServiceFactory.getStorageService(new StorageConfig(storageType, storageKey, storageSecret, Option(endpoint))) - - } +// else if (StringUtils.equalsIgnoreCase(storageType, "cephs3")) { +// val storageKey = Platform.config.getString("cephs3_storage_key") +// val storageSecret = Platform.config.getString("cephs3_storage_secret") +// val endpoint = Platform.config.getString("cephs3_storage_endpoint") +// storageService = StorageServiceFactory.getStorageService(new StorageConfig(storageType, storageKey, storageSecret, Option(endpoint))) +// } else throw new ServerException("ERR_INVALID_CLOUD_STORAGE", "Error while initialising cloud storage") } storageService @@ -46,6 +49,8 @@ class StorageService { Platform.config.getString("azure_storage_container") else if (StringUtils.equalsIgnoreCase(storageType, "aws")) Platform.config.getString("aws_storage_container") + else if (StringUtils.equalsIgnoreCase(storageType, "gcloud")) + Platform.config.getString("gcloud_storage_bucket") else if (StringUtils.equalsIgnoreCase(storageType, "cephs3")) Platform.config.getString("cephs3_storage_container") else From 64fdb653f98303cac87fa757c47b6e082ee7116a Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 23 Aug 2022 14:25:33 +0530 Subject: [PATCH 072/105] Issue #KN-9 feat: Content Publish API refactor. --- .../Publish API.postman_collection.json | 9744 +++++++++++++++++ .../Reports/Publish API.postman_test_run.json | 2679 +++++ 2 files changed, 12423 insertions(+) create mode 100644 content-api/api-tests/Collections/Publish API.postman_collection.json create mode 100644 content-api/api-tests/Reports/Publish API.postman_test_run.json diff --git a/content-api/api-tests/Collections/Publish API.postman_collection.json b/content-api/api-tests/Collections/Publish API.postman_collection.json new file mode 100644 index 000000000..75a526868 --- /dev/null +++ b/content-api/api-tests/Collections/Publish API.postman_collection.json @@ -0,0 +1,9744 @@ +{ + "info": { + "_postman_id": "607f186e-f5e0-4d51-a4c6-02c534d1689c", + "name": "Publish API", + "description": "The Content/Collection Publish APIs allow you to publish content/collection on the Sunbird platform. Publish API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/publish and /collection/v2/publish.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Pre-requisite", + "item": [ + { + "name": "Collection Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.environment.set(\"collection_id\", jsonResponse.result.identifier);", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Sample Collection\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.content-collection\",\n \"primaryCategory\": \"Digital Textbook\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "TOC Upload", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "fileUrl", + "value": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/hierarchy/do_113316820811522048194/createtoc.csv", + "type": "text" + } + ] + }, + "url": { + "raw": "{{host}}/collection/v4/import/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "import", + "{{collection_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Collection Create wo hierarchy", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.environment.set(\"collection_id_wo_hierarchy\", jsonResponse.result.identifier);", + "pm.globals.set(\"collection_id_wo_hierarchy\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Sample Collection\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.content-collection\",\n \"primaryCategory\": \"Digital Textbook\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "PDF Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"pdf_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/assets/do_2136088747812372481510/samplepdf.pdf\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "PDF Content wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"pdf_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "MP4 Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"mp4_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"video/mp4\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/assets/do_21360643694649344011752/draftversion.mp4\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "MP4 Content Create wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"mp4_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"video/mp4\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "WEBM Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"webm_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"video/webm\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/assets/do_21360604894303027211507/big-buck-bunny_trailer.webm\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "WEBM Content Create wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"webm_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"video/webm\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "HTML Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"html_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.html-archive\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/do_21357841995316428811795/artifact/2.-ekiikrnn-kii-prkrti-output-3_1657521986480_1657522093104.zip\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "HTML Content Create wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"html_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.html-archive\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "H5P Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"h5p_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.h5p-archive\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/do_2136088263163084801476/artifact/1661233685237_do_2136088263163084801476.zip\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "H5P Content Create wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"h5p_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.h5p-archive\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "ECML Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"ecml_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.ecml-archive\",\n \"primaryCategory\": \"Explanation Content\",\n \"body\": \"{\\\"theme\\\":{\\\"id\\\":\\\"theme\\\",\\\"version\\\":\\\"1.0\\\",\\\"startStage\\\":\\\"463caa09-b78e-412c-ae20-a2776c76b4a0\\\",\\\"stage\\\":[{\\\"x\\\":0,\\\"y\\\":0,\\\"w\\\":100,\\\"h\\\":100,\\\"id\\\":\\\"463caa09-b78e-412c-ae20-a2776c76b4a0\\\",\\\"rotate\\\":null,\\\"config\\\":{\\\"__cdata\\\":\\\"{\\\\\\\"opacity\\\\\\\":100,\\\\\\\"strokeWidth\\\\\\\":1,\\\\\\\"stroke\\\\\\\":\\\\\\\"rgba(255, 255, 255, 0)\\\\\\\",\\\\\\\"autoplay\\\\\\\":false,\\\\\\\"visible\\\\\\\":true,\\\\\\\"color\\\\\\\":\\\\\\\"#FFFFFF\\\\\\\",\\\\\\\"genieControls\\\\\\\":false,\\\\\\\"instructions\\\\\\\":\\\\\\\"\\\\\\\"}\\\"},\\\"manifest\\\":{\\\"media\\\":[]},\\\"shape\\\":[{\\\"type\\\":\\\"ellipse\\\",\\\"x\\\":15,\\\"y\\\":15,\\\"fill\\\":\\\"#00FF00\\\",\\\"w\\\":18,\\\"h\\\":32,\\\"stroke\\\":\\\"rgba(255, 255, 255, 0)\\\",\\\"strokeWidth\\\":1,\\\"opacity\\\":1,\\\"rotate\\\":0,\\\"r\\\":64.8,\\\"z-index\\\":0,\\\"id\\\":\\\"7e35536a-1e50-4ada-872e-416b04da61a0\\\",\\\"config\\\":{\\\"__cdata\\\":\\\"{\\\\\\\"opacity\\\\\\\":100,\\\\\\\"strokeWidth\\\\\\\":1,\\\\\\\"stroke\\\\\\\":\\\\\\\"rgba(255, 255, 255, 0)\\\\\\\",\\\\\\\"autoplay\\\\\\\":false,\\\\\\\"visible\\\\\\\":true,\\\\\\\"color\\\\\\\":\\\\\\\"#00FF00\\\\\\\",\\\\\\\"radius\\\\\\\":64.8}\\\"}}]}],\\\"manifest\\\":{\\\"media\\\":[{\\\"id\\\":\\\"d91cc898-8885-4642-9e55-d16bd502d946\\\",\\\"plugin\\\":\\\"org.ekstep.navigation\\\",\\\"ver\\\":\\\"1.0\\\",\\\"src\\\":\\\"/content-plugins/org.ekstep.navigation-1.0/renderer/controller/navigation_ctrl.js\\\",\\\"type\\\":\\\"js\\\"},{\\\"id\\\":\\\"e02a792e-b75e-4eea-bae0-58666a4ee5c2\\\",\\\"plugin\\\":\\\"org.ekstep.navigation\\\",\\\"ver\\\":\\\"1.0\\\",\\\"src\\\":\\\"/content-plugins/org.ekstep.navigation-1.0/renderer/templates/navigation.html\\\",\\\"type\\\":\\\"js\\\"},{\\\"id\\\":\\\"org.ekstep.navigation\\\",\\\"plugin\\\":\\\"org.ekstep.navigation\\\",\\\"ver\\\":\\\"1.0\\\",\\\"src\\\":\\\"/content-plugins/org.ekstep.navigation-1.0/renderer/plugin.js\\\",\\\"type\\\":\\\"plugin\\\"},{\\\"id\\\":\\\"org.ekstep.navigation_manifest\\\",\\\"plugin\\\":\\\"org.ekstep.navigation\\\",\\\"ver\\\":\\\"1.0\\\",\\\"src\\\":\\\"/content-plugins/org.ekstep.navigation-1.0/manifest.json\\\",\\\"type\\\":\\\"json\\\"}]},\\\"plugin-manifest\\\":{\\\"plugin\\\":[{\\\"id\\\":\\\"org.ekstep.navigation\\\",\\\"ver\\\":\\\"1.0\\\",\\\"type\\\":\\\"plugin\\\",\\\"depends\\\":\\\"\\\"}]},\\\"compatibilityVersion\\\":2}}\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "ECML Content Create invalid body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"ecml_content_id_invalid_body\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.ecml-archive\",\n \"primaryCategory\": \"Explanation Content\",\n \"body\": \"dummy\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "ECML Content Create wo body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"ecml_content_id_wo_body\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.ecml-archive\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "EPUB Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"epub_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/epub\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/assets/do_2136085231556526081377/faulkner-sound-and-the-fury.epub\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "EPUB Content Create wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"epub_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/epub\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "Youtube Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"yt_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"video/x-youtube\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://www.youtube.com/watch?v=fkLcI4R7unE\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "Youtube Content Create wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"yt_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"video/x-youtube\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "Plugin Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"plugin_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"org.ekstep.summary-test\",\n \"mimeType\": \"application/vnd.ekstep.plugin-archive\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://ntpproductionall.blob.core.windows.net/ntp-content-production/content/org.ekstep.summary/artifact/org.ekstep.summary-1.0-1_1574060894628.zip\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "Plugin Create wo artifact", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"plugin_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"test-plugin\",\n \"mimeType\": \"application/vnd.ekstep.plugin-archive\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + } + ] + }, + { + "name": "Positive", + "item": [ + { + "name": "Content Publish API", + "item": [ + { + "name": "Collection Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/publish/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "publish", + "{{collection_id}}" + ] + } + }, + "response": [] + }, + { + "name": "PDF Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{pdf_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{pdf_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "MP4 Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{mp4_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{mp4_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "WEBM Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{webm_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{webm_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "HTML Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/publish/{{html_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "publish", + "{{html_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "H5P Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/publish/{{h5p_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "publish", + "{{h5p_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "EPUB Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/publish/{{epub_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "publish", + "{{epub_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "ECML Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/publish/{{ecml_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "publish", + "{{ecml_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Youtube Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/publish/{{yt_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "publish", + "{{yt_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Plugin Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/publish/{{plugin_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "publish", + "{{plugin_id}}" + ] + } + }, + "response": [] + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "//Verification", + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200)", + "});", + "//code name contains a string", + "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", + "", + "// pm.test(\"Content-Encoding header is present\", () => {", + "// pm.response.to.have.header(\"Content-Encoding\");", + "// });", + "// pm.test(\"Content-Encoding header is gzip\", () => {", + "// pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "// });", + "", + "pm.test(\"Verify keys and data type of the params in positive scenario\", () => {", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + "});", + "", + "pm.test(\"params.status should be \\\"successful\\\"\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});" + ] + } + } + ] + }, + { + "name": "Negative", + "item": [ + { + "name": "Content Publish API", + "item": [ + { + "name": "Invalid Content ID Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/do_dummy_id", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "do_dummy_id" + ] + } + }, + "response": [] + }, + { + "name": "Invalid Collection ID Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/publish/do_dummy_id", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "publish", + "do_dummy_id" + ] + } + }, + "response": [] + }, + { + "name": "PDF Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{pdf_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{pdf_content_id_wo_artifact}}" + ] + } + }, + "response": [] + }, + { + "name": "MP4 Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{mp4_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{mp4_content_id_wo_artifact}}" + ] + } + }, + "response": [] + }, + { + "name": "WEBM Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{webm_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{webm_content_id_wo_artifact}}" + ] + } + }, + "response": [] + }, + { + "name": "HTML Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{html_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{html_content_id_wo_artifact}}" + ] + } + }, + "response": [] + }, + { + "name": "H5P Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{h5p_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{h5p_content_id_wo_artifact}}" + ] + } + }, + "response": [] + }, + { + "name": "EPUB Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{epub_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{epub_content_id_wo_artifact}}" + ] + } + }, + "response": [] + }, + { + "name": "Youtube Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{yt_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{yt_content_id_wo_artifact}}" + ] + } + }, + "response": [] + }, + { + "name": "Plugin Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{plugin_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{plugin_id_wo_artifact}}" + ] + } + }, + "response": [] + }, + { + "name": "Collection Publish without hierarchy", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws ERR_COLLECTION_REVIEW\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_COLLECTION_REVIEW\") ", + "});", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(function(){}, 40000);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/publish/{{collection_id_wo_hierarchy}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "publish", + "{{collection_id_wo_hierarchy}}" + ] + } + }, + "response": [] + }, + { + "name": "ECML Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(function(){}, 2000);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{ecml_content_id_wo_body}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{ecml_content_id_wo_body}}" + ] + } + }, + "response": [] + }, + { + "name": "ECML Content Publish invalid Body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"INVALID_CONTENT_BODY\") ", + "});", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(function(){}, 1000);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/publish/{{ecml_content_id_invalid_body}}", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "publish", + "{{ecml_content_id_invalid_body}}" + ] + } + }, + "response": [] + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "//Verification", + "// pm.test(\"Content-Encoding header should not present\", () => {", + "// pm.response.to.not.have.header(\"Content-Encoding\");", + "// });", + "", + "pm.test(\"Verify keys and data type of the params in negative scenario\", () => {", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.a(\"string\");", + "});", + "", + "pm.test(\"params.status should be \\\"failed\\\"\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "});", + "" + ] + } + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", + "});", + "", + "pm.test(\"Validate keys and data type of the response body\", () => {", + " let jsonResponse = pm.response.json();", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + "});" + ] + } + } + ] +} \ No newline at end of file diff --git a/content-api/api-tests/Reports/Publish API.postman_test_run.json b/content-api/api-tests/Reports/Publish API.postman_test_run.json new file mode 100644 index 000000000..d6d977823 --- /dev/null +++ b/content-api/api-tests/Reports/Publish API.postman_test_run.json @@ -0,0 +1,2679 @@ +{ + "id": "25eb49d4-fb87-4fdd-abb6-e860574ac33a", + "name": "Publish API", + "timestamp": "2022-08-23T08:43:52.665Z", + "collection_id": "13387833-607f186e-f5e0-4d51-a4c6-02c534d1689c", + "folder_id": 0, + "environment_id": "0e0b136d-70cc-437e-a0df-ccba162408d9", + "totalPass": 266, + "totalFail": 0, + "results": [ + { + "id": "80fd9644-56d3-4eb5-910f-c2f9a6bbcc39", + "name": "Collection Create", + "url": "http://localhost:9000/content/v4/create", + "time": 361, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 361 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "7c5475c1-7c6a-4ca5-b71f-37b05e719446", + "name": "TOC Upload", + "url": "http://localhost:9000/collection/v4/import/do_11360891275809587211", + "time": 961, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 961 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true + } + ] + }, + { + "id": "f00000f4-e316-4081-a994-ac9078ff9a1b", + "name": "Collection Create wo hierarchy", + "url": "http://localhost:9000/content/v4/create", + "time": 45, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 45 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "edfc8942-03f2-4b49-81d6-c29a1a01d2cb", + "name": "PDF Content Create", + "url": "http://localhost:9000/content/v4/create", + "time": 67, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 67 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "13c92a31-a1b0-4bd1-95a8-e1e46af2e61f", + "name": "PDF Content wo artifactUrl", + "url": "http://localhost:9000/content/v4/create", + "time": 38, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 38 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "637502c0-3bd9-427b-997e-d01372a846c5", + "name": "MP4 Content Create", + "url": "http://localhost:9000/content/v4/create", + "time": 47, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 47 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "e4adecc9-606a-4091-b4c1-e3d2e655c370", + "name": "MP4 Content Create wo artifactUrl", + "url": "http://localhost:9000/content/v4/create", + "time": 43, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 43 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "c0c3b560-fb40-4e22-accb-74498265940f", + "name": "WEBM Content Create", + "url": "http://localhost:9000/content/v4/create", + "time": 63, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 63 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "8bb660d5-4a55-42ec-9f63-285fddf01712", + "name": "WEBM Content Create wo artifactUrl", + "url": "http://localhost:9000/content/v4/create", + "time": 55, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 55 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "8ea033c2-ced7-4189-b1a9-d4ffa3e20196", + "name": "HTML Content Create", + "url": "http://localhost:9000/content/v4/create", + "time": 30, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 30 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "6df047f6-2ac2-4967-949c-f10d9f6decb4", + "name": "HTML Content Create wo artifactUrl", + "url": "http://localhost:9000/content/v4/create", + "time": 31, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 31 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "e4cee867-b30a-4426-b314-c81d8f28cb82", + "name": "H5P Content Create", + "url": "http://localhost:9000/content/v4/create", + "time": 41, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 41 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "ebe40740-4050-43ce-a316-892100ca0676", + "name": "H5P Content Create wo artifactUrl", + "url": "http://localhost:9000/content/v4/create", + "time": 25, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 25 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "2418c40f-9b7f-4e6e-90fe-9f0b3c04537d", + "name": "ECML Content Create", + "url": "http://localhost:9000/content/v4/create", + "time": 62, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 62 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "87ac52e6-5672-4198-b13c-01fd45cb3db5", + "name": "ECML Content Create invalid body", + "url": "http://localhost:9000/content/v4/create", + "time": 48, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 48 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "8cd499ee-3bcd-4efe-ada5-92b5f5ece200", + "name": "ECML Content Create wo body", + "url": "http://localhost:9000/content/v4/create", + "time": 45, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 45 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "b339d20a-19ed-4281-9831-c10c6383e386", + "name": "EPUB Content Create", + "url": "http://localhost:9000/content/v4/create", + "time": 39, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 39 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "869a5263-7711-4c53-bc38-0da493f4ece2", + "name": "EPUB Content Create wo artifactUrl", + "url": "http://localhost:9000/content/v4/create", + "time": 30, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 30 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "d71c64ed-ab39-477e-95de-9eeea47b7986", + "name": "Youtube Content Create", + "url": "http://localhost:9000/content/v4/create", + "time": 27, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 27 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "45065a85-6bf9-4cb5-9acc-2c06345f8a26", + "name": "Youtube Content Create wo artifactUrl", + "url": "http://localhost:9000/content/v4/create", + "time": 37, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 37 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "5a9bc533-ecb7-4fb8-ae48-75ea2180b040", + "name": "Plugin Create", + "url": "http://localhost:9000/content/v4/create", + "time": 41, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 41 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "b5dd8a58-9ab1-4833-b8bb-564eda36cbc9", + "name": "Plugin Create wo artifact", + "url": "http://localhost:9000/content/v4/create", + "time": 27, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 27 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true + } + ] + }, + { + "id": "f2342494-ae32-4093-8048-f852ad38223b", + "name": "Collection Publish", + "url": "http://localhost:9000/collection/v4/publish/do_11360891275809587211", + "time": 46, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 46 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + } + ] + }, + { + "id": "d7dcfe64-e0d3-48aa-a4ce-121f19eac58e", + "name": "PDF Content Publish", + "url": "http://localhost:9000/content/v4/publish/do_113608912769916928117", + "time": 65, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 65 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + } + ] + }, + { + "id": "79327a95-1346-4635-b8ab-a3427ff9d278", + "name": "MP4 Content Publish", + "url": "http://localhost:9000/content/v4/publish/do_113608912771776512119", + "time": 49, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 49 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + } + ] + }, + { + "id": "e203fc85-ac81-43d1-b744-054688acf98a", + "name": "WEBM Content Publish", + "url": "http://localhost:9000/content/v4/publish/do_113608912773750784121", + "time": 50, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 50 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + } + ] + }, + { + "id": "1f9def38-d148-49cc-a056-14bf1d72442f", + "name": "HTML Content Publish", + "url": "http://localhost:9000/collection/v4/publish/do_113608912775979008123", + "time": 56, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 56 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + } + ] + }, + { + "id": "af6b95b5-5466-4b36-bbf3-5e9762d900d0", + "name": "H5P Content Publish", + "url": "http://localhost:9000/collection/v4/publish/do_113608912777338880125", + "time": 46, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 46 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + } + ] + }, + { + "id": "1ac93190-744e-491e-aacd-cf8204b6a073", + "name": "EPUB Content Publish", + "url": "http://localhost:9000/collection/v4/publish/do_113608912781467648130", + "time": 40, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 40 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + } + ] + }, + { + "id": "9a2bbcf9-89d1-4af6-94a2-42c87774cdbf", + "name": "ECML Content Publish", + "url": "http://localhost:9000/collection/v4/publish/do_113608912778960896127", + "time": 844, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 844 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + } + ] + }, + { + "id": "113133ef-244f-46fc-b030-cf127e224ceb", + "name": "Youtube Content Publish", + "url": "http://localhost:9000/collection/v4/publish/do_113608912782786560132", + "time": 56, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 56 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + } + ] + }, + { + "id": "ab646ab4-85c5-4faf-867b-efb9f88f3154", + "name": "Plugin Publish", + "url": "http://localhost:9000/collection/v4/publish/org.ekstep.summary-test", + "time": 35, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in positive scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"successful\"": { + "pass": 1, + "fail": 0 + }, + "responseCode should be OK": { + "pass": 1, + "fail": 0 + }, + "Status code name has string OK": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 35 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Status code is 200": true, + "Verify keys and data type of the params in positive scenario": true, + "params.status should be \"successful\"": true, + "responseCode should be OK": true, + "Status code name has string OK": true + } + ] + }, + { + "id": "34908a0c-d5cf-48f9-9ab2-b851657949cf", + "name": "Invalid Content ID Publish", + "url": "http://localhost:9000/content/v4/publish/do_dummy_id", + "time": 37, + "responseCode": { + "code": 404, + "name": "Not Found" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 404": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 404": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 37 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 404": true + } + ] + }, + { + "id": "e048689b-3df0-4b72-a024-1b032090d353", + "name": "Invalid Collection ID Publish", + "url": "http://localhost:9000/collection/v4/publish/do_dummy_id", + "time": 34, + "responseCode": { + "code": 404, + "name": "Not Found" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 404": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 404": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 34 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 404": true + } + ] + }, + { + "id": "328e19c8-84f4-4a47-95d0-a4631db50b02", + "name": "PDF Content Publish wo artifactUrl", + "url": "http://localhost:9000/content/v4/publish/do_113608912770859008118", + "time": 49, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws CLIENT_ERROR": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 49 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + } + ] + }, + { + "id": "371f42d7-4e91-467f-8dbd-700cc34982f1", + "name": "MP4 Content Publish wo artifactUrl", + "url": "http://localhost:9000/content/v4/publish/do_113608912772677632120", + "time": 80, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws CLIENT_ERROR": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 80 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + } + ] + }, + { + "id": "e7e6b6d1-6312-4411-8231-59fa776f59cb", + "name": "WEBM Content Publish wo artifactUrl", + "url": "http://localhost:9000/content/v4/publish/do_113608912774955008122", + "time": 62, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws CLIENT_ERROR": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 62 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + } + ] + }, + { + "id": "912c062c-8fe3-4159-b6fd-8b90c8fb1f10", + "name": "HTML Content Publish wo artifactUrl", + "url": "http://localhost:9000/content/v4/publish/do_113608912776773632124", + "time": 94, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws CLIENT_ERROR": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 94 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + } + ] + }, + { + "id": "bfe28b75-08c8-4082-8bd4-3e7aa685c066", + "name": "H5P Content Publish wo artifactUrl", + "url": "http://localhost:9000/content/v4/publish/do_113608912778272768126", + "time": 48, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws CLIENT_ERROR": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 48 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + } + ] + }, + { + "id": "78fe24b6-8442-426d-9ba9-fd968bbc2595", + "name": "EPUB Content Publish wo artifactUrl", + "url": "http://localhost:9000/content/v4/publish/do_113608912782188544131", + "time": 51, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws CLIENT_ERROR": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 51 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + } + ] + }, + { + "id": "3125afd5-c8c4-4818-915f-0d1ad0b7ed9f", + "name": "Youtube Content Publish wo artifactUrl", + "url": "http://localhost:9000/content/v4/publish/do_113608912783646720133", + "time": 48, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws CLIENT_ERROR": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 48 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + } + ] + }, + { + "id": "53dbf026-9d1d-4ee4-b80f-ff42a0dfb501", + "name": "Plugin Publish wo artifactUrl", + "url": "http://localhost:9000/content/v4/publish/test-plugin", + "time": 43, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws CLIENT_ERROR": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 43 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + } + ] + }, + { + "id": "2d04e34f-860a-43ae-b076-4c3b5a26363c", + "name": "Collection Publish without hierarchy", + "url": "http://localhost:9000/collection/v4/publish/do_113608912768622592116", + "time": 50, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws ERR_COLLECTION_REVIEW": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws ERR_COLLECTION_REVIEW": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 50 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws ERR_COLLECTION_REVIEW": true + } + ] + }, + { + "id": "b4ac53d8-d142-4487-a779-e9686caf972e", + "name": "ECML Content Publish wo artifactUrl", + "url": "http://localhost:9000/content/v4/publish/do_113608912780697600129", + "time": 43, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws CLIENT_ERROR": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 43 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + } + ] + }, + { + "id": "203d51fd-1ed1-48f3-8c53-dee83997cf6a", + "name": "ECML Content Publish invalid Body", + "url": "http://localhost:9000/content/v4/publish/do_113608912779886592128", + "time": 61, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + }, + "testPassFailCounts": { + "Content-Type header is present": { + "pass": 1, + "fail": 0 + }, + "Content-Type header is application/json": { + "pass": 1, + "fail": 0 + }, + "Validate keys and data type of the response body": { + "pass": 1, + "fail": 0 + }, + "Verify keys and data type of the params in negative scenario": { + "pass": 1, + "fail": 0 + }, + "params.status should be \"failed\"": { + "pass": 1, + "fail": 0 + }, + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws CLIENT_ERROR": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 61 + ], + "allTests": [ + { + "Content-Type header is present": true, + "Content-Type header is application/json": true, + "Validate keys and data type of the response body": true, + "Verify keys and data type of the params in negative scenario": true, + "params.status should be \"failed\"": true, + "Status code is 400": true, + "Response throws CLIENT_ERROR": true + } + ] + } + ], + "count": 1, + "totalTime": 4150, + "collection": { + "requests": [ + { + "id": "80fd9644-56d3-4eb5-910f-c2f9a6bbcc39", + "method": "POST" + }, + { + "id": "7c5475c1-7c6a-4ca5-b71f-37b05e719446", + "method": "POST" + }, + { + "id": "f00000f4-e316-4081-a994-ac9078ff9a1b", + "method": "POST" + }, + { + "id": "edfc8942-03f2-4b49-81d6-c29a1a01d2cb", + "method": "POST" + }, + { + "id": "13c92a31-a1b0-4bd1-95a8-e1e46af2e61f", + "method": "POST" + }, + { + "id": "637502c0-3bd9-427b-997e-d01372a846c5", + "method": "POST" + }, + { + "id": "e4adecc9-606a-4091-b4c1-e3d2e655c370", + "method": "POST" + }, + { + "id": "c0c3b560-fb40-4e22-accb-74498265940f", + "method": "POST" + }, + { + "id": "8bb660d5-4a55-42ec-9f63-285fddf01712", + "method": "POST" + }, + { + "id": "8ea033c2-ced7-4189-b1a9-d4ffa3e20196", + "method": "POST" + }, + { + "id": "6df047f6-2ac2-4967-949c-f10d9f6decb4", + "method": "POST" + }, + { + "id": "e4cee867-b30a-4426-b314-c81d8f28cb82", + "method": "POST" + }, + { + "id": "ebe40740-4050-43ce-a316-892100ca0676", + "method": "POST" + }, + { + "id": "2418c40f-9b7f-4e6e-90fe-9f0b3c04537d", + "method": "POST" + }, + { + "id": "87ac52e6-5672-4198-b13c-01fd45cb3db5", + "method": "POST" + }, + { + "id": "8cd499ee-3bcd-4efe-ada5-92b5f5ece200", + "method": "POST" + }, + { + "id": "b339d20a-19ed-4281-9831-c10c6383e386", + "method": "POST" + }, + { + "id": "869a5263-7711-4c53-bc38-0da493f4ece2", + "method": "POST" + }, + { + "id": "d71c64ed-ab39-477e-95de-9eeea47b7986", + "method": "POST" + }, + { + "id": "45065a85-6bf9-4cb5-9acc-2c06345f8a26", + "method": "POST" + }, + { + "id": "5a9bc533-ecb7-4fb8-ae48-75ea2180b040", + "method": "POST" + }, + { + "id": "b5dd8a58-9ab1-4833-b8bb-564eda36cbc9", + "method": "POST" + }, + { + "id": "f2342494-ae32-4093-8048-f852ad38223b", + "method": "POST" + }, + { + "id": "d7dcfe64-e0d3-48aa-a4ce-121f19eac58e", + "method": "POST" + }, + { + "id": "79327a95-1346-4635-b8ab-a3427ff9d278", + "method": "POST" + }, + { + "id": "e203fc85-ac81-43d1-b744-054688acf98a", + "method": "POST" + }, + { + "id": "1f9def38-d148-49cc-a056-14bf1d72442f", + "method": "POST" + }, + { + "id": "af6b95b5-5466-4b36-bbf3-5e9762d900d0", + "method": "POST" + }, + { + "id": "1ac93190-744e-491e-aacd-cf8204b6a073", + "method": "POST" + }, + { + "id": "9a2bbcf9-89d1-4af6-94a2-42c87774cdbf", + "method": "POST" + }, + { + "id": "113133ef-244f-46fc-b030-cf127e224ceb", + "method": "POST" + }, + { + "id": "ab646ab4-85c5-4faf-867b-efb9f88f3154", + "method": "POST" + }, + { + "id": "34908a0c-d5cf-48f9-9ab2-b851657949cf", + "method": "POST" + }, + { + "id": "e048689b-3df0-4b72-a024-1b032090d353", + "method": "POST" + }, + { + "id": "328e19c8-84f4-4a47-95d0-a4631db50b02", + "method": "POST" + }, + { + "id": "371f42d7-4e91-467f-8dbd-700cc34982f1", + "method": "POST" + }, + { + "id": "e7e6b6d1-6312-4411-8231-59fa776f59cb", + "method": "POST" + }, + { + "id": "912c062c-8fe3-4159-b6fd-8b90c8fb1f10", + "method": "POST" + }, + { + "id": "bfe28b75-08c8-4082-8bd4-3e7aa685c066", + "method": "POST" + }, + { + "id": "78fe24b6-8442-426d-9ba9-fd968bbc2595", + "method": "POST" + }, + { + "id": "3125afd5-c8c4-4818-915f-0d1ad0b7ed9f", + "method": "POST" + }, + { + "id": "53dbf026-9d1d-4ee4-b80f-ff42a0dfb501", + "method": "POST" + }, + { + "id": "2d04e34f-860a-43ae-b076-4c3b5a26363c", + "method": "POST" + }, + { + "id": "b4ac53d8-d142-4487-a779-e9686caf972e", + "method": "POST" + }, + { + "id": "203d51fd-1ed1-48f3-8c53-dee83997cf6a", + "method": "POST" + } + ] + } +} \ No newline at end of file From 0997ac6e17a17445b10b2d19541d7ac138833af0 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 23 Aug 2022 15:32:47 +0530 Subject: [PATCH 073/105] Issue #KN-9 feat: Content Publish API refactor. --- ...ontent V2 API Test.postman_collection.json | 13047 ++++++++++++++-- 1 file changed, 12001 insertions(+), 1046 deletions(-) diff --git a/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json b/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json index 583e76895..4a0373bd6 100644 --- a/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json +++ b/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "58a713b4-b8bb-4885-9909-b23d253f8f31", + "_postman_id": "ec007894-70ee-4951-8e96-98f79de5908a", "name": "Content V2 API Test", "description": "The Content Management APIs allow you to create, manage and process content on the Sunbird platform. Content is the basic building block of the Knowledge Service. Some examples would be Videos, Audio, Pdfs, Html, ECML etc. The basic operations for this API include Create, Update, Read, Review, Publish.\n\nThe URL for Content Management API(s) is /content/v1.", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", @@ -741,66 +741,12 @@ } } ] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } }, { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "let jsonResponse = pm.response.json();", - "", - "//Verification", - "pm.test(\"Status code is 200\", () => {", - " pm.response.to.have.status(200)", - "});", - "//code name contains a string", - "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", - "", - "// pm.test(\"Content-Encoding header is present\", () => {", - "// pm.response.to.have.header(\"Content-Encoding\");", - "// });", - "// pm.test(\"Content-Encoding header is gzip\", () => {", - "// pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", - "// });", - "", - "pm.test(\"Verify keys and data type of the params in positive scenario\", () => {", - " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.msgid).to.be.null;", - " pm.expect(jsonResponse.params.err).to.be.null;", - " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", - " pm.expect(jsonResponse.params.errmsg).to.be.null;", - "});", - "", - "pm.test(\"params.status should be \\\"successful\\\"\", () => {", - " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", - "});", - "pm.test(\"responseCode should be OK\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", - "});" - ] - } - } - ] - }, - { - "name": "Negative", - "item": [ - { - "name": "Content Create", + "name": "Content Reserve DIAL code", "item": [ { - "name": "400 - missing channel", + "name": "Collection Create", "event": [ { "listen": "test", @@ -809,37 +755,52 @@ "let jsonResponse = pm.response.json()", "", "//Verification", - "pm.test(\"Status code is 400\", () => {", - " pm.response.to.have.status(400)", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "pm.test(\"Content-Type header is present\", () => {", + " pm.response.to.have.header(\"Content-Type\");", + "});", + "pm.test(\"Content-Type header is application/json\", () => {", + " pm.expect(pm.response.headers.get('Content-Type')).to.eql('application/json');", "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", "", - "pm.test(\"Verify keys and data type of the response result\", () => {", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse).to.be.an(\"object\").that.has.all.keys('id', 'ver', 'ts', 'params', 'responseCode', 'result');", + " pm.expect(jsonResponse.id).to.be.a(\"string\");", + " pm.expect(jsonResponse.ver).to.be.a(\"string\");", + " pm.expect(jsonResponse.ts).to.be.a(\"string\");", + " pm.expect(jsonResponse.responseCode).to.be.a(\"string\");", + " pm.expect(jsonResponse.params).to.be.an(\"object\").that.has.all.keys('resmsgid', 'msgid', 'err', 'status', 'errmsg');", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + " pm.expect(jsonResponse.result).to.have.all.keys('identifier', 'node_id', 'versionKey');", + " pm.expect(jsonResponse.result.identifier).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.node_id).to.be.a(\"string\");", + " pm.expect(jsonResponse.result.versionKey).to.be.a(\"string\");", "});", "", "//Validation", - "// Response body", - "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "pm.test(\"id should be api.content.create\", function () {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "pm.test(\"ver should be 4.0\", function () {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", "});", - "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "pm.test(\"params.status should be successful\", function () {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", "});", - "", - "// Result", - "pm.test(\"result body should include messages \\\"Required Metadata channel not set\\\"\", () => {", - " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Required Metadata channel not set');", + "pm.test(\"responseCode should be OK\", function () {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", "});", + "", + "// Set global variable", + "pm.environment.set(\"collection_id\", jsonResponse.result.identifier);", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", "" ], "type": "text/javascript" @@ -847,35 +808,36 @@ } ], "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true - } + "disabledSystemHeaders": {} }, "request": { "method": "POST", "header": [ { "key": "Content-Type", - "value": "application/json" + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." }, { "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." }, { "key": "Authorization", - "value": "{{kong_api_key}}" + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." }, { "key": "X-Channel-Id", "value": "{{channel_id}}", "type": "text", - "disabled": true + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Sample Collection\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.content-collection\",\n \"primaryCategory\": \"Digital Textbook\"\n }\n }\n}" }, "url": { "raw": "{{host}}/api/content/v2/create", @@ -889,488 +851,6510 @@ "create" ] }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" }, - "response": [] + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] }, { - "name": "400 - empty channel", + "name": "Reserve DIAL code", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 400\", () => {", - " pm.response.to.have.status(400)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.not.be.empty;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", - "});", - "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", - "});", - "", - "// Result", - "pm.test(\"result body should include messages \\\"Required Metadata channel not set\\\"\", () => {", - " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Required Metadata channel not set');", - "});", - "" + "// Multiple scenarios handled at one place", + "pm.test(\"Response contains DIAL code\", function () {", + " const responseJson = pm.response.json();", + " var req = JSON.parse(request.data);", + " if(req.request.dialcodes.count > 1000){", + " pm.response.to.have.status(403);", + " } else {", + " const reservedDialcodes = responseJson.result.reservedDialcodes;", + " pm.expect(reservedDialcodes).not.null", + " _.forEach(JSON.parse(reservedDialcodes), function(value, key) {", + " const oldDialcode = pm.globals.get(\"new_dialcode\")", + " pm.globals.set(\"replaced_dialcode\", oldDialcode);", + " pm.globals.set(\"new_dialcode\", key);", + " });", + " console.log(pm.globals.get(\"replaced_dialcode\")); ", + " console.log(pm.globals.get(\"new_dialcode\"));", + " }", + " ", + "});" ], "type": "text/javascript" } } ], - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true - } - }, "request": { "method": "POST", "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" - }, { "key": "Authorization", "value": "{{kong_api_key}}" }, { - "key": "X-Channel-Id", - "value": "", - "type": "text" + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 3,\n \"qrCodeSpec\": {\n \"errorCorrectionLevel\": \"H\"\n }\n }\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/create", + "raw": "{{host}}/api/collection/v1/dialcode/reserve/{{collection_id}}", "host": [ "{{host}}" ], "path": [ "api", - "content", - "v2", - "create" + "collection", + "v1", + "dialcode", + "reserve", + "{{collection_id}}" ] - }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, "response": [] }, { - "name": "400 - missing name", + "name": "Update Reserved DIAL code", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 400\", () => {", - " pm.response.to.have.status(400)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.not.be.empty;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", - "});", - "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", - "});", - "", - "// Result", - "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", - " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", - "});", - "" + "// Multiple scenarios handled at one place", + "pm.test(\"Response contains DIAL code\", function () {", + " const responseJson = pm.response.json();", + " var req = JSON.parse(request.data);", + " if(req.request.dialcodes.count > 1000){", + " pm.response.to.have.status(403);", + " } else {", + " const reservedDialcodes = responseJson.result.reservedDialcodes;", + " pm.expect(reservedDialcodes).not.null", + " }", + " ", + "});" ], "type": "text/javascript" } } ], - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true - } - }, "request": { "method": "POST", "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" - }, { "key": "Authorization", "value": "{{kong_api_key}}" }, { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 5,\n \"qrCodeSpec\": {\n \"errorCorrectionLevel\": \"H\"\n }\n }\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/create", + "raw": "{{host}}/api/collection/v1/dialcode/reserve/{{collection_id}}", "host": [ "{{host}}" ], "path": [ "api", - "content", - "v2", - "create" + "collection", + "v1", + "dialcode", + "reserve", + "{{collection_id}}" ] - }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, "response": [] }, { - "name": "400 - name: invalid datatype", + "name": "Reserve DIAL codes without qr spec", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 400\", () => {", - " pm.response.to.have.status(400)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.not.be.empty;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", - "});", - "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", - "});", - "", - "// Result", - "pm.test(\"result body should include messages \\\"Metadata name should be a/an String value\\\"\", () => {", - " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Metadata name should be a/an String value');", - "});", - "" + "// Multiple scenarios handled at one place", + "pm.test(\"Response contains DIAL code\", function () {", + " const responseJson = pm.response.json();", + " var req = JSON.parse(request.data);", + " if(req.request.dialcodes.count > 1000){", + " pm.response.to.have.status(403);", + " } else {", + " const reservedDialcodes = responseJson.result.reservedDialcodes;", + " pm.expect(reservedDialcodes).not.null", + " }", + " ", + "});" ], "type": "text/javascript" } } ], - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true - } - }, "request": { "method": "POST", "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" - }, { "key": "Authorization", "value": "{{kong_api_key}}" }, { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": 423432,\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 7\n }\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/create", + "raw": "{{host}}/api/collection/v1/dialcode/reserve/{{collection_id}}", "host": [ "{{host}}" ], "path": [ "api", - "content", - "v2", - "create" + "collection", + "v1", + "dialcode", + "reserve", + "{{collection_id}}" ] - }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, "response": [] - }, + } + ] + }, + { + "name": "Content Link DIAL code", + "item": [ { - "name": "400 - name empty", + "name": "Link DIAL code", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 400\", function () {", - " pm.response.to.have.status(400)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.not.be.empty;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", - "});", - "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", - "});", - "", - "// Result", - "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", - " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", - "});", - "" + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(function(){}, 1000);" ], "type": "text/javascript" } } ], - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true - } - }, "request": { "method": "POST", "header": [ { - "key": "Content-Type", - "value": "application/json" + "key": "X-Channel-ID", + "value": "{{channel_id}}" }, { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" + "key": "Content-Type", + "value": "application/json" }, { "key": "Authorization", "value": "{{kong_api_key}}" }, { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" + "key": "x-authenticated-user-token", + "value": "{{user-token}}" } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": [{\n \"identifier\": [\"{{collection_id}}\"],\n \"dialcode\": [\"{{new_dialcode}}\"]\n }]\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/create", + "raw": "{{host}}/api/collection/v1/dialcode/link/{{collection_id}}", "host": [ "{{host}}" ], "path": [ "api", - "content", - "v2", - "create" + "collection", + "v1", + "dialcode", + "link", + "{{collection_id}}" ] - }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, "response": [] }, { - "name": "400 - missing code", + "name": "Update linked DIAL code", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 400\", function () {", - " pm.response.to.have.status(400)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.not.be.empty;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", - "});", - "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", - "});", - "", - "// Result", - "pm.test(\"result body should include messages \\\"Required Metadata code not set\\\"\", () => {", - " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Required Metadata code not set');", - "});", - "" + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(function(){}, 1000);" ], "type": "text/javascript" } } ], - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true - } - }, "request": { "method": "POST", "header": [ { - "key": "Content-Type", - "value": "application/json" + "key": "X-Channel-ID", + "value": "{{channel_id}}" }, { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" + "key": "Content-Type", + "value": "application/json" }, { "key": "Authorization", "value": "{{kong_api_key}}" }, { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" + "key": "x-authenticated-user-token", + "value": "{{user-token}}" } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": [{\n \"identifier\": [\"{{collection_id}}\"],\n \"dialcode\": [\"{{replaced_dialcode}}\"]\n }]\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/create", + "raw": "{{host}}/api/collection/v1/dialcode/link/{{collection_id}}", "host": [ "{{host}}" ], "path": [ "api", - "content", - "v2", - "create" + "collection", + "v1", + "dialcode", + "link", + "{{collection_id}}" ] - }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, "response": [] - }, + } + ] + }, + { + "name": "Content Publish API", + "item": [ { - "name": "400 - missing mimeType", - "event": [ + "name": "Pre-requisite", + "item": [ { - "listen": "test", - "script": { - "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 400\", function () {", - " pm.response.to.have.status(400)", - "});", + "name": "Collection Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.environment.set(\"collection_id\", jsonResponse.result.identifier);", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Sample Collection\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.content-collection\",\n \"primaryCategory\": \"Digital Textbook\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "TOC Upload", + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "fileUrl", + "value": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/hierarchy/do_113316820811522048194/createtoc.csv", + "type": "text" + } + ] + }, + "url": { + "raw": "{{host}}/api/collection/v1/import/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "collection", + "v1", + "import", + "{{collection_id}}" + ] + } + }, + "response": [] + }, + { + "name": "PDF Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"pdf_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/assets/do_2136088747812372481510/samplepdf.pdf\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "MP4 Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"mp4_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"video/mp4\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/assets/do_21360643694649344011752/draftversion.mp4\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "WEBM Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"webm_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"video/webm\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/assets/do_21360604894303027211507/big-buck-bunny_trailer.webm\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "HTML Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"html_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.html-archive\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/do_21357841995316428811795/artifact/2.-ekiikrnn-kii-prkrti-output-3_1657521986480_1657522093104.zip\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "H5P Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"h5p_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.h5p-archive\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/do_2136088263163084801476/artifact/1661233685237_do_2136088263163084801476.zip\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "ECML Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"ecml_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.ecml-archive\",\n \"primaryCategory\": \"Explanation Content\",\n \"body\": \"{\\\"theme\\\":{\\\"id\\\":\\\"theme\\\",\\\"version\\\":\\\"1.0\\\",\\\"startStage\\\":\\\"463caa09-b78e-412c-ae20-a2776c76b4a0\\\",\\\"stage\\\":[{\\\"x\\\":0,\\\"y\\\":0,\\\"w\\\":100,\\\"h\\\":100,\\\"id\\\":\\\"463caa09-b78e-412c-ae20-a2776c76b4a0\\\",\\\"rotate\\\":null,\\\"config\\\":{\\\"__cdata\\\":\\\"{\\\\\\\"opacity\\\\\\\":100,\\\\\\\"strokeWidth\\\\\\\":1,\\\\\\\"stroke\\\\\\\":\\\\\\\"rgba(255, 255, 255, 0)\\\\\\\",\\\\\\\"autoplay\\\\\\\":false,\\\\\\\"visible\\\\\\\":true,\\\\\\\"color\\\\\\\":\\\\\\\"#FFFFFF\\\\\\\",\\\\\\\"genieControls\\\\\\\":false,\\\\\\\"instructions\\\\\\\":\\\\\\\"\\\\\\\"}\\\"},\\\"manifest\\\":{\\\"media\\\":[]},\\\"shape\\\":[{\\\"type\\\":\\\"ellipse\\\",\\\"x\\\":15,\\\"y\\\":15,\\\"fill\\\":\\\"#00FF00\\\",\\\"w\\\":18,\\\"h\\\":32,\\\"stroke\\\":\\\"rgba(255, 255, 255, 0)\\\",\\\"strokeWidth\\\":1,\\\"opacity\\\":1,\\\"rotate\\\":0,\\\"r\\\":64.8,\\\"z-index\\\":0,\\\"id\\\":\\\"7e35536a-1e50-4ada-872e-416b04da61a0\\\",\\\"config\\\":{\\\"__cdata\\\":\\\"{\\\\\\\"opacity\\\\\\\":100,\\\\\\\"strokeWidth\\\\\\\":1,\\\\\\\"stroke\\\\\\\":\\\\\\\"rgba(255, 255, 255, 0)\\\\\\\",\\\\\\\"autoplay\\\\\\\":false,\\\\\\\"visible\\\\\\\":true,\\\\\\\"color\\\\\\\":\\\\\\\"#00FF00\\\\\\\",\\\\\\\"radius\\\\\\\":64.8}\\\"}}]}],\\\"manifest\\\":{\\\"media\\\":[{\\\"id\\\":\\\"d91cc898-8885-4642-9e55-d16bd502d946\\\",\\\"plugin\\\":\\\"org.ekstep.navigation\\\",\\\"ver\\\":\\\"1.0\\\",\\\"src\\\":\\\"/content-plugins/org.ekstep.navigation-1.0/renderer/controller/navigation_ctrl.js\\\",\\\"type\\\":\\\"js\\\"},{\\\"id\\\":\\\"e02a792e-b75e-4eea-bae0-58666a4ee5c2\\\",\\\"plugin\\\":\\\"org.ekstep.navigation\\\",\\\"ver\\\":\\\"1.0\\\",\\\"src\\\":\\\"/content-plugins/org.ekstep.navigation-1.0/renderer/templates/navigation.html\\\",\\\"type\\\":\\\"js\\\"},{\\\"id\\\":\\\"org.ekstep.navigation\\\",\\\"plugin\\\":\\\"org.ekstep.navigation\\\",\\\"ver\\\":\\\"1.0\\\",\\\"src\\\":\\\"/content-plugins/org.ekstep.navigation-1.0/renderer/plugin.js\\\",\\\"type\\\":\\\"plugin\\\"},{\\\"id\\\":\\\"org.ekstep.navigation_manifest\\\",\\\"plugin\\\":\\\"org.ekstep.navigation\\\",\\\"ver\\\":\\\"1.0\\\",\\\"src\\\":\\\"/content-plugins/org.ekstep.navigation-1.0/manifest.json\\\",\\\"type\\\":\\\"json\\\"}]},\\\"plugin-manifest\\\":{\\\"plugin\\\":[{\\\"id\\\":\\\"org.ekstep.navigation\\\",\\\"ver\\\":\\\"1.0\\\",\\\"type\\\":\\\"plugin\\\",\\\"depends\\\":\\\"\\\"}]},\\\"compatibilityVersion\\\":2}}\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "EPUB Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"epub_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/epub\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://sunbirdstagingpublic.blob.core.windows.net/sunbird-content-staging/content/assets/do_2136085231556526081377/faulkner-sound-and-the-fury.epub\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "Youtube Content Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"yt_content_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"video/x-youtube\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://www.youtube.com/watch?v=fkLcI4R7unE\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "Plugin Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"plugin_id\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"org.ekstep.summary-test\",\n \"mimeType\": \"application/vnd.ekstep.plugin-archive\",\n \"primaryCategory\": \"Explanation Content\",\n \"artifactUrl\": \"https://ntpproductionall.blob.core.windows.net/ntp-content-production/content/org.ekstep.summary/artifact/org.ekstep.summary-1.0-1_1574060894628.zip\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + } + ] + }, + { + "name": "Test Cases", + "item": [ + { + "name": "Collection Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/collection/v1/publish/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "collection", + "v1", + "publish", + "{{collection_id}}" + ] + } + }, + "response": [] + }, + { + "name": "PDF Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{pdf_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{pdf_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "MP4 Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{mp4_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{mp4_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "WEBM Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{webm_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{webm_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "HTML Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{html_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{html_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "H5P Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{h5p_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{h5p_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "EPUB Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{epub_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{epub_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "ECML Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{ecml_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{ecml_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Youtube Content Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{yt_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{yt_content_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Plugin Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{plugin_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{plugin_id}}" + ] + } + }, + "response": [] + } + ] + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "//Verification", + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200)", + "});", + "//code name contains a string", + "tests[\"Status code name has string OK\"] = responseCode.name.has(\"OK\");", + "", + "// pm.test(\"Content-Encoding header is present\", () => {", + "// pm.response.to.have.header(\"Content-Encoding\");", + "// });", + "// pm.test(\"Content-Encoding header is gzip\", () => {", + "// pm.expect(pm.response.headers.get('Content-Encoding')).to.eql('gzip');", + "// });", + "", + "pm.test(\"Verify keys and data type of the params in positive scenario\", () => {", + " pm.expect(jsonResponse.params.resmsgid).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.msgid).to.be.null;", + " pm.expect(jsonResponse.params.err).to.be.null;", + " pm.expect(jsonResponse.params.status).to.be.a(\"string\");", + " pm.expect(jsonResponse.params.errmsg).to.be.null;", + "});", + "", + "pm.test(\"params.status should be \\\"successful\\\"\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"successful\");", + "});", + "pm.test(\"responseCode should be OK\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"OK\");", + "});" + ] + } + } + ] + }, + { + "name": "Negative", + "item": [ + { + "name": "Content Create", + "item": [ + { + "name": "400 - missing channel", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata channel not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata channel not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "disabled": true + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - empty channel", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata channel not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata channel not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - missing name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - name: invalid datatype", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Metadata name should be a/an String value\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Metadata name should be a/an String value');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": 423432,\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - name empty", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - missing code", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata code not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata code not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - missing mimeType", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Required Metadata mimeType not set\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata mimeType not set');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - invalid mimeType", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"Metadata mimeType should be one of: [application/vnd.ekstep.ecml-archive, application/vnd.ekstep.html-archive, application/vnd.android.package-archive, application/vnd.ekstep.content-archive, application/vnd.ekstep.content-collection, application/vnd.ekstep.plugin-archive, application/vnd.ekstep.h5p-archive, application/epub, text/x-url, video/x-youtube, application/octet-stream, application/msword, application/pdf, image/jpeg, image/jpg, image/png, image/tiff, image/bmp, image/gif, image/svg+xml, video/avi, video/mpeg, video/quicktime, video/3gpp, video/mp4, video/ogg, video/webm, audio/mp3, audio/mp4, audio/mpeg, audio/ogg, audio/webm, audio/x-wav, audio/wav, application/json, application/quiz]\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('Metadata mimeType should be one of: [application/vnd.ekstep.ecml-archive, application/vnd.ekstep.html-archive, application/vnd.android.package-archive, application/vnd.ekstep.content-archive, application/vnd.ekstep.content-collection, application/vnd.ekstep.plugin-archive, application/vnd.ekstep.h5p-archive, application/epub, text/x-url, video/x-youtube, application/octet-stream, application/msword, application/pdf, image/jpeg, image/jpg, image/png, image/tiff, image/bmp, image/gif, image/svg+xml, video/avi, video/mpeg, video/quicktime, video/3gpp, video/mp4, video/ogg, video/webm, audio/mp3, audio/mp4, audio/mpeg, audio/ogg, audio/webm, audio/x-wav, audio/wav, application/json, application/quiz]');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"some-mimeType\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - missing primaryCategory", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"VALIDATION_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"VALIDATION_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"primaryCategory is a mandatory parameter\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"primaryCategory is a mandatory parameter\");", + "});", + "", + "// Result", + "pm.test(\"result body should be empty\", () => {", + " pm.expect(jsonResponse.result).to.eql({});", + " pm.expect(jsonResponse.result).to.be.empty;", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - Invalid subject", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.not.be.empty;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.errmsg should be \\\"Validation Errors.\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors.\");", + "});", + "", + "// Result", + "pm.test(\"result body should include messages \\\"subject range data is empty from the given framework.\\\"\", () => {", + " pm.expect(jsonResponse.result.messages).to.have.length(1)", + " pm.expect(jsonResponse.result.messages).to.include('subject range data is empty from the given framework.');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12-erwe\",\n \"subject\": [\"test\"],\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "404 - Invalid primaryCategory", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 404\", () => {", + " pm.response.to.have.status(404)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.be.null;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"404\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"404\");", + "});", + "pm.test(`params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}\\\"`, () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(`Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}`);", + "});", + "", + "// Result", + "pm.test(\"messages should be null\", () => {", + " pm.expect(jsonResponse.result.messages).to.eql(null);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": { + "connection": true + } + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"aabaa\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "pm.test(\"id should be api.content.create\", () => {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});" + ] + } + } + ] + }, + { + "name": "Content Read", + "item": [ + { + "name": "404 - Not Found", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", + "", + "pm.test(\"Test data type of the response and keys\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.be.null;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"id should be api.content.read\", () => {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.read\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"NOT_FOUND\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"NOT_FOUND\");", + "});", + "pm.test(\"params.status should be \\\"failed\\\"\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "});", + "pm.test(`params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get('invalid_content_id')}\\\"`, () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(`Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get('invalid_content_id')}`);", + "});", + "", + "// Result", + "pm.test(\"messages should be null\", () => {", + " pm.expect(jsonResponse.result.messages).to.eql(null);", + "});", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.globals.set('invalid_content_id', 'do_42353245436534');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + } + ], + "url": { + "raw": "{{host}}/api/content/v2/read/{{invalid_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "read", + "{{invalid_content_id}}" + ] + }, + "description": "Fetch a particular Batch\nThis API is associated with fetching a particular batch on the Sunbird Platform.\nThe endpoint for Fetch a particular Batch is /batch/read/{Batch_ID}\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Content Update", + "item": [ + { + "name": "400 - Invalid versionKey", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", + "//code name contains a string", + "tests[\"Status code name has string Bad Request\"] = responseCode.name.has(\"Bad Request\");", + "", + "pm.test(\"Content-Encoding header should not present\", () => {", + " pm.response.to.not.have.header(\"Content-Encoding\");", + "});", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.be.null;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be CLIENT_ERROR\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be CLIENT_ERROR\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", + "});", + "pm.test(\"params.status should be failed\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "});", + "pm.test(\"params.errmsg should be \\\"Invalid version Key\\\"\", () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(\"Invalid version Key\");", + "});", + "", + "// Result", + "pm.test(\"messages should be null\", () => {", + " pm.expect(jsonResponse.result.messages).to.eql(null);", + "});", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.globals.set('invalid-versionKey', '3534534543');", + "// pm.globals.set(\"content_id\", '');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{invalid-versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "update", + "{{content_id}}" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "400 - Empty name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 400\", () => {", + " pm.response.to.have.status(400)", + "});", "//code name contains a string", "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", "", @@ -1395,9 +7379,9 @@ "});", "", "// Result", - "pm.test(\"result body should include messages \\\"Required Metadata mimeType not set\\\"\", () => {", + "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Required Metadata mimeType not set');", + " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", "});", "" ], @@ -1405,25 +7389,216 @@ } } ], - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/update/{{content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "update", + "{{content_id}}" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + }, + "response": [] + }, + { + "name": "404 - Invalid content id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 404\", () => {", + " pm.response.to.have.status(404)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.be.null;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be NOT_FOUND\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"NOT_FOUND\");", + "});", + "pm.test(`params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"invalid_content_id\")}\\\"`, () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(`Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"invalid_content_id\")}`);", + "});", + "", + "// Result", + "pm.test(\"messages should be null\", () => {", + " pm.expect(jsonResponse.result.messages).to.eql(null);", + "});", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.globals.set(\"invalid_content_id\", 'do_21357909972698726412211');" + ], + "type": "text/javascript" + } } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "type": "text" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/update/{{invalid_content_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "update", + "{{invalid_content_id}}" + ] + }, + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." }, + "response": [] + }, + { + "name": "404 - Invalid primaryCategory", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 404\", () => {", + " pm.response.to.have.status(404)", + "});", + "//code name contains a string", + "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", + "", + "pm.test(\"Verify keys and data type of the response result\", () => {", + " pm.expect(jsonResponse.result).to.be.an(\"object\");", + " pm.expect(jsonResponse.result).to.have.all.keys('messages');", + " pm.expect(jsonResponse.result.messages).to.be.null;", + "});", + "", + "//Validation", + "// Response body", + "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", + " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", + "});", + "", + "// Params", + "pm.test(\"params.err should be \\\"404\\\"\", () => {", + " pm.expect(jsonResponse.params.err).to.eql(\"404\");", + "});", + "pm.test(\"params.status should be \\\"failed\\\"\", () => {", + " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", + "});", + "pm.test(`params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}\\\"`, () => {", + " pm.expect(jsonResponse.params.errmsg).to.eql(`Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}`);", + "});", + "", + "pm.test(\"messages should be null\", () => {", + " pm.expect(jsonResponse.result.messages).to.eql(null);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], "request": { - "method": "POST", + "method": "PATCH", "header": [ { "key": "Content-Type", - "value": "application/json" + "value": "application/json", + "type": "text" }, { "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" + "value": "{{keycloak_access_token}}", + "type": "text" }, { "key": "Authorization", - "value": "{{kong_api_key}}" + "value": "{{kong_api_key}}", + "type": "text" }, { "key": "X-Channel-Id", @@ -1433,10 +7608,10 @@ ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/create", + "raw": "{{host}}/api/content/v2/update/{{content_id}}", "host": [ "{{host}}" ], @@ -1444,463 +7619,375 @@ "api", "content", "v2", - "create" + "update", + "{{content_id}}" ] }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." }, "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "// pm.globals.set(\"content_id\", '');" + ] + } }, { - "name": "400 - invalid mimeType", + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "let jsonResponse = pm.response.json();", + "", + "pm.test(\"id should be api.content.update\", () => {", + " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", + "});", + "pm.test(\"ver should be 4.0\", () => {", + " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", + "});" + ] + } + } + ] + }, + { + "name": "Content Reserve DIAL code", + "item": [ + { + "name": "Reserve DIAL code with Invalid channel Id in header", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", "pm.test(\"Status code is 400\", function () {", - " pm.response.to.have.status(400)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.not.be.empty;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", - "});", - "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + " pm.response.to.have.status(400);", "});", "", - "// Result", - "pm.test(\"result body should include messages \\\"Metadata mimeType should be one of: [application/vnd.ekstep.ecml-archive, application/vnd.ekstep.html-archive, application/vnd.android.package-archive, application/vnd.ekstep.content-archive, application/vnd.ekstep.content-collection, application/vnd.ekstep.plugin-archive, application/vnd.ekstep.h5p-archive, application/epub, text/x-url, video/x-youtube, application/octet-stream, application/msword, application/pdf, image/jpeg, image/jpg, image/png, image/tiff, image/bmp, image/gif, image/svg+xml, video/avi, video/mpeg, video/quicktime, video/3gpp, video/mp4, video/ogg, video/webm, audio/mp3, audio/mp4, audio/mpeg, audio/ogg, audio/webm, audio/x-wav, audio/wav, application/json, application/quiz]\\\"\", () => {", - " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Metadata mimeType should be one of: [application/vnd.ekstep.ecml-archive, application/vnd.ekstep.html-archive, application/vnd.android.package-archive, application/vnd.ekstep.content-archive, application/vnd.ekstep.content-collection, application/vnd.ekstep.plugin-archive, application/vnd.ekstep.h5p-archive, application/epub, text/x-url, video/x-youtube, application/octet-stream, application/msword, application/pdf, image/jpeg, image/jpg, image/png, image/tiff, image/bmp, image/gif, image/svg+xml, video/avi, video/mpeg, video/quicktime, video/3gpp, video/mp4, video/ogg, video/webm, audio/mp3, audio/mp4, audio/mpeg, audio/ogg, audio/webm, audio/x-wav, audio/wav, application/json, application/quiz]');", - "});", - "" + "pm.test(\"Response throws ERR_INVALID_CHANNEL\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_INVALID_CHANNEL\") ", + "});" ], "type": "text/javascript" } } ], - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true - } - }, "request": { "method": "POST", "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" - }, { "key": "Authorization", "value": "{{kong_api_key}}" }, { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "dummy" } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"some-mimeType\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 3,\n \"qrCodeSpec\": {\n \"errorCorrectionLevel\": \"H\"\n }\n }\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/create", + "raw": "{{host}}/api/collection/v1/dialcode/reserve/{{collection_id}}", "host": [ "{{host}}" ], "path": [ "api", - "content", - "v2", - "create" + "collection", + "v1", + "dialcode", + "reserve", + "{{collection_id}}" ] - }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, "response": [] }, { - "name": "400 - missing primaryCategory", + "name": "Reserve DIAL code with Zero count", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 400\", () => {", - " pm.response.to.have.status(400)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"VALIDATION_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"VALIDATION_ERROR\");", - "});", - "pm.test(\"params.errmsg should be \\\"primaryCategory is a mandatory parameter\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"primaryCategory is a mandatory parameter\");", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", "});", "", - "// Result", - "pm.test(\"result body should be empty\", () => {", - " pm.expect(jsonResponse.result).to.eql({});", - " pm.expect(jsonResponse.result).to.be.empty;", - "});", - "" + "pm.test(\"Response throws ERR_INVALID_COUNT_RANGE\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_INVALID_COUNT_RANGE\") ", + "});" ], "type": "text/javascript" } } ], - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true - } - }, "request": { "method": "POST", "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" - }, { "key": "Authorization", "value": "{{kong_api_key}}" }, { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 0,\n \"qrCodeSpec\": {\n \"errorCorrectionLevel\": \"H\"\n }\n }\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/create", + "raw": "{{host}}/api/collection/v1/dialcode/reserve/{{collection_id}}", "host": [ "{{host}}" ], "path": [ "api", - "content", - "v2", - "create" + "collection", + "v1", + "dialcode", + "reserve", + "{{collection_id}}" ] - }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, "response": [] }, { - "name": "400 - Invalid subject", + "name": "Reserve DIAL code with negative count", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 400\", () => {", - " pm.response.to.have.status(400)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.not.be.empty;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", - "});", - "pm.test(\"params.errmsg should be \\\"Validation Errors.\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors.\");", + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", "});", "", - "// Result", - "pm.test(\"result body should include messages \\\"subject range data is empty from the given framework.\\\"\", () => {", - " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('subject range data is empty from the given framework.');", - "});", - "" + "pm.test(\"Response throws ERR_INVALID_COUNT_RANGE\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_INVALID_COUNT_RANGE\") ", + "});" ], "type": "text/javascript" } } ], - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true - } - }, "request": { "method": "POST", "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, { "key": "Content-Type", "value": "application/json" }, { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" - }, + "key": "X-Channel-ID", + "value": "{{channel_id}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": -2,\n \"qrCodeSpec\": {\n \"errorCorrectionLevel\": \"H\"\n }\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/collection/v1/dialcode/reserve/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "collection", + "v1", + "dialcode", + "reserve", + "{{collection_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Reserve DIAL code with count greater than max limit(250)", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws ERR_INVALID_COUNT_RANGE\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_INVALID_COUNT_RANGE\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ { "key": "Authorization", "value": "{{kong_api_key}}" }, { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12-erwe\",\n \"subject\": [\"test\"],\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 251,\n \"qrCodeSpec\": {\n \"errorCorrectionLevel\": \"H\"\n }\n }\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/create", + "raw": "{{host}}/api/collection/v1/dialcode/reserve/{{collection_id}}", "host": [ "{{host}}" ], "path": [ "api", - "content", - "v2", - "create" + "collection", + "v1", + "dialcode", + "reserve", + "{{collection_id}}" ] - }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, "response": [] }, { - "name": "404 - Invalid primaryCategory", + "name": "Reserve DIAL code with invalid collection Id", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 404\", () => {", - " pm.response.to.have.status(404)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.be.null;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"404\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"404\");", - "});", - "pm.test(`params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}\\\"`, () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(`Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}`);", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", "});", "", - "// Result", - "pm.test(\"messages should be null\", () => {", - " pm.expect(jsonResponse.result.messages).to.eql(null);", - "});", - "" + "pm.test(\"Response throws RESOURCE_NOT_FOUND\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"RESOURCE_NOT_FOUND\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"NOT_FOUND\") ", + "});" ], "type": "text/javascript" } } ], - "protocolProfileBehavior": { - "disabledSystemHeaders": { - "connection": true - } - }, "request": { "method": "POST", "header": [ - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}" - }, { "key": "Authorization", "value": "{{kong_api_key}}" }, { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"createdBy\": \"530b19ea-dc8d-4cc7-a4b5-0c0214c8113a\",\n \"resourceType\": \"Learn\",\n \"framework\": \"ekstep_ncert_k-12\",\n \"primaryCategory\": \"aabaa\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 25,\n \"qrCodeSpec\": {\n \"errorCorrectionLevel\": \"H\"\n }\n }\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/create", + "raw": "{{host}}/api/collection/v1/dialcode/reserve/do_dummy_id", "host": [ "{{host}}" ], "path": [ "api", - "content", - "v2", - "create" + "collection", + "v1", + "dialcode", + "reserve", + "do_dummy_id" ] - }, - "description": "This API is associated with batch creation\nThe endpoint for Creates a Batch is /batch/create\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, "response": [] } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "let jsonResponse = pm.response.json();", - "", - "pm.test(\"id should be api.content.create\", () => {", - " pm.expect(jsonResponse.id).to.eql(\"api.content.create\");", - "});", - "pm.test(\"ver should be 4.0\", () => {", - " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", - "});" - ] - } - } ] }, { - "name": "Content Read", + "name": "Content Link DIAL code", "item": [ { - "name": "404 - Not Found", + "name": "Link DIAL code with invalid collection id in the URL", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", "pm.test(\"Status code is 404\", function () {", - " pm.response.to.have.status(404)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", - "", - "pm.test(\"Test data type of the response and keys\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.be.null;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"id should be api.content.read\", () => {", - " pm.expect(jsonResponse.id).to.eql(\"api.content.read\");", - "});", - "pm.test(\"ver should be 4.0\", () => {", - " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", - "});", - "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"NOT_FOUND\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"NOT_FOUND\");", - "});", - "pm.test(\"params.status should be \\\"failed\\\"\", () => {", - " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", - "});", - "pm.test(`params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get('invalid_content_id')}\\\"`, () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(`Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get('invalid_content_id')}`);", + " pm.response.to.have.status(404);", "});", "", - "// Result", - "pm.test(\"messages should be null\", () => {", - " pm.expect(jsonResponse.result.messages).to.eql(null);", - "});", - "" + "pm.test(\"Response throws RESOURCE_NOT_FOUND\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"RESOURCE_NOT_FOUND\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"NOT_FOUND\") ", + "});" ], "type": "text/javascript" } @@ -1909,116 +7996,72 @@ "listen": "prerequest", "script": { "exec": [ - "pm.globals.set('invalid_content_id', 'do_42353245436534');" + "setTimeout(function(){}, 1000);" ], "type": "text/javascript" } } ], "request": { - "method": "GET", + "method": "POST", "header": [ { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}", - "type": "text" + "key": "X-Channel-ID", + "value": "{{channel_id}}" + }, + { + "key": "Content-Type", + "value": "application/json" }, { "key": "Authorization", - "value": "{{kong_api_key}}", - "type": "text" + "value": "{{kong_api_key}}" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}" } ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": [{\n \"identifier\": [\"{{collection_id}}\"],\n \"dialcode\": [\"{{new_dialcode}}\"]\n }]\n }\n}" + }, "url": { - "raw": "{{host}}/api/content/v2/read/{{invalid_content_id}}", + "raw": "{{host}}/api/collection/v1/dialcode/link/do_dummy_id", "host": [ "{{host}}" ], "path": [ "api", - "content", - "v2", - "read", - "{{invalid_content_id}}" + "collection", + "v1", + "dialcode", + "link", + "do_dummy_id" ] - }, - "description": "Fetch a particular Batch\nThis API is associated with fetching a particular batch on the Sunbird Platform.\nThe endpoint for Fetch a particular Batch is /batch/read/{Batch_ID}\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } }, { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "" - ] - } - } - ] - }, - { - "name": "Content Update", - "item": [ - { - "name": "400 - Invalid versionKey", + "name": "Link DIAL code with invalid collection id in the request body", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 400\", () => {", - " pm.response.to.have.status(400)", - "});", - "//code name contains a string", - "tests[\"Status code name has string Bad Request\"] = responseCode.name.has(\"Bad Request\");", - "", - "pm.test(\"Content-Encoding header should not present\", () => {", - " pm.response.to.not.have.header(\"Content-Encoding\");", - "});", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.be.null;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be CLIENT_ERROR\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be CLIENT_ERROR\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", - "});", - "pm.test(\"params.status should be failed\", () => {", - " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", - "});", - "pm.test(\"params.errmsg should be \\\"Invalid version Key\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Invalid version Key\");", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", "});", "", - "// Result", - "pm.test(\"messages should be null\", () => {", - " pm.expect(jsonResponse.result.messages).to.eql(null);", - "});", - "" + "pm.test(\"Response throws RESOURCE_NOT_FOUND\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"RESOURCE_NOT_FOUND\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_DIALCODE_LINK\") ", + "});" ], "type": "text/javascript" } @@ -2027,369 +8070,5281 @@ "listen": "prerequest", "script": { "exec": [ - "pm.globals.set('invalid-versionKey', '3534534543');", - "// pm.globals.set(\"content_id\", '');" + "setTimeout(function(){}, 1000);" ], "type": "text/javascript" } } ], "request": { - "method": "PATCH", + "method": "POST", "header": [ { - "key": "Content-Type", - "value": "application/json", - "type": "text" + "key": "X-Channel-ID", + "value": "{{channel_id}}" }, { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}", - "type": "text" + "key": "Content-Type", + "value": "application/json" }, { "key": "Authorization", - "value": "{{kong_api_key}}", - "type": "text" + "value": "{{kong_api_key}}" }, { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" + "key": "x-authenticated-user-token", + "value": "{{user-token}}" } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{invalid-versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": [{\n \"identifier\": [\"do_dummy_Id\"],\n \"dialcode\": [\"{{new_dialcode}}\"]\n }]\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/update/{{content_id}}", + "raw": "{{host}}/api/collection/v1/dialcode/link/{{collection_id}}", "host": [ "{{host}}" - ], - "path": [ - "api", - "content", - "v2", - "update", - "{{content_id}}" + ], + "path": [ + "api", + "collection", + "v1", + "dialcode", + "link", + "{{collection_id}}" ] - }, - "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, "response": [] }, { - "name": "400 - Empty name", + "name": "Link DIAL code with invalid DIAL code in the request body", "event": [ { "listen": "test", "script": { "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 400\", () => {", - " pm.response.to.have.status(400)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Bad Request\\\"\"] = responseCode.name.has(\"Bad Request\");", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.not.be.empty;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"CLIENT_ERROR\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"CLIENT_ERROR\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"CLIENT_ERROR\");", - "});", - "pm.test(\"params.errmsg should be \\\"Validation Errors\\\"\", () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(\"Validation Errors\");", + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", "});", "", - "// Result", - "pm.test(\"result body should include messages \\\"Required Metadata name not set\\\"\", () => {", - " pm.expect(jsonResponse.result.messages).to.have.length(1)", - " pm.expect(jsonResponse.result.messages).to.include('Required Metadata name not set');", - "});", - "" + "pm.test(\"Response throws RESOURCE_NOT_FOUND\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"RESOURCE_NOT_FOUND\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_DIALCODE_LINK\") ", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(function(){}, 1000);" ], "type": "text/javascript" } } ], "request": { - "method": "PATCH", + "method": "POST", "header": [ { - "key": "Content-Type", - "value": "application/json", - "type": "text" + "key": "X-Channel-ID", + "value": "{{channel_id}}" }, { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}", - "type": "text" + "key": "Content-Type", + "value": "application/json" }, { "key": "Authorization", - "value": "{{kong_api_key}}", - "type": "text" + "value": "{{kong_api_key}}" }, { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" + "key": "x-authenticated-user-token", + "value": "{{user-token}}" } ], "body": { "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"\"\n }\n }\n}" + "raw": "{\n \"request\": {\n \"content\": [{\n \"identifier\": [\"{{collection_id}}\"],\n \"dialcode\": [\"DUMMY\"]\n }]\n }\n}" }, "url": { - "raw": "{{host}}/api/content/v2/update/{{content_id}}", + "raw": "{{host}}/api/collection/v1/dialcode/link/{{collection_id}}", "host": [ "{{host}}" ], "path": [ "api", - "content", - "v2", - "update", - "{{content_id}}" + "collection", + "v1", + "dialcode", + "link", + "{{collection_id}}" ] - }, - "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." + } }, "response": [] - }, + } + ] + }, + { + "name": "Content Publish API", + "item": [ { - "name": "404 - Invalid content id", - "event": [ + "name": "Pre-requisite", + "item": [ { - "listen": "test", - "script": { - "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 404\", () => {", - " pm.response.to.have.status(404)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.be.null;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be NOT_FOUND\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"NOT_FOUND\");", - "});", - "pm.test(`params.errmsg should be \\\"Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"invalid_content_id\")}\\\"`, () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(`Error! Node(s) doesn't Exists. | [Invalid Node Id.]: ${pm.globals.get(\"invalid_content_id\")}`);", - "});", - "", - "// Result", - "pm.test(\"messages should be null\", () => {", - " pm.expect(jsonResponse.result.messages).to.eql(null);", - "});", - "" + "name": "Collection Create wo hierarchy", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.environment.set(\"collection_id_wo_hierarchy\", jsonResponse.result.identifier);", + "pm.globals.set(\"collection_id_wo_hierarchy\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Sample Collection\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.content-collection\",\n \"primaryCategory\": \"Digital Textbook\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "PDF Content wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"pdf_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "MP4 Content Create wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"mp4_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"video/mp4\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "WEBM Content Create wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"webm_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"video/webm\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "HTML Content Create wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"html_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.html-archive\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "H5P Content Create wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"h5p_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.h5p-archive\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "ECML Content Create invalid body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"ecml_content_id_invalid_body\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.ecml-archive\",\n \"primaryCategory\": \"Explanation Content\",\n \"body\": \"dummy\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "ECML Content Create wo body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"ecml_content_id_wo_body\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.ecml-archive\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "EPUB Content Create wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"epub_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/epub\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "Youtube Content Create wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"yt_content_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"video/x-youtube\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + }, + { + "name": "Plugin Create wo artifact", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.globals.set(\"plugin_id_wo_artifact\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"test-plugin\",\n \"mimeType\": \"application/vnd.ekstep.plugin-archive\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [ + { + "name": "Content Create - 200 OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:42:53 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999995" + }, + { + "key": "request-time", + "value": "34" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "36" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "40" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "41" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:42:53ZZ\",\n \"params\": {\n \"resmsgid\": \"a06bcfc7-23b6-494a-8a63-bbdee8c6e373\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"identifier\": \"do_21358408067678208014\",\n \"node_id\": \"do_21358408067678208014\",\n \"versionKey\": \"1658212973248\"\n }\n}" + }, + { + "name": "Content Create - 400 Bad Request", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"Explanation Content\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:28:26 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Content-Length", + "value": "297" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999998" + }, + { + "key": "request-time", + "value": "11" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "13" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "18" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "125" + }, + { + "key": "Via", + "value": "kong/0.14.1" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:28:26ZZ\",\n \"params\": {\n \"resmsgid\": \"7efe066b-39e0-4f03-a569-0e9f19e8822b\",\n \"msgid\": null,\n \"err\": \"CLIENT_ERROR\",\n \"status\": \"failed\",\n \"errmsg\": \"Validation Errors\"\n },\n \"responseCode\": \"CLIENT_ERROR\",\n \"result\": {\n \"messages\": [\n \"Required Metadata name not set\"\n ]\n }\n}" + }, + { + "name": "Content Create - 404 Not Found", + "originalRequest": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Untitled Content\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/pdf\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/create", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "create" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Date", + "value": "Tue, 19 Jul 2022 06:33:43 GMT" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Transfer-Encoding", + "value": "chunked" + }, + { + "key": "Connection", + "value": "keep-alive" + }, + { + "key": "Vary", + "value": "Accept-Encoding" + }, + { + "key": "X-RateLimit-Limit-hour", + "value": "1000000" + }, + { + "key": "X-RateLimit-Remaining-hour", + "value": "999997" + }, + { + "key": "request-time", + "value": "16" + }, + { + "key": "x-envoy-upstream-service-time", + "value": "18" + }, + { + "key": "Access-Control-Allow-Origin", + "value": "*" + }, + { + "key": "X-Kong-Upstream-Latency", + "value": "23" + }, + { + "key": "X-Kong-Proxy-Latency", + "value": "115" + }, + { + "key": "Via", + "value": "kong/0.14.1" + }, + { + "key": "Content-Encoding", + "value": "gzip" + } + ], + "cookie": [], + "body": "{\n \"id\": \"api.content.create\",\n \"ver\": \"4.0\",\n \"ts\": \"2022-07-19T06:33:43ZZ\",\n \"params\": {\n \"resmsgid\": \"78745a2e-004b-4422-99e4-e2494387b3d4\",\n \"msgid\": null,\n \"err\": \"404\",\n \"status\": \"failed\",\n \"errmsg\": \"Entry is not found in cassandra for content with identifier: obj-cat:abcd_content_all {}\"\n },\n \"responseCode\": \"RESOURCE_NOT_FOUND\",\n \"result\": {\n \"messages\": null\n }\n}" + } + ] + } + ] + }, + { + "name": "Test Cases", + "item": [ + { + "name": "Invalid Content ID Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } ], - "type": "text/javascript" - } + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/do_dummy_id", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "do_dummy_id" + ] + } + }, + "response": [] }, { - "listen": "prerequest", - "script": { - "exec": [ - "pm.globals.set(\"invalid_content_id\", 'do_21357909972698726412211');" + "name": "Invalid Collection ID Publish", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Content-Type", - "value": "application/json", - "type": "text" + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/collection/v1/publish/do_dummy_id", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "collection", + "v1", + "publish", + "do_dummy_id" + ] + } }, - { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}", - "type": "text" + "response": [] + }, + { + "name": "PDF Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{pdf_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{pdf_content_id_wo_artifact}}" + ] + } }, - { - "key": "Authorization", - "value": "{{kong_api_key}}", - "type": "text" + "response": [] + }, + { + "name": "MP4 Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{mp4_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{mp4_content_id_wo_artifact}}" + ] + } }, - { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"lastUpdatedBy\": \"874ed8a5-782e-4f6c-8f36-e0288455901e\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\"\n }\n }\n}" + "response": [] }, - "url": { - "raw": "{{host}}/api/content/v2/update/{{invalid_content_id}}", - "host": [ - "{{host}}" + { + "name": "WEBM Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "api", - "content", - "v2", - "update", - "{{invalid_content_id}}" - ] + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{webm_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{webm_content_id_wo_artifact}}" + ] + } + }, + "response": [] }, - "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." - }, - "response": [] - }, - { - "name": "404 - Invalid primaryCategory", - "event": [ { - "listen": "test", - "script": { - "exec": [ - "let jsonResponse = pm.response.json()", - "", - "//Verification", - "pm.test(\"Status code is 404\", () => {", - " pm.response.to.have.status(404)", - "});", - "//code name contains a string", - "tests[\"Status code name has string \\\"Not Found\\\"\"] = responseCode.name.has(\"Not Found\");", - "", - "pm.test(\"Verify keys and data type of the response result\", () => {", - " pm.expect(jsonResponse.result).to.be.an(\"object\");", - " pm.expect(jsonResponse.result).to.have.all.keys('messages');", - " pm.expect(jsonResponse.result.messages).to.be.null;", - "});", - "", - "//Validation", - "// Response body", - "pm.test(\"responseCode should be RESOURCE_NOT_FOUND\", () => {", - " pm.expect(jsonResponse.responseCode).to.eql(\"RESOURCE_NOT_FOUND\");", - "});", - "", - "// Params", - "pm.test(\"params.err should be \\\"404\\\"\", () => {", - " pm.expect(jsonResponse.params.err).to.eql(\"404\");", - "});", - "pm.test(\"params.status should be \\\"failed\\\"\", () => {", - " pm.expect(jsonResponse.params.status).to.eql(\"failed\");", - "});", - "pm.test(`params.errmsg should be \\\"Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}\\\"`, () => {", - " pm.expect(jsonResponse.params.errmsg).to.eql(`Entry is not found in cassandra for content with identifier: obj-cat:${JSON.parse(request.data).request.content.primaryCategory}_content_all {}`);", - "});", - "", - "pm.test(\"messages should be null\", () => {", - " pm.expect(jsonResponse.result.messages).to.eql(null);", - "});", - "" + "name": "HTML Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "PATCH", - "header": [ - { - "key": "Content-Type", - "value": "application/json", - "type": "text" + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{html_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{html_content_id_wo_artifact}}" + ] + } }, - { - "key": "X-Authenticated-User-token", - "value": "{{keycloak_access_token}}", - "type": "text" + "response": [] + }, + { + "name": "H5P Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{h5p_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{h5p_content_id_wo_artifact}}" + ] + } }, - { - "key": "Authorization", - "value": "{{kong_api_key}}", - "type": "text" + "response": [] + }, + { + "name": "EPUB Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{epub_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{epub_content_id_wo_artifact}}" + ] + } }, - { - "key": "X-Channel-Id", - "value": "{{channel_id}}", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"request\": {\n \"content\": {\n \"versionKey\": \"{{versionKey}}\",\n \"description\": \"dsd\",\n \"name\": \"API DOCUMENTATION CONTENT\",\n \"primaryCategory\": \"abcd\"\n }\n }\n}" + "response": [] }, - "url": { - "raw": "{{host}}/api/content/v2/update/{{content_id}}", - "host": [ - "{{host}}" + { + "name": "Youtube Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } ], - "path": [ - "api", - "content", - "v2", - "update", - "{{content_id}}" - ] + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{yt_content_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{yt_content_id_wo_artifact}}" + ] + } + }, + "response": [] }, - "description": "This API is associated with updating a batch on the Sunbird Platform.\nThe endpoint for Course Batch Update is /batch/update\nThe fields marked with an asterisk (*) are mandatory. They cannot be null or empty." - }, - "response": [] - } - ], - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "exec": [ - "// pm.globals.set(\"content_id\", '');" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "exec": [ - "let jsonResponse = pm.response.json();", - "", - "pm.test(\"id should be api.content.update\", () => {", - " pm.expect(jsonResponse.id).to.eql(\"api.content.update\");", - "});", - "pm.test(\"ver should be 4.0\", () => {", - " pm.expect(jsonResponse.ver).to.eql(\"4.0\");", - "});" - ] - } + { + "name": "Plugin Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{plugin_id_wo_artifact}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{plugin_id_wo_artifact}}" + ] + } + }, + "response": [] + }, + { + "name": "Collection Publish without hierarchy", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws ERR_COLLECTION_REVIEW\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_COLLECTION_REVIEW\") ", + "});", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(function(){}, 40000);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/collection/v1/publish/{{collection_id_wo_hierarchy}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "collection", + "v1", + "publish", + "{{collection_id_wo_hierarchy}}" + ] + } + }, + "response": [] + }, + { + "name": "ECML Content Publish wo artifactUrl", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"VALIDATOR_ERROR\") ", + "});" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(function(){}, 2000);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{ecml_content_id_wo_body}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{ecml_content_id_wo_body}}" + ] + } + }, + "response": [] + }, + { + "name": "ECML Content Publish invalid Body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws CLIENT_ERROR\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"INVALID_CONTENT_BODY\") ", + "});", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(function(){}, 1000);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "type": "text" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}", + "type": "text" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"lastPublishedBy\": \"Testing\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/api/content/v2/publish/{{ecml_content_id_invalid_body}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "content", + "v2", + "publish", + "{{ecml_content_id_invalid_body}}" + ] + } + }, + "response": [] + } + ] } ] } From 920b6024212832dbb03aa94fe3fcb87c917ed0ff Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 24 Aug 2022 12:08:52 +0530 Subject: [PATCH 074/105] Issue #KN-9 feat: Content Publish API refactor. --- ...ontent V2 API Test.postman_collection.json | 79 ++++++++++--------- .../Publish API.postman_collection.json | 48 +++++------ 2 files changed, 66 insertions(+), 61 deletions(-) diff --git a/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json b/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json index 4a0373bd6..35981e978 100644 --- a/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json +++ b/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json @@ -3,8 +3,7 @@ "_postman_id": "ec007894-70ee-4951-8e96-98f79de5908a", "name": "Content V2 API Test", "description": "The Content Management APIs allow you to create, manage and process content on the Sunbird platform. Content is the basic building block of the Knowledge Service. Some examples would be Videos, Audio, Pdfs, Html, ECML etc. The basic operations for this API include Create, Update, Read, Review, Publish.\n\nThe URL for Content Management API(s) is /content/v1.", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "1419050" + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, "item": [ { @@ -1362,7 +1361,8 @@ }, "response": [] } - ] + ], + "description": "The Content/Collection Reserve DIAL code APIs allow you to reserve DIAL codes to a content/collection on the Sunbird platform. Reserve DAIL code API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/dialcode/reserve and /collection/v1/dialcode/reserve." }, { "name": "Content Link DIAL code", @@ -1408,7 +1408,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}" + "value": "{{keycloak_access_token}}" } ], "body": { @@ -1473,7 +1473,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}" + "value": "{{keycloak_access_token}}" } ], "body": { @@ -1497,7 +1497,8 @@ }, "response": [] } - ] + ], + "description": "The Content/Collection Link DIAL code APIs allow you to link DIAL codes to content/collection/collection units on the Sunbird platform. Reserve DAIL code API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/dialcode/link and /collection/v1/dialcode/link." }, { "name": "Content Publish API", @@ -1904,7 +1905,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}" + "value": "{{keycloak_access_token}}" } ], "body": { @@ -5450,7 +5451,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -5508,7 +5509,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -5566,7 +5567,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -5624,7 +5625,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -5682,7 +5683,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -5740,7 +5741,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -5798,7 +5799,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -5856,7 +5857,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -5914,7 +5915,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -5972,7 +5973,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -6003,7 +6004,8 @@ } ] } - ] + ], + "description": "The Content/Collection Publish APIs allow you to publish content/collection on the Sunbird platform. Publish API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/publish and /collection/v1/publish." } ], "event": [ @@ -7964,7 +7966,8 @@ }, "response": [] } - ] + ], + "description": "The Content/Collection Reserve DIAL code APIs allow you to reserve DIAL codes to a content/collection on the Sunbird platform. Reserve DAIL code API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/dialcode/reserve and /collection/v1/dialcode/reserve." }, { "name": "Content Link DIAL code", @@ -8019,7 +8022,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}" + "value": "{{keycloak_access_token}}" } ], "body": { @@ -8093,7 +8096,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}" + "value": "{{keycloak_access_token}}" } ], "body": { @@ -8167,7 +8170,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}" + "value": "{{keycloak_access_token}}" } ], "body": { @@ -8191,7 +8194,8 @@ }, "response": [] } - ] + ], + "description": "The Content/Collection Link DIAL code APIs allow you to link DIAL codes to content/collection/collection units on the Sunbird platform. Reserve DAIL code API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/dialcode/link and /collection/v1/dialcode/link" }, { "name": "Content Publish API", @@ -12491,7 +12495,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -12549,7 +12553,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -12616,7 +12620,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -12683,7 +12687,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -12750,7 +12754,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -12817,7 +12821,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -12884,7 +12888,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -12951,7 +12955,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -13018,7 +13022,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -13085,7 +13089,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -13162,7 +13166,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -13238,7 +13242,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -13315,7 +13319,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -13346,7 +13350,8 @@ } ] } - ] + ], + "description": "The Content/Collection Publish APIs allow you to publish content/collection on the Sunbird platform. Publish API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/publish and /collection/v1/publish." } ], "event": [ diff --git a/content-api/api-tests/Collections/Publish API.postman_collection.json b/content-api/api-tests/Collections/Publish API.postman_collection.json index 75a526868..d060dd489 100644 --- a/content-api/api-tests/Collections/Publish API.postman_collection.json +++ b/content-api/api-tests/Collections/Publish API.postman_collection.json @@ -2,7 +2,7 @@ "info": { "_postman_id": "607f186e-f5e0-4d51-a4c6-02c534d1689c", "name": "Publish API", - "description": "The Content/Collection Publish APIs allow you to publish content/collection on the Sunbird platform. Publish API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/publish and /collection/v2/publish.", + "description": "The Content/Collection Publish APIs allow you to publish content/collection on the Sunbird platform. Publish API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/publish and /collection/v1/publish.", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, "item": [ @@ -8193,7 +8193,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -8250,7 +8250,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -8307,7 +8307,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -8364,7 +8364,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -8421,7 +8421,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -8478,7 +8478,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -8535,7 +8535,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -8592,7 +8592,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -8649,7 +8649,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -8706,7 +8706,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -8822,7 +8822,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -8879,7 +8879,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -8945,7 +8945,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -9011,7 +9011,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -9077,7 +9077,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -9143,7 +9143,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -9209,7 +9209,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -9275,7 +9275,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -9341,7 +9341,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -9407,7 +9407,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -9483,7 +9483,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -9558,7 +9558,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { @@ -9634,7 +9634,7 @@ }, { "key": "x-authenticated-user-token", - "value": "{{user-token}}", + "value": "{{keycloak_access_token}}", "type": "text" }, { From a286b1991f1d083cb61d9cc2c744b4c06c026646 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 24 Aug 2022 12:15:37 +0530 Subject: [PATCH 075/105] Issue #KN-9 feat: Content Publish API refactor. --- .../Content V2 API Test.postman_collection.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json b/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json index 35981e978..81e9d54fb 100644 --- a/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json +++ b/content-api/api-tests/Collections/Content V2 API Test.postman_collection.json @@ -1362,7 +1362,7 @@ "response": [] } ], - "description": "The Content/Collection Reserve DIAL code APIs allow you to reserve DIAL codes to a content/collection on the Sunbird platform. Reserve DAIL code API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/dialcode/reserve and /collection/v1/dialcode/reserve." + "description": "The Content/Collection Reserve DIAL code APIs allow you to reserve DIAL codes to a content/collection on the Sunbird platform. Reserve DAIL code API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URLs for Content Reserve DIAL code API(s) are /content/v2/dialcode/reserve and /collection/v1/dialcode/reserve." }, { "name": "Content Link DIAL code", @@ -1498,7 +1498,7 @@ "response": [] } ], - "description": "The Content/Collection Link DIAL code APIs allow you to link DIAL codes to content/collection/collection units on the Sunbird platform. Reserve DAIL code API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/dialcode/link and /collection/v1/dialcode/link." + "description": "The Content/Collection Link DIAL code APIs allow you to link DIAL codes to content/collection/collection units on the Sunbird platform. Reserve DAIL code API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URLs for Content Link DIAL code API(s) are /content/v2/dialcode/link and /collection/v1/dialcode/link." }, { "name": "Content Publish API", @@ -6005,7 +6005,7 @@ ] } ], - "description": "The Content/Collection Publish APIs allow you to publish content/collection on the Sunbird platform. Publish API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/publish and /collection/v1/publish." + "description": "The Content/Collection Publish APIs allow you to publish content/collection on the Sunbird platform. Publish API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URLs for Content Publish API(s) are /content/v2/publish and /collection/v1/publish." } ], "event": [ @@ -7967,7 +7967,7 @@ "response": [] } ], - "description": "The Content/Collection Reserve DIAL code APIs allow you to reserve DIAL codes to a content/collection on the Sunbird platform. Reserve DAIL code API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/dialcode/reserve and /collection/v1/dialcode/reserve." + "description": "The Content/Collection Reserve DIAL code APIs allow you to reserve DIAL codes to a content/collection on the Sunbird platform. Reserve DAIL code API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URLs for Content Reserve DIAL code API(s) are /content/v2/dialcode/reserve and /collction/v1/dialcode/reserve." }, { "name": "Content Link DIAL code", @@ -8195,7 +8195,7 @@ "response": [] } ], - "description": "The Content/Collection Link DIAL code APIs allow you to link DIAL codes to content/collection/collection units on the Sunbird platform. Reserve DAIL code API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/dialcode/link and /collection/v1/dialcode/link" + "description": "The Content/Collection Link DIAL code APIs allow you to link DIAL codes to content/collection/collection units on the Sunbird platform. Reserve DAIL code API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URLs for Content Link DIAL code API(s) are /content/v2/dialcode/link and /collection/v1/dialcode/link" }, { "name": "Content Publish API", @@ -13351,7 +13351,7 @@ ] } ], - "description": "The Content/Collection Publish APIs allow you to publish content/collection on the Sunbird platform. Publish API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URL for Content Management API(s) is /content/v2/publish and /collection/v1/publish." + "description": "The Content/Collection Publish APIs allow you to publish content/collection on the Sunbird platform. Publish API was previously available as part of learning-service which has now been refactored into content-service.\n\nThe URLs for Content Publish API(s) are /content/v2/publish and /collection/v1/publish." } ], "event": [ From 809ac27f2ee5280e4589f25ae42e914d95d5391b Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Tue, 30 Aug 2022 11:09:25 +0530 Subject: [PATCH 076/105] Issue #KN-231 feat: Added the support for google-cloud. --- .../sunbird/content/actors/ContentActor.scala | 3 +- .../sunbird/content/util/CopyManager.scala | 2 +- platform-modules/mimetype-manager/pom.xml | 2 +- .../sunbird/cloudstore/StorageService.scala | 51 +++++++++---------- .../cloudstore/StorageServiceTest.scala | 4 +- 5 files changed, 30 insertions(+), 32 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala index fabc95d43..df9047ff8 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala @@ -144,6 +144,7 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe def uploadPreSignedUrl(request: Request): Future[Response] = { val `type`: String = request.get("type").asInstanceOf[String].toLowerCase() val fileName: String = request.get("fileName").asInstanceOf[String] + val mimeType: String = request.get("mimeType").asInstanceOf[String] val filePath: String = request.getRequest.getOrDefault("filePath","").asInstanceOf[String] .replaceAll("^/+|/+$", "") val identifier: String = request.get("identifier").asInstanceOf[String] @@ -152,7 +153,7 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe val objectKey = if (StringUtils.isEmpty(filePath)) "content" + File.separator + `type` + File.separator + identifier + File.separator + Slug.makeSlug(fileName, true) else filePath + File.separator + "content" + File.separator + `type` + File.separator + identifier + File.separator + Slug.makeSlug(fileName, true) val expiry = Platform.config.getString("cloud_storage.upload.url.ttl") - val preSignedURL = ss.getSignedURL(objectKey, Option.apply(expiry.toInt), Option.apply("w")) + val preSignedURL = ss.getSignedURL(objectKey, Option.apply(expiry.toInt), Option.apply("w"), Option.apply(mimeType)) ResponseHandler.OK().put("identifier", identifier).put("pre_signed_url", preSignedURL) .put("url_expiry", expiry) }) recoverWith { case e: CompletionException => throw e.getCause } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/util/CopyManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/util/CopyManager.scala index cbf52207d..f1c2f86cc 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/util/CopyManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/util/CopyManager.scala @@ -222,7 +222,7 @@ object CopyManager { protected def getFileNameFromURL(fileUrl: String): String = if (!FilenameUtils.getExtension(fileUrl).isEmpty) FilenameUtils.getBaseName(fileUrl) + "_" + System.currentTimeMillis + "." + FilenameUtils.getExtension(fileUrl) else FilenameUtils.getBaseName(fileUrl) + "_" + System.currentTimeMillis - protected def isInternalUrl(url: String)(implicit ss: StorageService): Boolean = url.contains(ss.getContainerName()) + protected def isInternalUrl(url: String)(implicit ss: StorageService): Boolean = url.contains(ss.getContainerName) def prepareHierarchyRequest(originHierarchy: util.Map[String, AnyRef], originNode: Node, node: Node, copyType: String, request: Request):util.HashMap[String, AnyRef] = { val children:util.List[util.Map[String, AnyRef]] = originHierarchy.get("children").asInstanceOf[util.List[util.Map[String, AnyRef]]] diff --git a/platform-modules/mimetype-manager/pom.xml b/platform-modules/mimetype-manager/pom.xml index c97b9bbd2..80a17876b 100644 --- a/platform-modules/mimetype-manager/pom.xml +++ b/platform-modules/mimetype-manager/pom.xml @@ -30,7 +30,7 @@ org.sunbird cloud-store-sdk - 1.4.0 + 1.4.1 org.scala-lang diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala index 0045caf82..f03a79627 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala @@ -1,7 +1,6 @@ package org.sunbird.cloudstore import java.io.File - import org.apache.commons.lang3.StringUtils import org.sunbird.cloud.storage.BaseStorageService import org.sunbird.common.Platform @@ -10,7 +9,7 @@ import org.sunbird.cloud.storage.factory.StorageServiceFactory import org.sunbird.common.exception.ServerException import org.sunbird.common.Slug -import scala.concurrent.ExecutionContext +import scala.concurrent.{ExecutionContext, Future} class StorageService { @@ -18,20 +17,20 @@ class StorageService { var storageService: BaseStorageService = null @throws[Exception] - def getService(): BaseStorageService = { + def getService: BaseStorageService = { if (null == storageService) { if (StringUtils.equalsIgnoreCase(storageType, "azure")) { val storageKey = Platform.config.getString("azure_storage_key") val storageSecret = Platform.config.getString("azure_storage_secret") - storageService = StorageServiceFactory.getStorageService(new StorageConfig(storageType, storageKey, storageSecret)) + storageService = StorageServiceFactory.getStorageService(StorageConfig(storageType, storageKey, storageSecret)) } else if (StringUtils.equalsIgnoreCase(storageType, "aws")) { val storageKey = Platform.config.getString("aws_storage_key") val storageSecret = Platform.config.getString("aws_storage_secret") - storageService = StorageServiceFactory.getStorageService(new StorageConfig(storageType, storageKey, storageSecret)) + storageService = StorageServiceFactory.getStorageService(StorageConfig(storageType, storageKey, storageSecret)) } else if (StringUtils.equalsIgnoreCase(storageType, "gcloud")) { val storageKey = Platform.config.getString("gcloud_client_key") val storageSecret = Platform.config.getString("gcloud_private_secret") - storageService = StorageServiceFactory.getStorageService(new StorageConfig(storageType, storageKey, storageSecret)) + storageService = StorageServiceFactory.getStorageService(StorageConfig(storageType, storageKey, storageSecret)) } // else if (StringUtils.equalsIgnoreCase(storageType, "cephs3")) { // val storageKey = Platform.config.getString("cephs3_storage_key") @@ -44,17 +43,13 @@ class StorageService { storageService } - def getContainerName(): String = { - if (StringUtils.equalsIgnoreCase(storageType, "azure")) - Platform.config.getString("azure_storage_container") - else if (StringUtils.equalsIgnoreCase(storageType, "aws")) - Platform.config.getString("aws_storage_container") - else if (StringUtils.equalsIgnoreCase(storageType, "gcloud")) - Platform.config.getString("gcloud_storage_bucket") - else if (StringUtils.equalsIgnoreCase(storageType, "cephs3")) - Platform.config.getString("cephs3_storage_container") - else - throw new ServerException("ERR_INVALID_CLOUD_STORAGE", "Container name not configured.") + def getContainerName: String = { + storageType match { + case "azure" => Platform.config.getString("azure_storage_container") + case "aws" => Platform.config.getString("aws_storage_container") + case "gcloud" => Platform.config.getString("gcloud_storage_bucket") + case _ => throw new ServerException("ERR_INVALID_CLOUD_STORAGE", "Container name not configured.") + } } def uploadFile(folderName: String, file: File, slug: Option[Boolean] = Option(true)): Array[String] = { @@ -67,11 +62,11 @@ class StorageService { def uploadDirectory(folderName: String, directory: File, slug: Option[Boolean] = Option(true)): Array[String] = { val slugFile = if (slug.getOrElse(true)) Slug.createSlugFile(directory) else directory val objectKey = folderName + File.separator - val url = getService.upload(getContainerName(), slugFile.getAbsolutePath, objectKey, Option.apply(true), Option.apply(1), Option.apply(5), Option.empty) + val url = getService.upload(getContainerName, slugFile.getAbsolutePath, objectKey, Option.apply(true), Option.apply(1), Option.apply(5), Option.empty) Array[String](objectKey, url) } - def uploadDirectoryAsync(folderName: String, directory: File, slug: Option[Boolean] = Option(true))(implicit ec: ExecutionContext) = { + def uploadDirectoryAsync(folderName: String, directory: File, slug: Option[Boolean] = Option(true))(implicit ec: ExecutionContext): Future[List[String]] = { val slugFile = if (slug.getOrElse(true)) Slug.createSlugFile(directory) else directory val objectKey = folderName + File.separator getService.uploadFolder(getContainerName, slugFile.getAbsolutePath, objectKey, Option.apply(false), None, None, 1) @@ -82,26 +77,28 @@ class StorageService { blob.contentLength } - def copyObjectsByPrefix(source: String, destination: String) = { + def copyObjectsByPrefix(source: String, destination: String): Unit = { getService.copyObjects(getContainerName, source, getContainerName, destination, Option.apply(true)) } - def deleteFile(key: String, isDirectory: Option[Boolean] = Option(false)) = { + def deleteFile(key: String, isDirectory: Option[Boolean] = Option(false)): Unit = { getService.deleteObject(getContainerName, key, isDirectory) } - def getSignedURL(key: String, ttl: Option[Int], permission: Option[String]): String = { - getService().getSignedURL(getContainerName, key, ttl, permission) + def getSignedURL(key: String, ttl: Option[Int], permission: Option[String], contentType: Option[String] = None): String = { + storageType match { + case "gcloud" => getService.getPutSignedURL(getContainerName, key, ttl, permission, contentType) + case _ => getService.getSignedURL (getContainerName, key, ttl, permission) + } } def getUri(key: String): String = { try { getService.getUri(getContainerName, key, Option.apply(false)) } catch { - case e:Exception => { - println("StorageService --> getUri --> Exception: " + e.getMessage) - "" - } + case e:Exception => + println("StorageService --> getUri --> Exception: " + e.getMessage) + "" } } } diff --git a/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala b/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala index 7cd55d82e..fe0d078bb 100644 --- a/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala +++ b/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala @@ -6,12 +6,12 @@ class StorageServiceTest extends AsyncFlatSpec with Matchers { val ss = new StorageService "getService" should "return a Storage Service" in { - val service = ss.getService() + val service = ss.getService assert(service != null) } "getContainerName" should "return the container name" in { - val container = ss.getContainerName() + val container = ss.getContainerName assert(container == "sunbird-content-dev") } } From c9449b8eeee541cfe1faff230eac6e232b0525aa Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Tue, 30 Aug 2022 13:05:08 +0530 Subject: [PATCH 077/105] Issue #KN-231 test: Fixed the unit test. --- .../scala/org/sunbird/content/actors/TestContentActor.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala index 40778e99f..52b413a43 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala @@ -93,8 +93,8 @@ class TestContentActor extends BaseSpec with MockFactory { val graphDB = mock[GraphService] (oec.graphService _).expects().returns(graphDB) (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getValidNode())) - implicit val ss = mock[StorageService] - (ss.getSignedURL(_: String, _: Option[Int], _: Option[String])).expects(*, *, *).returns("cloud store url") + implicit val ss: StorageService = mock[StorageService] + (ss.getSignedURL(_: String, _: Option[Int], _: Option[String], _: Option[String])).expects(*, *, *, *).returns("cloud store url") val request = getContentRequest() request.getRequest.putAll(mapAsJavaMap(Map("fileName" -> "presigned_url", "filePath" -> "/data/cloudstore/", "type" -> "assets", "identifier" -> "do_1234"))) request.setOperation("uploadPreSignedUrl") From 9c4884d57e58f597dc34f34e3b337bcb129b82af Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Thu, 1 Sep 2022 16:55:33 +0530 Subject: [PATCH 078/105] Issue #KN-231 test: Improved unit test coverage. --- .../org/sunbird/cloudstore/StorageServiceTest.scala | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala b/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala index fe0d078bb..47ba320e1 100644 --- a/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala +++ b/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala @@ -2,6 +2,8 @@ package org.sunbird.cloudstore import org.scalatest.{AsyncFlatSpec, Matchers} +import java.io.File + class StorageServiceTest extends AsyncFlatSpec with Matchers { val ss = new StorageService @@ -14,4 +16,15 @@ class StorageServiceTest extends AsyncFlatSpec with Matchers { val container = ss.getContainerName assert(container == "sunbird-content-dev") } + + "getSignedURL" should "return the signed url" in { + val objectKey = "content" + File.separator + "asset" + File.separator + "do_53245" + File.separator + "abc.png" + val preSignedURL = ss.getSignedURL(objectKey, Option.apply(600), Option.apply("w"), Option.apply("")) + assert(preSignedURL.contains(objectKey)) + } + + "getUri" should "return the signed url" in { + val uri = ss.getUri("content/abc.json") + assert(uri != null) + } } From 29e64c511706385ecf999bd8d78b109c7279cf09 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 1 Sep 2022 17:28:21 +0530 Subject: [PATCH 079/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../sunbird/content/actors/ContentActor.scala | 3 + .../org/sunbird/content/dial/DIALErrors.scala | 8 +- .../sunbird/content/dial/DIALManager.scala | 104 +++++++++++++++++- .../controllers/v3/ContentController.scala | 10 +- .../controllers/v4/CollectionController.scala | 12 +- .../controllers/v4/ContentController.scala | 12 +- .../content-service/app/utils/ApiId.scala | 2 + content-api/content-service/conf/routes | 4 +- 8 files changed, 144 insertions(+), 11 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala index e3925113f..f3f3d2636 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala @@ -50,6 +50,7 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe case "acceptFlag" => acceptFlag(request) case "linkDIALCode" => linkDIALCode(request) case "reserveDialCode" => reserveDialCode(request) + case "releaseDialCode" => releaseDialCode(request) case "importContent" => importContent(request) case "systemUpdate" => systemUpdate(request) case "reviewContent" => reviewContent(request) @@ -179,6 +180,8 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe def reserveDialCode(request: Request): Future[Response] = DIALManager.reserve(request) + def releaseDialCode(request: Request): Future[Response] = DIALManager.release(request) + def importContent(request: Request): Future[Response] = importMgr.importObject(request) def reviewContent(request: Request): Future[Response] = { diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala index 743cbe86a..3ecd0acdb 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala @@ -13,6 +13,9 @@ object DIALErrors { val ERR_CONTENT_INVALID_OBJECT: String = "ERR_CONTENT_INVALID_OBJECT" val ERR_DUPLICATE_DIAL_CODES: String = "ERR_DUPLICATE_DIAL_CODES" val ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING: String = "ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING" + val ERR_CONTENT_RETIRED_OBJECT_ID: String = "ERR_CONTENT_RETIRED_OBJECT_ID" + val ERR_CONTENT_MISSING_RESERVED_DIAL_CODES: String = "ERR_CONTENT_MISSING_RESERVED_DIAL_CODES" + val ERR_ALL_DIALCODES_UTILIZED: String = "ERR_ALL_DIALCODES_UTILIZED" //Error Messages val ERR_INVALID_REQ_MSG: String = "Invalid Request! Please Provide Valid Request." @@ -29,7 +32,10 @@ object DIALErrors { val ERR_DIAL_GEN_LIST_EMPTY_MSG: String = "Dialcode generated list is empty. Please Try Again After Sometime!" val ERR_DIAL_GENERATION_MSG: String = "Error During generate Dialcode. Please Try Again After Sometime!" val ERR_DIAL_INVALID_COUNT_RESPONSE = "No new DIAL Codes have been generated, as requested count is less or equal to existing reserved dialcode count." - val ERR_CONTENT_INVALID_OBJECT_MSG = "Invalid Request. Cannot update status of Live Node." + val ERR_CONTENT_INVALID_OBJECT_MSG = "Invalid Request. Cannot update 'Live' content." val ERR_DUPLICATE_DIAL_CODES_MSG: String = "QR Code should not be linked to multiple contents. Please validate: " val ERR_DIALCODE_CONTENT_LINK_FIELDS_MISSING_MSG: String = "Required fields for content link dialcode are missing: " + val ERR_CONTENT_RETIRED_OBJECT_ID_MSG: String = "Invalid Request. Cannot update 'Retired' content." + val ERR_CONTENT_MISSING_RESERVED_DIAL_CODES_MSG: String = "Invalid Request. Content does not have reserved DIAL codes." + val ERR_ALL_DIALCODES_UTILIZED_MSG: String = "Error! All Reserved DIAL Codes are Utilized." } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index fa7385d17..5f47e9670 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -279,8 +279,8 @@ object DIALManager { val contentMetadata = rootNode.getMetadata validateChannel(contentMetadata.get(DIALConstants.CHANNEL).asInstanceOf[String], channelId) - validateContentForReservedDialcodes(contentMetadata) - validateCountForReservingDialCode(request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]]) + validateContentForReserveAndReleaseDialcodes(contentMetadata) + validateCountForReservingAndReleasingDialCode(request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]]) validateContentStatus(contentMetadata) val reservedDialCodes = if(contentMetadata.containsKey(DIALConstants.RESERVED_DIALCODES)) ScalaJsonUtils.deserialize[Map[String, Integer]](contentMetadata.get(DIALConstants.RESERVED_DIALCODES).asInstanceOf[String]) else Map.empty[String, Integer] @@ -302,17 +302,113 @@ object DIALManager { }) } + def release(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { + val channelId: String = request.getContext.getOrDefault(DIALConstants.CHANNEL, "").asInstanceOf[String] + val contentId: String = request.get(ContentConstants.IDENTIFIER).asInstanceOf[String] + + if (contentId == null || contentId.isEmpty) throw new ClientException(DIALErrors.ERR_CONTENT_BLANK_OBJECT_ID, DIALErrors.ERR_CONTENT_BLANK_OBJECT_ID_MSG) + + val req = new Request() + req.setContext(request.getContext) + req.put(DIALConstants.IDENTIFIER, contentId) + req.put(ContentConstants.ROOT_ID, contentId) + req.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) + DataNode.read(req).flatMap(rootNode => { + val contentMetadata = rootNode.getMetadata + + validateChannel(contentMetadata.get(DIALConstants.CHANNEL).asInstanceOf[String], channelId) + validateContentForReserveAndReleaseDialcodes(contentMetadata) + validateCountForReservingAndReleasingDialCode(request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]]) + + val reservedDialCodes = if(contentMetadata.containsKey(DIALConstants.RESERVED_DIALCODES)) ScalaJsonUtils.deserialize[Map[String, Integer]](contentMetadata.get(DIALConstants.RESERVED_DIALCODES).asInstanceOf[String]) + else throw new ClientException(DIALErrors.ERR_CONTENT_MISSING_RESERVED_DIAL_CODES, DIALErrors.ERR_CONTENT_MISSING_RESERVED_DIAL_CODES_MSG) + + populateAssignedDialCodes(contentId, contentMetadata, req).map(assignedDialCodes => { + val toReleaseDIALCodes = reservedDialCodes.keySet -- assignedDialCodes.toSet + + if(toReleaseDIALCodes.isEmpty) throw new ClientException(DIALErrors.ERR_ALL_DIALCODES_UTILIZED, DIALErrors.ERR_ALL_DIALCODES_UTILIZED_MSG) + + val reqDialcodesCount = request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]].get(DIALConstants.COUNT).asInstanceOf[Integer] + + val updatedReleaseDialcodes = if (toReleaseDIALCodes.size > reqDialcodesCount) { + toReleaseDIALCodes.take(reqDialcodesCount) + } else toReleaseDIALCodes + + val updatedReserveDialCodes = reservedDialCodes.filter(rec => !updatedReleaseDialcodes.contains(rec._1)).keySet.zipWithIndex.map { case (dialCode, idx) => + (dialCode -> idx.asInstanceOf[Integer]) + }.toMap + + val updateReq = new Request() + updateReq.setContext(request.getContext) + updateReq.getContext.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) + updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) + updateReq.put(DIALConstants.VERSION_KEY,rootNode.getMetadata.get(ContentConstants.VERSION_KEY)) + updateReq.put(DIALConstants.RESERVED_DIALCODES, if(updatedReserveDialCodes.nonEmpty) updatedReserveDialCodes.asJava else null) + DataNode.update(updateReq).map(node => { + ResponseHandler.OK.putAll(Map(ContentConstants.IDENTIFIER -> node.getIdentifier.replace(ContentConstants.IMAGE_SUFFIX, ""), + ContentConstants.VERSION_KEY -> node.getMetadata.get(ContentConstants.VERSION_KEY), + DIALConstants.RESERVED_DIALCODES -> node.getMetadata.get(DIALConstants.RESERVED_DIALCODES)).asJava) + }) + }).flatMap(f=>f) + }) + } + + def populateAssignedDialCodes(contentId: String, contentMetadata: util.Map[String, AnyRef], request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[List[String]] = { + + request.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) + request.getContext.put(ContentConstants.VERSION, ContentConstants.SCHEMA_VERSION) + request.put(ContentConstants.ROOT_ID, contentId) + + HierarchyManager.getHierarchy(request).flatMap(getHierarchyResponse => { + val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] + val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList + val childrenAssignedDIALList = getAssignedDIALcodes(childrenHierarchy) + val contentAssignedDIALList = childrenAssignedDIALList ++ collectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] + + if(contentMetadata.getOrDefault(ContentConstants.IDENTIFIER,"").asInstanceOf[String].endsWith(ContentConstants.IMAGE_SUFFIX)) { + request.put(ContentConstants.ROOT_ID, contentMetadata.getOrDefault(ContentConstants.IDENTIFIER,"").asInstanceOf[String]) + request.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) + HierarchyManager.getHierarchy(request).flatMap(getHierarchyResponse => { + val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] + val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList + val childrenAssignedDIALList = getAssignedDIALcodes(childrenHierarchy) + val contentImageAssignedDIALList = childrenAssignedDIALList ++ collectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] + + Future(contentImageAssignedDIALList ++ contentAssignedDIALList) + }) + } else Future(contentAssignedDIALList) + }) + } + + def getAssignedDIALcodes(childrenHierarchy: List[util.Map[String, AnyRef]]): List[String] = { + childrenHierarchy.map(child => { + val subChildrenDIALMap = if(child.get(ContentConstants.CHILDREN)!=null) + getAssignedDIALcodes(child.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList) + else List.empty[String] + + val childDIALMap = if(child.get(DIALConstants.DIALCODES)!=null) + child.get(DIALConstants.DIALCODES).asInstanceOf[List[String]] + else List.empty[String] + + subChildrenDIALMap ++ childDIALMap + }).filter(msg => msg.nonEmpty).flatten + } + + def validateChannel(contentChannel: String, channelId: String): Unit = { if(contentChannel == null || channelId == null || !contentChannel.equalsIgnoreCase(channelId)) throw new ClientException(DIALErrors.ERR_INVALID_CHANNEL, DIALErrors.ERR_INVALID_CHANNEL_MSG) } - def validateContentForReservedDialcodes(metaData: util.Map[String, AnyRef]): Unit = { + def validateContentForReserveAndReleaseDialcodes(metaData: util.Map[String, AnyRef]): Unit = { val validMimeType = if (Platform.config.hasPath("reserve_dialcode.mimeType")) Platform.config.getStringList("reserve_dialcode.mimeType") else util.Arrays.asList(ContentConstants.COLLECTION_MIME_TYPE) if (!validMimeType.contains(metaData.get(ContentConstants.MIME_TYPE))) throw new ClientException(DIALErrors.ERR_CONTENT_MIMETYPE, DIALErrors.ERR_CONTENT_MIMETYPE_MSG) + + if(metaData.get(ContentConstants.STATUS).asInstanceOf[String].equalsIgnoreCase("Retired")) + throw new ClientException(DIALErrors.ERR_CONTENT_RETIRED_OBJECT_ID, DIALErrors.ERR_CONTENT_RETIRED_OBJECT_ID_MSG) } - def validateCountForReservingDialCode(request: util.Map[String, AnyRef]): Unit = { + def validateCountForReservingAndReleasingDialCode(request: util.Map[String, AnyRef]): Unit = { if (null == request.get(DIALConstants.COUNT) || !request.get(DIALConstants.COUNT).isInstanceOf[Integer]) throw new ClientException(DIALErrors.ERR_INVALID_COUNT, DIALErrors.ERR_INVALID_COUNT_MSG) val count = request.get(DIALConstants.COUNT).asInstanceOf[Integer] val maxCount = if (Platform.config.hasPath("reserve_dialcode.max_count")) Platform.config.getInt("reserve_dialcode.max_count") else 250 diff --git a/content-api/content-service/app/controllers/v3/ContentController.scala b/content-api/content-service/app/controllers/v3/ContentController.scala index ab3538098..0729f625a 100644 --- a/content-api/content-service/app/controllers/v3/ContentController.scala +++ b/content-api/content-service/app/controllers/v3/ContentController.scala @@ -216,9 +216,13 @@ class ContentController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentActor: } def releaseDialcodes(identifier: String) = Action.async { implicit request => - val result = ResponseHandler.OK() - val response = JavaJsonUtils.serialize(result) - Future(Ok(response).as("application/json")) + val headers = commonHeaders() + val body = requestBody() + body.putAll(headers) + body.putAll(Map("identifier" -> identifier).asJava) + val releaseDialCode = getRequest(body, headers, "releaseDialCode") + setRequestContext(releaseDialCode, version, objectType, schemaName) + getResult(ApiId.RELEASE_DIAL_CONTENT, contentActor, releaseDialCode) } def publishUnlisted(identifier: String) = Action.async { implicit request => diff --git a/content-api/content-service/app/controllers/v4/CollectionController.scala b/content-api/content-service/app/controllers/v4/CollectionController.scala index 4dfd17829..2c07a292b 100644 --- a/content-api/content-service/app/controllers/v4/CollectionController.scala +++ b/content-api/content-service/app/controllers/v4/CollectionController.scala @@ -193,7 +193,17 @@ class CollectionController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentAc body.putAll(Map("identifier" -> identifier).asJava) val reserveDialCode = getRequest(body, headers, "reserveDialCode") setRequestContext(reserveDialCode, version, objectType, schemaName) - getResult(ApiId.RESERVE_DIAL_COLLECTION, contentActor, reserveDialCode) + getResult(ApiId.RESERVE_DIAL_COLLECTION, contentActor, reserveDialCode, version = apiVersion) + } + + def releaseDialCode(identifier: String) = Action.async { implicit request => + val headers = commonHeaders() + val body = requestBody() + body.putAll(headers) + body.putAll(Map("identifier" -> identifier).asJava) + val releaseDialCode = getRequest(body, headers, "releaseDialCode") + setRequestContext(releaseDialCode, version, objectType, schemaName) + getResult(ApiId.RELEASE_DIAL_COLLECTION, contentActor, releaseDialCode, version = apiVersion) } def copy(identifier: String, mode: Option[String], copyType: String) = Action.async { implicit request => diff --git a/content-api/content-service/app/controllers/v4/ContentController.scala b/content-api/content-service/app/controllers/v4/ContentController.scala index f5a25d0fe..8db895c56 100644 --- a/content-api/content-service/app/controllers/v4/ContentController.scala +++ b/content-api/content-service/app/controllers/v4/ContentController.scala @@ -138,7 +138,17 @@ class ContentController @Inject()(@Named(ActorNames.CONTENT_ACTOR) contentActor: body.putAll(Map("identifier" -> identifier).asJava) val reserveDialCode = getRequest(body, headers, "reserveDialCode") setRequestContext(reserveDialCode, version, objectType, schemaName) - getResult(ApiId.RESERVE_DIAL_CONTENT, contentActor, reserveDialCode) + getResult(ApiId.RESERVE_DIAL_CONTENT, contentActor, reserveDialCode, version = apiVersion) + } + + def releaseDialCode(identifier: String) = Action.async { implicit request => + val headers = commonHeaders() + val body = requestBody() + body.putAll(headers) + body.putAll(Map("identifier" -> identifier).asJava) + val releaseDialCode = getRequest(body, headers, "releaseDialCode") + setRequestContext(releaseDialCode, version, objectType, schemaName) + getResult(ApiId.RELEASE_DIAL_CONTENT, contentActor, releaseDialCode, version = apiVersion) } def upload(identifier: String, fileFormat: Option[String], validation: Option[String]) = Action.async { implicit request => diff --git a/content-api/content-service/app/utils/ApiId.scala b/content-api/content-service/app/utils/ApiId.scala index 8b5afe44f..9306d13f7 100644 --- a/content-api/content-service/app/utils/ApiId.scala +++ b/content-api/content-service/app/utils/ApiId.scala @@ -30,6 +30,7 @@ object ApiId { val GET_HIERARCHY = "api.content.hierarchy.get" val LINK_DIAL_COLLECTION = "api.collection.dialcode.link" val RESERVE_DIAL_CONTENT = "api.content.dialcode.reserve" + val RELEASE_DIAL_CONTENT = "api.content.dialcode.release" //License APIs val CREATE_LICENSE = "api.license.create" @@ -101,4 +102,5 @@ object ApiId { val IMPORT_CSV = "api.collection.import" val EXPORT_CSV = "api.collection.export" val RESERVE_DIAL_COLLECTION = "api.collection.dialcode.reserve" + val RELEASE_DIAL_COLLECTION = "api.collection.dialcode.release" } diff --git a/content-api/content-service/conf/routes b/content-api/content-service/conf/routes index 17b4e3059..d903bbe64 100644 --- a/content-api/content-service/conf/routes +++ b/content-api/content-service/conf/routes @@ -100,6 +100,7 @@ PATCH /content/v4/system/update/:identifier controllers.v4.ContentControl POST /content/v4/review/:identifier controllers.v4.ContentController.review(identifier:String) POST /content/v4/reject/:identifier controllers.v4.ContentController.reviewReject(identifier:String) POST /content/v4/dialcode/reserve/:identifier controllers.v4.ContentController.reserveDialCode(identifier:String) +POST /content/v4/dialcode/release/:identifier controllers.v4.ContentController.releaseDialCode(identifier:String) # App v4 APIs POST /app/v4/register controllers.v4.AppController.register @@ -131,4 +132,5 @@ GET /object/v4/read/:identifier controllers.v4.ObjectController POST /collection/v4/import/:collectionId controllers.v4.CollectionController.importCollection(collectionId:String) GET /collection/v4/export/:collectionId controllers.v4.CollectionController.exportCollection(collectionId:String, fileType:Option[String]) POST /collection/v4/review/:identifier controllers.v4.CollectionController.review(identifier:String) -POST /collection/v4/dialcode/reserve/:identifier controllers.v4.CollectionController.reserveDialCode(identifier:String) \ No newline at end of file +POST /collection/v4/dialcode/reserve/:identifier controllers.v4.CollectionController.reserveDialCode(identifier:String) +POST /collection/v4/dialcode/release/:identifier controllers.v4.CollectionController.releaseDialCode(identifier:String) \ No newline at end of file From ca85c978c18a32d6fcd9dc31cd2cca9654ab0299 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 6 Sep 2022 15:08:33 +0530 Subject: [PATCH 080/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../sunbird/content/dial/DIALManager.scala | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 5f47e9670..332fb07e2 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -127,23 +127,20 @@ object DIALManager { req.put(ContentConstants.IDENTIFIER, objectId) req.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) DataNode.read(req).flatMap(rootNode => { - req.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) - req.getContext.put(ContentConstants.VERSION, ContentConstants.SCHEMA_VERSION) - req.put(ContentConstants.ROOT_ID, objectId) - HierarchyManager.getHierarchy(req).flatMap(getHierarchyResponse => { - val updatedChildrenHierarchy = getUpdatedChildrenHierarchy(getHierarchyResponse, requestMap) - val consolidatedUnitDIALMap = getConsolidatedUnitDIALMap(updatedChildrenHierarchy, requestMap, objectId) - validateDuplicateDIALCodes(consolidatedUnitDIALMap.filter(rec => rec._2.asInstanceOf[List[String]].nonEmpty)) - - val hierarchyReq = getHierarchyRequest(req, objectId, updatedChildrenHierarchy, rootNode) - oec.graphService.saveExternalProps(hierarchyReq).flatMap(rec => if(requestMap.contains(objectId)) { - val updateReq = getLinkUpdateRequest(req, rootNode, requestMap, objectId) - - DataNode.update(updateReq).flatMap(response => { + val updateReq = getLinkUpdateRequest(req, rootNode, requestMap, objectId) + DataNode.update(updateReq).flatMap(response => { + req.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) + req.getContext.put(ContentConstants.VERSION, ContentConstants.SCHEMA_VERSION) + req.put(ContentConstants.ROOT_ID, objectId) + HierarchyManager.getHierarchy(req).flatMap(getHierarchyResponse => { + val updatedChildrenHierarchy = getUpdatedChildrenHierarchy(getHierarchyResponse, requestMap) + val consolidatedUnitDIALMap = getConsolidatedUnitDIALMap(updatedChildrenHierarchy, requestMap, objectId) + validateDuplicateDIALCodes(consolidatedUnitDIALMap.filter(rec => rec._2.asInstanceOf[List[String]].nonEmpty)) + + val hierarchyReq = getHierarchyRequest(req, objectId, updatedChildrenHierarchy, rootNode) + oec.graphService.saveExternalProps(hierarchyReq).flatMap(rec => getResponseCollectionLink(requestMap, consolidatedUnitDIALMap.keySet.toList, requestMap.keySet.diff(consolidatedUnitDIALMap.keySet).toList) - }) - } else { - getResponseCollectionLink(requestMap, consolidatedUnitDIALMap.keySet.toList, requestMap.keySet.diff(consolidatedUnitDIALMap.keySet).toList) + ) }) }) }) @@ -175,9 +172,9 @@ object DIALManager { def getLinkUpdateRequest(req: Request, rootNode: Node, requestMap: Map[String, List[String]], objectId: String): Request = { val updateReq = new Request(req) updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) - updateReq.put(DIALConstants.VERSION_KEY,rootNode.getMetadata.get("versionKey")) + updateReq.put(DIALConstants.VERSION_KEY, rootNode.getMetadata.get("versionKey")) - if(requestMap(objectId).isEmpty) + if(!requestMap.contains(objectId)) updateReq.put(DIALConstants.DIALCODES, null) else updateReq.put(DIALConstants.DIALCODES, requestMap(objectId).toArray[String]) @@ -354,25 +351,29 @@ object DIALManager { } def populateAssignedDialCodes(contentId: String, contentMetadata: util.Map[String, AnyRef], request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[List[String]] = { - + request.put(ContentConstants.MODE,"") request.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) request.getContext.put(ContentConstants.VERSION, ContentConstants.SCHEMA_VERSION) - request.put(ContentConstants.ROOT_ID, contentId) + request.put(ContentConstants.ROOT_ID, contentId.replaceAll(ContentConstants.IMAGE_SUFFIX, "")) HierarchyManager.getHierarchy(request).flatMap(getHierarchyResponse => { val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList val childrenAssignedDIALList = getAssignedDIALcodes(childrenHierarchy) - val contentAssignedDIALList = childrenAssignedDIALList ++ collectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] + val contentAssignedDIALList = if(collectionHierarchy.containsKey(DIALConstants.DIALCODES) && collectionHierarchy.get(DIALConstants.DIALCODES) != null) + childrenAssignedDIALList ++ collectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] + else childrenAssignedDIALList if(contentMetadata.getOrDefault(ContentConstants.IDENTIFIER,"").asInstanceOf[String].endsWith(ContentConstants.IMAGE_SUFFIX)) { request.put(ContentConstants.ROOT_ID, contentMetadata.getOrDefault(ContentConstants.IDENTIFIER,"").asInstanceOf[String]) request.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) - HierarchyManager.getHierarchy(request).flatMap(getHierarchyResponse => { - val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList - val childrenAssignedDIALList = getAssignedDIALcodes(childrenHierarchy) - val contentImageAssignedDIALList = childrenAssignedDIALList ++ collectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] + HierarchyManager.getHierarchy(request).flatMap(getImageHierarchyResponse => { + val imageCollectionHierarchy = getImageHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] + val imageChildrenHierarchy = imageCollectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList + val imageChildrenAssignedDIALList = getAssignedDIALcodes(imageChildrenHierarchy) + val contentImageAssignedDIALList = if(imageCollectionHierarchy.containsKey(DIALConstants.DIALCODES) && imageCollectionHierarchy.get(DIALConstants.DIALCODES) != null) + imageChildrenAssignedDIALList ++ imageCollectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] + else imageChildrenAssignedDIALList Future(contentImageAssignedDIALList ++ contentAssignedDIALList) }) @@ -387,7 +388,7 @@ object DIALManager { else List.empty[String] val childDIALMap = if(child.get(DIALConstants.DIALCODES)!=null) - child.get(DIALConstants.DIALCODES).asInstanceOf[List[String]] + child.get(DIALConstants.DIALCODES).asInstanceOf[util.List[String]].asScala.toList else List.empty[String] subChildrenDIALMap ++ childDIALMap From 921801d8703504f2c6e7ce6c5daeaf828f52faf1 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 6 Sep 2022 15:13:19 +0530 Subject: [PATCH 081/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../content/dial/DIALManagerTest.scala | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index 9457a4173..1ea02a355 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -283,6 +283,25 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory }) } + "release DIAL" should "update content with reservedDialcodes excluding the number of dialcodes mentioned in count" in { + (oec.httpUtil _).expects().returns(httpUtil) + (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() + + val nodes: util.List[Node] = getCategoryNode() + (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() + + val contentId: String = "do_123456" + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode(contentId))).anyNumberOfTimes() + (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) + (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode(contentId))) + + val request = getReleaseDIALRequest(contentId) + + val response = DIALManager.release(request) + response.map(result => { + assert(result.getResponseCode.toString=="OK") + }) + } def getDIALSearchResponse:Response = { val resString = "{\n \"id\": \"sunbird.dialcode.search\",\n \"ver\": \"3.0\",\n \"ts\": \"2020-04-21T19:39:14ZZ\",\n \"params\": {\n \"resmsgid\": \"1dfcc25b-6c37-49f8-a6c3-7185063e8752\",\n \"msgid\": null,\n \"err\": null,\n \"status\": \"successful\",\n \"errmsg\": null\n },\n \"responseCode\": \"OK\",\n \"result\": {\n \"dialcodes\": [\n {\n \"dialcode_index\": 7609876,\n \"identifier\": \"N4Z7D5\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.603+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610113,\n \"identifier\": \"E8B7Z6\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.635+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610117,\n \"identifier\": \"R4X2P2\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.637+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7610961,\n \"identifier\": \"L4A6W8\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.734+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n },\n {\n \"dialcode_index\": 7611164,\n \"identifier\": \"D2E1J9\",\n \"channel\": \"testr01\",\n \"batchcode\": \"testPub0001.20200421T193801\",\n \"publisher\": \"testPub0001\",\n \"generated_on\": \"2020-04-21T19:38:01.759+0000\",\n \"status\": \"Draft\",\n \"objectType\": \"DialCode\"\n }\n ],\n \"count\": 5\n }\n}"; @@ -561,7 +580,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory def getReserveRequest():util.Map[String, AnyRef] = { val reqMap : java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){ put("dialcodes", new util.HashMap[String, AnyRef](){ - put("count", 2.asInstanceOf[Integer]) + put("count", 12.asInstanceOf[Integer]) put("qrCodeSpec", new util.HashMap[String, AnyRef](){ put("errorCorrectionLevel", "H") }) @@ -570,6 +589,25 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory reqMap } + def getReleaseDIALRequest(identifier: String): Request = { + val request = new Request() + request.setObjectType("Content") + request.setContext(getContext()) + request.getContext.put("identifier",identifier) + request.put("identifier",identifier) + request.putAll(getReserveRequest()) + request + } + + def getReleaseRequest():util.Map[String, AnyRef] = { + val reqMap : java.util.Map[String, AnyRef] = new util.HashMap[String, AnyRef](){ + put("dialcodes", new util.HashMap[String, AnyRef](){ + put("count", 2.asInstanceOf[Integer]) + }) + } + reqMap + } + def getGenerateDIALResponse:Response = { val resString = "{\"id\": \"api.dialcode.generate\",\"ver\": \"1.0\",\"ts\": \"2022-07-05T09:47:26.000Z\",\"params\": {\"resmsgid\": \"79eb8b00-fc47-11ec-af25-0f53946b16ec\",\"msgid\": \"79be1260-fc47-11ec-8c03-63ca5ce41074\",\"status\": \"successful\",\"err\": null,\"errmsg\": null},\"responseCode\": \"OK\",\"result\": {\"dialcodes\": [\"K2C3R6\",\"H2E8F9\"],\"count\": 2,\"batchcode\": \"do_11357423520695910411\",\"publisher\": null}}" JsonUtils.deserialize(resString, classOf[Response]) From 9c6b84d97b7d41b9d4973830c23465056cf84e31 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 6 Sep 2022 16:18:09 +0530 Subject: [PATCH 082/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../test/scala/org/sunbird/content/dial/DIALManagerTest.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index 1ea02a355..cd8fc38f7 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -250,6 +250,8 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes() (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode("do_1111"))).anyNumberOfTimes() + (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) + (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())) val request = getCollectionRNFRequest() From fa6402edaf2e3d0397a2dff25df28a7dd1ff9dc3 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 6 Sep 2022 16:51:51 +0530 Subject: [PATCH 083/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../sunbird/content/dial/DIALManager.scala | 42 ++++++------ .../content/dial/DIALManagerTest.scala | 64 ++++++++++++++----- 2 files changed, 68 insertions(+), 38 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 332fb07e2..10fc83866 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -351,33 +351,33 @@ object DIALManager { } def populateAssignedDialCodes(contentId: String, contentMetadata: util.Map[String, AnyRef], request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[List[String]] = { - request.put(ContentConstants.MODE,"") request.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) request.getContext.put(ContentConstants.VERSION, ContentConstants.SCHEMA_VERSION) - request.put(ContentConstants.ROOT_ID, contentId.replaceAll(ContentConstants.IMAGE_SUFFIX, "")) - - HierarchyManager.getHierarchy(request).flatMap(getHierarchyResponse => { - val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList - val childrenAssignedDIALList = getAssignedDIALcodes(childrenHierarchy) - val contentAssignedDIALList = if(collectionHierarchy.containsKey(DIALConstants.DIALCODES) && collectionHierarchy.get(DIALConstants.DIALCODES) != null) - childrenAssignedDIALList ++ collectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] - else childrenAssignedDIALList - + request.put(ContentConstants.ROOT_ID, contentMetadata.getOrDefault(ContentConstants.IDENTIFIER,"").asInstanceOf[String]) + request.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) + + HierarchyManager.getHierarchy(request).flatMap(getImageHierarchyResponse => { + val imageCollectionHierarchy = getImageHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] + val imageChildrenHierarchy = imageCollectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList + val imageChildrenAssignedDIALList = getAssignedDIALcodes(imageChildrenHierarchy) + val contentImageAssignedDIALList = if(imageCollectionHierarchy.containsKey(DIALConstants.DIALCODES) && imageCollectionHierarchy.get(DIALConstants.DIALCODES) != null) + imageChildrenAssignedDIALList ++ imageCollectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] + else imageChildrenAssignedDIALList + + request.put(ContentConstants.ROOT_ID, contentId) + request.put(ContentConstants.MODE, "") if(contentMetadata.getOrDefault(ContentConstants.IDENTIFIER,"").asInstanceOf[String].endsWith(ContentConstants.IMAGE_SUFFIX)) { - request.put(ContentConstants.ROOT_ID, contentMetadata.getOrDefault(ContentConstants.IDENTIFIER,"").asInstanceOf[String]) - request.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) - HierarchyManager.getHierarchy(request).flatMap(getImageHierarchyResponse => { - val imageCollectionHierarchy = getImageHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - val imageChildrenHierarchy = imageCollectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList - val imageChildrenAssignedDIALList = getAssignedDIALcodes(imageChildrenHierarchy) - val contentImageAssignedDIALList = if(imageCollectionHierarchy.containsKey(DIALConstants.DIALCODES) && imageCollectionHierarchy.get(DIALConstants.DIALCODES) != null) - imageChildrenAssignedDIALList ++ imageCollectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] - else imageChildrenAssignedDIALList + HierarchyManager.getHierarchy(request).flatMap(getHierarchyResponse => { + val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] + val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList + val childrenAssignedDIALList = getAssignedDIALcodes(childrenHierarchy) + val contentAssignedDIALList = if(collectionHierarchy.containsKey(DIALConstants.DIALCODES) && collectionHierarchy.get(DIALConstants.DIALCODES) != null) + childrenAssignedDIALList ++ collectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] + else childrenAssignedDIALList Future(contentImageAssignedDIALList ++ contentAssignedDIALList) }) - } else Future(contentAssignedDIALList) + } else Future(contentImageAssignedDIALList) }) } diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index cd8fc38f7..c17f31cf0 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -197,9 +197,10 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory val nodes: util.List[Node] = getCategoryNode() (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode("do_1111"))).anyNumberOfTimes() - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) + val contentId = "do_1111" + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy(contentId))).anyNumberOfTimes() + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode(contentId))).anyNumberOfTimes() + (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode(contentId))) (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())) (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) @@ -225,10 +226,10 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory val nodes: util.List[Node] = getCategoryNode() (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode("do_1111"))).anyNumberOfTimes() - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) + val contentId = "do_1111" + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy(contentId))).anyNumberOfTimes() + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode(contentId))).anyNumberOfTimes() + (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode(contentId))) (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())) (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) @@ -247,11 +248,11 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory val nodes: util.List[Node] = getCategoryNode() (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() - - (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy())).anyNumberOfTimes() - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode("do_1111"))).anyNumberOfTimes() + val contentId = "do_1111" + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy(contentId))).anyNumberOfTimes() + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode(contentId))).anyNumberOfTimes() (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) - (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode("do_1111"))) + (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode(contentId))) (graphDB.saveExternalProps(_: Request)).expects(*).returns(Future(new Response())) val request = getCollectionRNFRequest() @@ -286,14 +287,14 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory } "release DIAL" should "update content with reservedDialcodes excluding the number of dialcodes mentioned in count" in { - (oec.httpUtil _).expects().returns(httpUtil) (oec.graphService _).expects().returns(graphDB).anyNumberOfTimes() val nodes: util.List[Node] = getCategoryNode() (graphDB.getNodeByUniqueIds(_: String, _: SearchCriteria)).expects(*, *).returns(Future(nodes)).anyNumberOfTimes() val contentId: String = "do_123456" - (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getNode(contentId))).anyNumberOfTimes() + (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getReleaseNode(contentId))).anyNumberOfTimes() + (graphDB.readExternalProps(_: Request, _: List[String])).expects(*, *).returns(Future(getCassandraHierarchy(contentId))).anyNumberOfTimes() (graphDB.getNodeProperty(_: String, _: String, _: String)).expects(*, *, *).returns(Future(new Property("versionKey", new org.neo4j.driver.internal.value.StringValue("1234")))) (graphDB.upsertNode(_: String, _: Node, _: Request)).expects(*, *, *).returns(Future(getNode(contentId))) @@ -444,6 +445,35 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory node } + def getReleaseNode(identifier: String): Node = { + val node = new Node() + node.setIdentifier(identifier) + node.setNodeType("DATA_NODE") + node.setObjectType("Content") + val reservedDialcodesMap = new util.HashMap[String, Int] (){ + put("V4M9H3", 0); + put("W1I5W9", 1); + put("P7W5F1", 2); + put("A8H7V2", 3); + } + + node.setMetadata(new util.HashMap[String, AnyRef]() { + { + put("identifier", identifier) + put("name", "Test Content") + put("code", "test.resource") + put("contentType", "Resource") + put("mimeType", "application/pdf") + put("status", "Draft") + put("channel", "test") + put("versionKey", "1234") + put("primaryCategory", "Learning Resource") + put("reservedDialcodes", JsonUtils.serialize(reservedDialcodesMap)) + } + }) + node + } + def getCollectionPartialSuccessRequest(): Request = { val request = new Request() request.setObjectType("Content") @@ -540,11 +570,11 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory util.Arrays.asList(node) } - def getCassandraHierarchy(): Response = { + def getCassandraHierarchy(contentId: String): Response = { val hierarchyString: String = - """{"ownershipType": ["createdBy"],"subject": ["Mathematics"],"channel": "0126825293972439041","organisation": ["Sunbird"], + s"""{"ownershipType": ["createdBy"],"subject": ["Mathematics"],"channel": "0126825293972439041","organisation": ["Sunbird"], |"language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","objectType": "Content","gradeLevel": ["Class 4"], - |"primaryCategory": "Digital Textbook","children": [{"ownershipType": ["createdBy"],"parent": "do_1111","code": "do_1132828084877148161531", + |"primaryCategory": "Digital Textbook","children": [{"ownershipType": ["createdBy"],"parent": "$contentId","code": "do_1132828084877148161531", |"keywords": [],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "This chapter describes about human body", |"language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.470+0000", |"objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_2222", @@ -564,7 +594,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory |"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132339274094346241120","audience": ["Student"],"visibility": "Default", |"consumerId": "273f3b18-5dda-4a27-984a-060c7cd398d3","index": 1,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"], |"lastPublishedBy": "8454cb21-3ce9-4e30-85b5-fade097880d8","version": 2,"license": "CC BY 4.0","prevState": "Live","size": 849897.0, - |"lastPublishedOn": "2021-03-21T13:06:11.272+0000","name": "Untitled Content","status": "Live","code": "a88b0257-670b-455b-98b8-6e359ebac009","credentials": {"enabled": "No"},"prevStatus": "Processing","description": "updated","streamingUrl": "https://sunbirddevmedia-inct.streaming.media.azure.net/9c0ebb33-af08-403f-afb4-eb24749f40a1/test-874-kb.ism/manifest(format=m3u8-aapl-v3)","idealScreenSize": "normal","createdOn": "2021-03-11T13:34:14.475+0000","contentDisposition": "inline","lastUpdatedOn": "2021-03-21T13:06:09.526+0000","dialcodeRequired": "No","lastStatusChangedOn": "2021-03-21T18:36:15.799+0530","createdFor": ["ORG_001"],"creator": "Reviewer User","os": ["All"],"se_FWIds": ["NCFCOPY"],"pkgVersion": 14.0,"versionKey": "1616331969523","idealScreenDensity": "hdpi","framework": "NCFCOPY","depth": 4,"s3Key": "ecar_files/do_1132339274094346241120/untitled-content_1616331971279_do_1132339274094346241120_14.0.ecar","createdBy": "95e4942d-cbe8-477d-aebd-ad8e6de4bfc8","compatibilityLevel": 1,"resourceType": "Learn"},{"ownershipType": ["createdBy"],"parent": "do_1132833371215872001720","unitIdentifiers": ["do_1132239562839900161634"],"copyright": "2021 MIT","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_113223967141863424174-latest","plugins": [{"identifier": "org.sunbird.questionunit.quml","semanticVersion": "1.1"}],"subject": ["Hindi"],"channel": "01309282781705830427","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_113223967141863424174/esa_1614253812772_do_113223967141863424174_1.0.ecar","language": ["English"],"source": "https://dock.sunbirded.org/api/content/v1/read/do_1132239617341767681638","mimeType": "application/vnd.ekstep.ecml-archive","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_113223967141863424174/esa_1614253813394_do_113223967141863424174_1.0_spine.ecar","size": 24293.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Class 10"],"primaryCategory": "Exam Question","appId": "dev.dock.portal","contentEncoding": "gzip","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_113223967141863424174/artifact/1614253223147_do_1132239617341767681638.zip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-02-25T11:50:16.032+0000","contentType": "Resource","se_gradeLevels": ["Class 10"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_113223967141863424174","audience": ["Student"],"visibility": "Default","author": "anusha","maxQuestions": 1,"consumerId": "b7054510-3ca4-49fd-b373-b100b3f65e18","index": 2,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "5a587cc1-e018-4859-a0a8-e842650b9d64","version": 2,"se_subjects": ["Hindi"],"license": "CC BY 4.0","prevState": "Review","size": 384798.0,"lastPublishedOn": "2021-02-25T11:50:12.771+0000","name": "esa","topic": ["तोप"],"status": "Live","code": "d19f43ce-753d-2c70-a9fd-70302af424a0","credentials": {"enabled": "No"},"prevStatus": "Processing","origin": "do_1132239617341767681638","streamingUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_113223967141863424174-latest","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-02-25T11:50:01.500+0000","se_boards": ["CBSE"],"processId": "2b00cca7-42d5-4e35-aa03-1c22dfe03de8","contentDisposition": "inline","lastUpdatedOn": "2021-02-25T11:50:12.678+0000","originData": {"identifier": "do_1132239617341767681638","repository": "https://dock.sunbirded.org/api/content/v1/read/do_1132239617341767681638"},"collectionId": "do_1132239562836049921627","dialcodeRequired": "No","editorVersion": 3,"lastStatusChangedOn": "2021-02-25T11:50:16.017+0000","creator": "anusha","os": ["All"],"questionCategories": ["SA"],"cloudStorageKey": "content/do_113223967141863424174/artifact/1614253223147_do_1132239617341767681638.zip","se_FWIds": ["ekstep_ncert_k-12"],"marks": "12","bloomsLevel": ["Apply"],"pkgVersion": 1.0,"versionKey": "1614253812678","idealScreenDensity": "hdpi","framework": "ekstep_ncert_k-12","depth": 4,"s3Key": "ecar_files/do_113223967141863424174/esa_1614253812772_do_113223967141863424174_1.0.ecar","lastSubmittedOn": "2021-02-25T11:50:11.539+0000","createdBy": "19ba0e4e-9285-4335-8dd0-f674bf03fa4d","se_topics": ["तोप"],"compatibilityLevel": 1,"itemSetPreviewUrl": "https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/do_1132239617341767681638/artifact/do_1132239617341767681638_1614253222002.pdf","board": "CBSE","programId": "463cfa30-775c-11eb-8c56-93946e419809"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.475+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "Yes","identifier": "do_1132833371215872001720","lastStatusChangedOn": "2021-05-20T08:58:33.475+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113475","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 3,"compatibilityLevel": 1,"name": "5.1.1 Key parts in the head","topic": [],"status": "Draft"},{"ownershipType": ["createdBy"],"parent": "do_1132833371215134721712","code": "do_1132828084876165121519","keywords": [],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "","language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.473+0000","objectType": "Content","primaryCategory": "Textbook Unit","contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.473+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "No","identifier": "do_1132833371215708161718","lastStatusChangedOn": "2021-05-20T08:58:33.473+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 2,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113473","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 3,"compatibilityLevel": 1,"name": "5.1.2 Other parts","topic": [],"status": "Draft"},{"ownershipType": ["createdBy"],"parent": "do_1132833371215134721712","unitIdentifiers": ["do_11323721176414617611924"],"copyright": "2021 MIT","organisationId": "e7328d77-42a7-44c8-84f4-8cfea235f07d","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1132372524622561281279-latest","plugins": [{"identifier": "org.sunbird.questionunit.quml","semanticVersion": "1.1"}],"subject": ["Mathematics"],"channel": "01309282781705830427","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132372524622561281279/untitled_1615875562931_do_1132372524622561281279_1.0.ecar","language": ["English"],"source": "https://dock.sunbirded.org/api/content/v1/read/do_11323724954450329611930","mimeType": "application/vnd.ekstep.ecml-archive","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132372524622561281279/untitled_1615875563539_do_1132372524622561281279_1.0_spine.ecar","size": 19563.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Class 5"],"primaryCategory": "Exam Question","appId": "dev.dock.portal","contentEncoding": "gzip","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_1132372524622561281279/artifact/1615875430184_do_11323724954450329611930.zip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-03-16T06:19:26.162+0000","contentType": "Resource","se_gradeLevels": ["Class 5"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132372524622561281279","audience": ["Student"],"visibility": "Default","author": "N18","maxQuestions": 1,"consumerId": "f73cfcc5-4d43-4fa0-8b81-46166c81bc2b","learningOutcome": ["identify the need to find area and perimeter of rectangle and square."],"index": 3,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "5a587cc1-e018-4859-a0a8-e842650b9d64","version": 2,"se_subjects": ["Mathematics"],"license": "CC BY 4.0","prevState": "Review","size": 374996.0,"lastPublishedOn": "2021-03-16T06:19:22.931+0000","name": "Untitled","topic": ["Speed, Distance and Time"],"status": "Live","code": "2544c8b8-7946-b6c0-e1c7-ced4aee4ea8c","credentials": {"enabled": "No"},"prevStatus": "Processing","origin": "do_11323724954450329611930","streamingUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1132372524622561281279-latest","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-03-16T06:19:04.712+0000","se_boards": ["CBSE"],"processId": "9995e013-a7c9-4da1-b2c9-2f59da33414a","contentDisposition": "inline","lastUpdatedOn": "2021-03-16T06:19:20.817+0000","originData": {"identifier": "do_11323724954450329611930","repository": "https://dock.sunbirded.org/api/content/v1/read/do_11323724954450329611930"},"collectionId": "do_11323721176353996811921","dialcodeRequired": "No","editorVersion": 3,"lastStatusChangedOn": "2021-03-16T06:19:26.147+0000","creator": "N18","os": ["All"],"questionCategories": ["MTF"],"cloudStorageKey": "content/do_1132372524622561281279/artifact/1615875430184_do_11323724954450329611930.zip","se_FWIds": ["ekstep_ncert_k-12"],"marks": "2","bloomsLevel": ["Apply"],"pkgVersion": 1.0,"versionKey": "1615875560817","idealScreenDensity": "hdpi","framework": "ekstep_ncert_k-12","depth": 3,"s3Key": "ecar_files/do_1132372524622561281279/untitled_1615875562931_do_1132372524622561281279_1.0.ecar","lastSubmittedOn": "2021-03-16T06:19:17.005+0000","createdBy": "60f91e9e-34ee-4f9f-a907-d312d0e8063e","se_topics": ["Speed, Distance and Time"],"compatibilityLevel": 1,"itemSetPreviewUrl": "https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/do_11323724954450329611930/artifact/do_11323724954450329611930_1615875429226.pdf","board": "CBSE","programId": "800eb440-8613-11eb-a663-4f63bbe94184"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.466+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "Yes","identifier": "do_1132833371215134721712","lastStatusChangedOn": "2021-05-20T08:58:33.466+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113466","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 2,"compatibilityLevel": 1,"name": "5.1 Parts of Body","topic": ["Role Of The Sense Organs"],"status": "Draft"},{"ownershipType": ["createdBy"],"parent": "do_2222","code": "do_1132828084877066241529","keywords": [],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "","language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.476+0000","objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_1132833371215953921722","code": "do_1132828084876492801521","keywords": ["test key","check"],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "","language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.468+0000","objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_1132833371215298561714","code": "do_1132828084876820481527","keywords": ["abcd","cgf"],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "labeled new","language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.464+0000","objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_1132833371214970881710","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132338069147811841118/test-874-kb.mp4","channel": "b00bc992ef25f1a9a8d63291e20efc8d","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132338069147811841118/untitled-content_1615468830522_do_1132338069147811841118_2.0.ecar","organisation": ["Sunbird"],"language": ["English"],"mimeType": "video/mp4","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132338069147811841118/untitled-content_1615468834470_do_1132338069147811841118_2.0_spine.ecar","size": 1361.0}},"objectType": "Content","primaryCategory": "Learning Resource","appId": "dev.sunbird.portal","contentEncoding": "identity","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132338069147811841118/test-874-kb.mp4","lockKey": "d73707c8-9999-4fc9-9b34-0207f74faf43","sYS_INTERNAL_LAST_UPDATED_ON": "2021-03-12T08:10:31.335+0000","contentType": "Resource","trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132338069147811841118","audience": ["Student"],"visibility": "Default","consumerId": "273f3b18-5dda-4a27-984a-060c7cd398d3","index": 1,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "8454cb21-3ce9-4e30-85b5-fade097880d8","version": 2,"license": "CC BY 4.0","prevState": "Live","size": 849876.0,"lastPublishedOn": "2021-03-11T13:20:30.514+0000","name": "Untitled Content","status": "Live","code": "9deb2c69-7240-472a-98e7-ed438e76262b","credentials": {"enabled": "No"},"prevStatus": "Processing","streamingUrl": "https://sunbirddevmedia-inct.streaming.media.azure.net/f17bccc5-cab3-4da8-a5eb-11d7211f1507/test-874-kb.ism/manifest(format=m3u8-aapl-v3)","idealScreenSize": "normal","createdOn": "2021-03-11T09:29:05.654+0000","contentDisposition": "inline","lastUpdatedOn": "2021-03-11T13:20:28.256+0000","dialcodeRequired": "No","lastStatusChangedOn": "2021-03-11T18:50:28.256+0530","createdFor": ["ORG_001"],"creator": "Reviewer User","os": ["All"],"se_FWIds": ["NCFCOPY"],"pkgVersion": 2.0,"versionKey": "1615455090358","idealScreenDensity": "hdpi","framework": "NCFCOPY","depth": 5,"s3Key": "ecar_files/do_1132338069147811841118/untitled-content_1615468830522_do_1132338069147811841118_2.0.ecar","createdBy": "95e4942d-cbe8-477d-aebd-ad8e6de4bfc8","compatibilityLevel": 1,"resourceType": "Learn"},{"ownershipType": ["createdBy"],"parent": "do_1132833371214970881710","unitIdentifiers": ["do_1132238266042040321422"],"copyright": "2021 MIT","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_11322383952751820816-latest","plugins": [{"identifier": "org.sunbird.questionunit.quml","semanticVersion": "1.1"}],"subject": ["Hindi"],"channel": "01309282781705830427","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_11322383952751820816/sapractice_1614238238045_do_11322383952751820816_1.0.ecar","language": ["English"],"source": "https://dock.sunbirded.org/api/content/v1/read/do_1132238287156183041424","mimeType": "application/vnd.ekstep.ecml-archive","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_11322383952751820816/sapractice_1614238238800_do_11322383952751820816_1.0_spine.ecar","size": 13171.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Class 10"],"primaryCategory": "Exam Question","appId": "dev.dock.portal","contentEncoding": "gzip","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11322383952751820816/artifact/1614237122171_do_1132238287156183041424.zip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-02-25T07:30:44.916+0000","contentType": "Resource","se_gradeLevels": ["Class 10"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_11322383952751820816","audience": ["Student"],"visibility": "Default","author": "anusha","maxQuestions": 1,"consumerId": "273f3b18-5dda-4a27-984a-060c7cd398d3","index": 2,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "5a587cc1-e018-4859-a0a8-e842650b9d64","version": 2,"se_subjects": ["Hindi"],"license": "CC BY 4.0","prevState": "Review","size": 362236.0,"lastPublishedOn": "2021-02-25T07:30:38.043+0000","name": "sa:practice","status": "Live","code": "f239c77e-ed71-9133-0145-7468a92bce79","credentials": {"enabled": "No"},"prevStatus": "Processing","origin": "do_1132238287156183041424","streamingUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_11322383952751820816-latest","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-02-25T07:30:23.577+0000","se_boards": ["CBSE"],"processId": "04d5aec9-ed09-4a57-963d-9fa654fecf8d","contentDisposition": "inline","lastUpdatedOn": "2021-02-25T07:30:37.956+0000","originData": {"identifier": "do_1132238287156183041424","repository": "https://dock.sunbirded.org/api/content/v1/read/do_1132238287156183041424"},"collectionId": "do_1132238266036551681415","dialcodeRequired": "No","editorVersion": 3,"lastStatusChangedOn": "2021-02-25T07:30:44.908+0000","creator": "anusha","os": ["All"],"questionCategories": ["SA"],"cloudStorageKey": "content/do_11322383952751820816/artifact/1614237122171_do_1132238287156183041424.zip","se_FWIds": ["ekstep_ncert_k-12"],"marks": "12","pkgVersion": 1.0,"versionKey": "1614238237956","idealScreenDensity": "hdpi","framework": "ekstep_ncert_k-12","depth": 5,"s3Key": "ecar_files/do_11322383952751820816/sapractice_1614238238045_do_11322383952751820816_1.0.ecar","lastSubmittedOn": "2021-02-25T07:30:36.709+0000","createdBy": "19ba0e4e-9285-4335-8dd0-f674bf03fa4d","compatibilityLevel": 1,"itemSetPreviewUrl": "https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/do_1132238287156183041424/artifact/do_1132238287156183041424_1614237121022.pdf","board": "CBSE","programId": "94564340-7737-11eb-96e0-29a9f8ed81cf"},{"ownershipType": ["createdBy"],"parent": "do_1132833371214970881710","unitIdentifiers": ["do_11322165488232038412588"],"copyright": "2021 MIT","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1132216902566133761410-latest","plugins": [{"identifier": "org.sunbird.questionunit.quml","semanticVersion": "1.1"}],"subject": ["Environmental Studies"],"channel": "01309282781705830427","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132216902566133761410/mcqmcq_1613975872529_do_1132216902566133761410_1.0.ecar","language": ["English"],"source": "https://dock.sunbirded.org/api/content/v1/read/do_11322168163282944012605","mimeType": "application/vnd.ekstep.ecml-archive","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132216902566133761410/mcqmcq_1613975873161_do_1132216902566133761410_1.0_spine.ecar","size": 17182.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Class 10"],"primaryCategory": "Exam Question","appId": "dev.dock.portal","contentEncoding": "gzip","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_1132216902566133761410/artifact/1613975740738_do_11322168163282944012605.zip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-02-22T06:37:55.328+0000","contentType": "Resource","se_gradeLevels": ["Class 10"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132216902566133761410","audience": ["Student"],"visibility": "Default","author": "color4","maxQuestions": 1,"consumerId": "7411b6bd-89f3-40ec-98d1-229dc64ce77d","learningOutcome": ["Understand the importance of values in life"],"index": 3,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "ae94b68c-a535-4dce-8e7a-fb9662b0ad68","version": 2,"se_subjects": ["Environmental Studies"],"license": "CC BY 4.0","prevState": "Review","size": 370363.0,"lastPublishedOn": "2021-02-22T06:37:52.529+0000","name": "MCQMCQ","topic": ["Animals"],"status": "Live","code": "0cbae0f8-e3eb-1d31-e2e5-0337dc7d697d","credentials": {"enabled": "No"},"prevStatus": "Processing","origin": "do_11322168163282944012605","streamingUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1132216902566133761410-latest","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-02-22T06:37:41.405+0000","se_boards": ["CBSE"],"processId": "fbcec2af-cb7a-4ed1-8683-ff04b475947e","contentDisposition": "inline","lastUpdatedOn": "2021-02-22T06:37:52.447+0000","originData": {"identifier": "do_11322168163282944012605","repository": "https://dock.sunbirded.org/api/content/v1/read/do_11322168163282944012605"},"collectionId": "do_11322165488181248012584","dialcodeRequired": "No","editorVersion": 3,"lastStatusChangedOn": "2021-02-22T06:37:55.314+0000","creator": "color4","os": ["All"],"questionCategories": ["MCQ"],"cloudStorageKey": "content/do_1132216902566133761410/artifact/1613975740738_do_11322168163282944012605.zip","se_FWIds": ["ekstep_ncert_k-12"],"marks": "1","bloomsLevel": ["Understand"],"pkgVersion": 1.0,"versionKey": "1613975872447","idealScreenDensity": "hdpi","framework": "ekstep_ncert_k-12","depth": 5,"s3Key": "ecar_files/do_1132216902566133761410/mcqmcq_1613975872529_do_1132216902566133761410_1.0.ecar","lastSubmittedOn": "2021-02-22T06:37:51.179+0000","createdBy": "0ce5b67e-b48e-489b-a818-e938e8bfc14b","se_topics": ["Animals"],"compatibilityLevel": 1,"itemSetPreviewUrl": "https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/do_11322168163282944012605/artifact/do_11322168163282944012605_1613975739805.pdf","board": "CBSE","programId": "b2433a00-74cd-11eb-9f3c-f39a9ab9f5ce"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.464+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "Yes","identifier": "do_1132833371214970881710","lastStatusChangedOn": "2021-05-20T08:58:33.464+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113464","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 4,"compatibilityLevel": 1,"name": "dsffgdg","topic": [],"status": "Draft"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.468+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "No","identifier": "do_1132833371215298561714","lastStatusChangedOn": "2021-05-20T08:58:33.468+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113468","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 3,"compatibilityLevel": 1,"name": "5.2.1 Respiratory System","topic": ["Look and say","Role Of The Sense Organs"],"status": "Draft"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.476+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "No","identifier": "do_1132833371215953921722","lastStatusChangedOn": "2021-05-20T08:58:33.476+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 2,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113476","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 2,"compatibilityLevel": 1,"name": "5.2 Organ Systems","topic": [],"status": "Draft"},{"ownershipType": ["createdBy"],"parent": "do_2222","copyright": "Sunbird","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132344630588948481134/test-874-kb.mp4","subject": ["Math"],"channel": "b00bc992ef25f1a9a8d63291e20efc8d","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132344630588948481134/untitled-content_1615535618825_do_1132344630588948481134_2.0.ecar","organisation": ["Sunbird"],"showNotification": true,"language": ["English"],"mimeType": "video/mp4","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132344630588948481134/untitled-content_1615535619590_do_1132344630588948481134_2.0_spine.ecar","size": 35301.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Grade 1"],"appIcon": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_1132344630588948481134/artifact/2a4b8abd789184932399d222d03d9b5c.thumb.jpg","primaryCategory": "Learning Resource","appId": "dev.sunbird.portal","contentEncoding": "identity","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132344630588948481134/test-874-kb.mp4","lockKey": "1d28d983-2704-44bd-803e-5feb4e62da62","sYS_INTERNAL_LAST_UPDATED_ON": "2021-03-12T08:10:34.367+0000","contentType": "Resource","se_gradeLevels": ["Grade 1"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132344630588948481134","lastUpdatedBy": "95e4942d-cbe8-477d-aebd-ad8e6de4bfc8","audience": ["Student"],"visibility": "Default","consumerId": "273f3b18-5dda-4a27-984a-060c7cd398d3","index": 3,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "8454cb21-3ce9-4e30-85b5-fade097880d8","version": 2,"se_subjects": ["Math"],"license": "CC BY 4.0","prevState": "Review","size": 883817.0,"lastPublishedOn": "2021-03-12T07:53:38.825+0000","name": "Untitled Content","status": "Live","code": "8851e754-6e20-44d4-9070-e1a9664163ad","credentials": {"enabled": "No"},"prevStatus": "Review","description": "updated desrciption","streamingUrl": "https://sunbirddevmedia-inct.streaming.media.azure.net/40ae07aa-069e-4056-8f2b-014bc9a2d21b/test-874-kb.ism/manifest(format=m3u8-aapl-v3)","medium": ["English"],"posterImage": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11299104587967692816/artifact/2a4b8abd789184932399d222d03d9b5c.jpg","idealScreenSize": "normal","createdOn": "2021-03-12T07:44:01.371+0000","se_boards": ["NCERT"],"copyrightYear": 2020,"contentDisposition": "inline","licenseterms": "By creating any type of content (resources, books, courses etc.) on DIKSHA, you consent to publish it under the Creative Commons License Framework. Please choose the applicable creative commons license you wish to apply to your content.","lastUpdatedOn": "2021-03-12T07:53:38.505+0000","dialcodeRequired": "No","lastStatusChangedOn": "2021-03-12T07:53:38.494+0000","createdFor": ["ORG_001"],"creator": "Reviewer User","os": ["All"],"se_FWIds": ["NCFCOPY"],"pkgVersion": 2.0,"versionKey": "1615535618583","idealScreenDensity": "hdpi","framework": "NCFCOPY","depth": 2,"s3Key": "ecar_files/do_1132344630588948481134/untitled-content_1615535618825_do_1132344630588948481134_2.0.ecar","lastSubmittedOn": "2021-03-12T07:53:10.005+0000","createdBy": "95e4942d-cbe8-477d-aebd-ad8e6de4bfc8","compatibilityLevel": 1,"board": "NCERT","resourceType": "Learn"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.470+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "No","identifier": "do_2222","lastStatusChangedOn": "2021-05-20T08:58:33.470+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113470","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 1,"compatibilityLevel": 1,"name": "5. Human Body","topic": [],"status": "Draft"}],"appId": "dev.sunbird.portal","contentEncoding": "gzip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-05-20T09:12:06.988+0000","contentType": "TextBook","trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1111","audience": ["Student"],"visibility": "Default","consumerId": "01814e02-fc27-4165-ae53-3d1816e55817","childNodes": ["do_1132339274094346241120","do_1132833371215872001720","do_1132833371215134721712","do_2222","do_113223967141863424174","do_1132833371214970881710","do_1132833371215708161718","do_1132372524622561281279","do_1132338069147811841118","do_1132833371215298561714","do_1132833371215953921722","do_11322383952751820816","do_1132216902566133761410","do_1132344630588948481134"],"discussionForum": {"enabled": "Yes"},"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"version": 2,"license": "CC BY 4.0","name": "TestCSVUpload","status": "Draft","code": "org.sunbird.yhqB6L","credentials": {"enabled": "No"},"description": "Enter description for TextBook","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-05-19T15:00:44.279+0000","contentDisposition": "inline","additionalCategories": ["Textbook"],"lastUpdatedOn": "2021-05-20T07:10:32.805+0000","dialcodeRequired": "No","lastStatusChangedOn": "2021-05-19T15:00:44.279+0000","createdFor": ["0126825293972439041"],"creator": "Book Creator","os": ["All"],"versionKey": "1621501113536","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 0,"createdBy": "8454cb21-3ce9-4e30-85b5-fade097880d8","compatibilityLevel": 1,"userConsent": "Yes","board": "State (Tamil Nadu)","resourceType": "Book"}""".stripMargin + |"lastPublishedOn": "2021-03-21T13:06:11.272+0000","name": "Untitled Content","status": "Live","code": "a88b0257-670b-455b-98b8-6e359ebac009","credentials": {"enabled": "No"},"prevStatus": "Processing","description": "updated","streamingUrl": "https://sunbirddevmedia-inct.streaming.media.azure.net/9c0ebb33-af08-403f-afb4-eb24749f40a1/test-874-kb.ism/manifest(format=m3u8-aapl-v3)","idealScreenSize": "normal","createdOn": "2021-03-11T13:34:14.475+0000","contentDisposition": "inline","lastUpdatedOn": "2021-03-21T13:06:09.526+0000","dialcodeRequired": "No","lastStatusChangedOn": "2021-03-21T18:36:15.799+0530","createdFor": ["ORG_001"],"creator": "Reviewer User","os": ["All"],"se_FWIds": ["NCFCOPY"],"pkgVersion": 14.0,"versionKey": "1616331969523","idealScreenDensity": "hdpi","framework": "NCFCOPY","depth": 4,"s3Key": "ecar_files/do_1132339274094346241120/untitled-content_1616331971279_do_1132339274094346241120_14.0.ecar","createdBy": "95e4942d-cbe8-477d-aebd-ad8e6de4bfc8","compatibilityLevel": 1,"resourceType": "Learn"},{"ownershipType": ["createdBy"],"parent": "do_1132833371215872001720","unitIdentifiers": ["do_1132239562839900161634"],"copyright": "2021 MIT","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_113223967141863424174-latest","plugins": [{"identifier": "org.sunbird.questionunit.quml","semanticVersion": "1.1"}],"subject": ["Hindi"],"channel": "01309282781705830427","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_113223967141863424174/esa_1614253812772_do_113223967141863424174_1.0.ecar","language": ["English"],"source": "https://dock.sunbirded.org/api/content/v1/read/do_1132239617341767681638","mimeType": "application/vnd.ekstep.ecml-archive","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_113223967141863424174/esa_1614253813394_do_113223967141863424174_1.0_spine.ecar","size": 24293.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Class 10"],"primaryCategory": "Exam Question","appId": "dev.dock.portal","contentEncoding": "gzip","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_113223967141863424174/artifact/1614253223147_do_1132239617341767681638.zip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-02-25T11:50:16.032+0000","contentType": "Resource","se_gradeLevels": ["Class 10"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_113223967141863424174","audience": ["Student"],"visibility": "Default","author": "anusha","maxQuestions": 1,"consumerId": "b7054510-3ca4-49fd-b373-b100b3f65e18","index": 2,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "5a587cc1-e018-4859-a0a8-e842650b9d64","version": 2,"se_subjects": ["Hindi"],"license": "CC BY 4.0","prevState": "Review","size": 384798.0,"lastPublishedOn": "2021-02-25T11:50:12.771+0000","name": "esa","topic": ["तोप"],"status": "Live","code": "d19f43ce-753d-2c70-a9fd-70302af424a0","credentials": {"enabled": "No"},"prevStatus": "Processing","origin": "do_1132239617341767681638","streamingUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_113223967141863424174-latest","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-02-25T11:50:01.500+0000","se_boards": ["CBSE"],"processId": "2b00cca7-42d5-4e35-aa03-1c22dfe03de8","contentDisposition": "inline","lastUpdatedOn": "2021-02-25T11:50:12.678+0000","originData": {"identifier": "do_1132239617341767681638","repository": "https://dock.sunbirded.org/api/content/v1/read/do_1132239617341767681638"},"collectionId": "do_1132239562836049921627","dialcodeRequired": "No","editorVersion": 3,"lastStatusChangedOn": "2021-02-25T11:50:16.017+0000","creator": "anusha","os": ["All"],"questionCategories": ["SA"],"cloudStorageKey": "content/do_113223967141863424174/artifact/1614253223147_do_1132239617341767681638.zip","se_FWIds": ["ekstep_ncert_k-12"],"marks": "12","bloomsLevel": ["Apply"],"pkgVersion": 1.0,"versionKey": "1614253812678","idealScreenDensity": "hdpi","framework": "ekstep_ncert_k-12","depth": 4,"s3Key": "ecar_files/do_113223967141863424174/esa_1614253812772_do_113223967141863424174_1.0.ecar","lastSubmittedOn": "2021-02-25T11:50:11.539+0000","createdBy": "19ba0e4e-9285-4335-8dd0-f674bf03fa4d","se_topics": ["तोप"],"compatibilityLevel": 1,"itemSetPreviewUrl": "https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/do_1132239617341767681638/artifact/do_1132239617341767681638_1614253222002.pdf","board": "CBSE","programId": "463cfa30-775c-11eb-8c56-93946e419809"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.475+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "Yes","identifier": "do_1132833371215872001720","lastStatusChangedOn": "2021-05-20T08:58:33.475+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113475","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 3,"compatibilityLevel": 1,"name": "5.1.1 Key parts in the head","topic": [],"status": "Draft"},{"ownershipType": ["createdBy"],"parent": "do_1132833371215134721712","code": "do_1132828084876165121519","keywords": [],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "","language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.473+0000","objectType": "Content","primaryCategory": "Textbook Unit","contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.473+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "No","identifier": "do_1132833371215708161718","lastStatusChangedOn": "2021-05-20T08:58:33.473+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 2,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113473","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 3,"compatibilityLevel": 1,"name": "5.1.2 Other parts","topic": [],"status": "Draft"},{"ownershipType": ["createdBy"],"parent": "do_1132833371215134721712","unitIdentifiers": ["do_11323721176414617611924"],"copyright": "2021 MIT","organisationId": "e7328d77-42a7-44c8-84f4-8cfea235f07d","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1132372524622561281279-latest","plugins": [{"identifier": "org.sunbird.questionunit.quml","semanticVersion": "1.1"}],"subject": ["Mathematics"],"channel": "01309282781705830427","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132372524622561281279/untitled_1615875562931_do_1132372524622561281279_1.0.ecar","language": ["English"],"source": "https://dock.sunbirded.org/api/content/v1/read/do_11323724954450329611930","mimeType": "application/vnd.ekstep.ecml-archive","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132372524622561281279/untitled_1615875563539_do_1132372524622561281279_1.0_spine.ecar","size": 19563.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Class 5"],"primaryCategory": "Exam Question","appId": "dev.dock.portal","contentEncoding": "gzip","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_1132372524622561281279/artifact/1615875430184_do_11323724954450329611930.zip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-03-16T06:19:26.162+0000","contentType": "Resource","se_gradeLevels": ["Class 5"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132372524622561281279","audience": ["Student"],"visibility": "Default","author": "N18","maxQuestions": 1,"consumerId": "f73cfcc5-4d43-4fa0-8b81-46166c81bc2b","learningOutcome": ["identify the need to find area and perimeter of rectangle and square."],"index": 3,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "5a587cc1-e018-4859-a0a8-e842650b9d64","version": 2,"se_subjects": ["Mathematics"],"license": "CC BY 4.0","prevState": "Review","size": 374996.0,"lastPublishedOn": "2021-03-16T06:19:22.931+0000","name": "Untitled","topic": ["Speed, Distance and Time"],"status": "Live","code": "2544c8b8-7946-b6c0-e1c7-ced4aee4ea8c","credentials": {"enabled": "No"},"prevStatus": "Processing","origin": "do_11323724954450329611930","streamingUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1132372524622561281279-latest","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-03-16T06:19:04.712+0000","se_boards": ["CBSE"],"processId": "9995e013-a7c9-4da1-b2c9-2f59da33414a","contentDisposition": "inline","lastUpdatedOn": "2021-03-16T06:19:20.817+0000","originData": {"identifier": "do_11323724954450329611930","repository": "https://dock.sunbirded.org/api/content/v1/read/do_11323724954450329611930"},"collectionId": "do_11323721176353996811921","dialcodeRequired": "No","editorVersion": 3,"lastStatusChangedOn": "2021-03-16T06:19:26.147+0000","creator": "N18","os": ["All"],"questionCategories": ["MTF"],"cloudStorageKey": "content/do_1132372524622561281279/artifact/1615875430184_do_11323724954450329611930.zip","se_FWIds": ["ekstep_ncert_k-12"],"marks": "2","bloomsLevel": ["Apply"],"pkgVersion": 1.0,"versionKey": "1615875560817","idealScreenDensity": "hdpi","framework": "ekstep_ncert_k-12","depth": 3,"s3Key": "ecar_files/do_1132372524622561281279/untitled_1615875562931_do_1132372524622561281279_1.0.ecar","lastSubmittedOn": "2021-03-16T06:19:17.005+0000","createdBy": "60f91e9e-34ee-4f9f-a907-d312d0e8063e","se_topics": ["Speed, Distance and Time"],"compatibilityLevel": 1,"itemSetPreviewUrl": "https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/do_11323724954450329611930/artifact/do_11323724954450329611930_1615875429226.pdf","board": "CBSE","programId": "800eb440-8613-11eb-a663-4f63bbe94184"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.466+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "Yes","identifier": "do_1132833371215134721712","lastStatusChangedOn": "2021-05-20T08:58:33.466+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113466","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 2,"compatibilityLevel": 1,"name": "5.1 Parts of Body","topic": ["Role Of The Sense Organs"],"status": "Draft"},{"ownershipType": ["createdBy"],"parent": "do_2222","code": "do_1132828084877066241529","keywords": [],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "","language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.476+0000","objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_1132833371215953921722","code": "do_1132828084876492801521","keywords": ["test key","check"],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "","language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.468+0000","objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_1132833371215298561714","code": "do_1132828084876820481527","keywords": ["abcd","cgf"],"credentials": {"enabled": "No"},"channel": "0126825293972439041","description": "labeled new","language": ["English"],"mimeType": "application/vnd.ekstep.content-collection","idealScreenSize": "normal","createdOn": "2021-05-20T08:58:33.464+0000","objectType": "Content","primaryCategory": "Textbook Unit","children": [{"ownershipType": ["createdBy"],"parent": "do_1132833371214970881710","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132338069147811841118/test-874-kb.mp4","channel": "b00bc992ef25f1a9a8d63291e20efc8d","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132338069147811841118/untitled-content_1615468830522_do_1132338069147811841118_2.0.ecar","organisation": ["Sunbird"],"language": ["English"],"mimeType": "video/mp4","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132338069147811841118/untitled-content_1615468834470_do_1132338069147811841118_2.0_spine.ecar","size": 1361.0}},"objectType": "Content","primaryCategory": "Learning Resource","appId": "dev.sunbird.portal","contentEncoding": "identity","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132338069147811841118/test-874-kb.mp4","lockKey": "d73707c8-9999-4fc9-9b34-0207f74faf43","sYS_INTERNAL_LAST_UPDATED_ON": "2021-03-12T08:10:31.335+0000","contentType": "Resource","trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132338069147811841118","audience": ["Student"],"visibility": "Default","consumerId": "273f3b18-5dda-4a27-984a-060c7cd398d3","index": 1,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "8454cb21-3ce9-4e30-85b5-fade097880d8","version": 2,"license": "CC BY 4.0","prevState": "Live","size": 849876.0,"lastPublishedOn": "2021-03-11T13:20:30.514+0000","name": "Untitled Content","status": "Live","code": "9deb2c69-7240-472a-98e7-ed438e76262b","credentials": {"enabled": "No"},"prevStatus": "Processing","streamingUrl": "https://sunbirddevmedia-inct.streaming.media.azure.net/f17bccc5-cab3-4da8-a5eb-11d7211f1507/test-874-kb.ism/manifest(format=m3u8-aapl-v3)","idealScreenSize": "normal","createdOn": "2021-03-11T09:29:05.654+0000","contentDisposition": "inline","lastUpdatedOn": "2021-03-11T13:20:28.256+0000","dialcodeRequired": "No","lastStatusChangedOn": "2021-03-11T18:50:28.256+0530","createdFor": ["ORG_001"],"creator": "Reviewer User","os": ["All"],"se_FWIds": ["NCFCOPY"],"pkgVersion": 2.0,"versionKey": "1615455090358","idealScreenDensity": "hdpi","framework": "NCFCOPY","depth": 5,"s3Key": "ecar_files/do_1132338069147811841118/untitled-content_1615468830522_do_1132338069147811841118_2.0.ecar","createdBy": "95e4942d-cbe8-477d-aebd-ad8e6de4bfc8","compatibilityLevel": 1,"resourceType": "Learn"},{"ownershipType": ["createdBy"],"parent": "do_1132833371214970881710","unitIdentifiers": ["do_1132238266042040321422"],"copyright": "2021 MIT","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_11322383952751820816-latest","plugins": [{"identifier": "org.sunbird.questionunit.quml","semanticVersion": "1.1"}],"subject": ["Hindi"],"channel": "01309282781705830427","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_11322383952751820816/sapractice_1614238238045_do_11322383952751820816_1.0.ecar","language": ["English"],"source": "https://dock.sunbirded.org/api/content/v1/read/do_1132238287156183041424","mimeType": "application/vnd.ekstep.ecml-archive","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_11322383952751820816/sapractice_1614238238800_do_11322383952751820816_1.0_spine.ecar","size": 13171.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Class 10"],"primaryCategory": "Exam Question","appId": "dev.dock.portal","contentEncoding": "gzip","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11322383952751820816/artifact/1614237122171_do_1132238287156183041424.zip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-02-25T07:30:44.916+0000","contentType": "Resource","se_gradeLevels": ["Class 10"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_11322383952751820816","audience": ["Student"],"visibility": "Default","author": "anusha","maxQuestions": 1,"consumerId": "273f3b18-5dda-4a27-984a-060c7cd398d3","index": 2,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "5a587cc1-e018-4859-a0a8-e842650b9d64","version": 2,"se_subjects": ["Hindi"],"license": "CC BY 4.0","prevState": "Review","size": 362236.0,"lastPublishedOn": "2021-02-25T07:30:38.043+0000","name": "sa:practice","status": "Live","code": "f239c77e-ed71-9133-0145-7468a92bce79","credentials": {"enabled": "No"},"prevStatus": "Processing","origin": "do_1132238287156183041424","streamingUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_11322383952751820816-latest","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-02-25T07:30:23.577+0000","se_boards": ["CBSE"],"processId": "04d5aec9-ed09-4a57-963d-9fa654fecf8d","contentDisposition": "inline","lastUpdatedOn": "2021-02-25T07:30:37.956+0000","originData": {"identifier": "do_1132238287156183041424","repository": "https://dock.sunbirded.org/api/content/v1/read/do_1132238287156183041424"},"collectionId": "do_1132238266036551681415","dialcodeRequired": "No","editorVersion": 3,"lastStatusChangedOn": "2021-02-25T07:30:44.908+0000","creator": "anusha","os": ["All"],"questionCategories": ["SA"],"cloudStorageKey": "content/do_11322383952751820816/artifact/1614237122171_do_1132238287156183041424.zip","se_FWIds": ["ekstep_ncert_k-12"],"marks": "12","pkgVersion": 1.0,"versionKey": "1614238237956","idealScreenDensity": "hdpi","framework": "ekstep_ncert_k-12","depth": 5,"s3Key": "ecar_files/do_11322383952751820816/sapractice_1614238238045_do_11322383952751820816_1.0.ecar","lastSubmittedOn": "2021-02-25T07:30:36.709+0000","createdBy": "19ba0e4e-9285-4335-8dd0-f674bf03fa4d","compatibilityLevel": 1,"itemSetPreviewUrl": "https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/do_1132238287156183041424/artifact/do_1132238287156183041424_1614237121022.pdf","board": "CBSE","programId": "94564340-7737-11eb-96e0-29a9f8ed81cf"},{"ownershipType": ["createdBy"],"parent": "do_1132833371214970881710","unitIdentifiers": ["do_11322165488232038412588"],"copyright": "2021 MIT","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1132216902566133761410-latest","plugins": [{"identifier": "org.sunbird.questionunit.quml","semanticVersion": "1.1"}],"subject": ["Environmental Studies"],"channel": "01309282781705830427","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132216902566133761410/mcqmcq_1613975872529_do_1132216902566133761410_1.0.ecar","language": ["English"],"source": "https://dock.sunbirded.org/api/content/v1/read/do_11322168163282944012605","mimeType": "application/vnd.ekstep.ecml-archive","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132216902566133761410/mcqmcq_1613975873161_do_1132216902566133761410_1.0_spine.ecar","size": 17182.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Class 10"],"primaryCategory": "Exam Question","appId": "dev.dock.portal","contentEncoding": "gzip","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_1132216902566133761410/artifact/1613975740738_do_11322168163282944012605.zip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-02-22T06:37:55.328+0000","contentType": "Resource","se_gradeLevels": ["Class 10"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132216902566133761410","audience": ["Student"],"visibility": "Default","author": "color4","maxQuestions": 1,"consumerId": "7411b6bd-89f3-40ec-98d1-229dc64ce77d","learningOutcome": ["Understand the importance of values in life"],"index": 3,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "ae94b68c-a535-4dce-8e7a-fb9662b0ad68","version": 2,"se_subjects": ["Environmental Studies"],"license": "CC BY 4.0","prevState": "Review","size": 370363.0,"lastPublishedOn": "2021-02-22T06:37:52.529+0000","name": "MCQMCQ","topic": ["Animals"],"status": "Live","code": "0cbae0f8-e3eb-1d31-e2e5-0337dc7d697d","credentials": {"enabled": "No"},"prevStatus": "Processing","origin": "do_11322168163282944012605","streamingUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/ecml/do_1132216902566133761410-latest","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-02-22T06:37:41.405+0000","se_boards": ["CBSE"],"processId": "fbcec2af-cb7a-4ed1-8683-ff04b475947e","contentDisposition": "inline","lastUpdatedOn": "2021-02-22T06:37:52.447+0000","originData": {"identifier": "do_11322168163282944012605","repository": "https://dock.sunbirded.org/api/content/v1/read/do_11322168163282944012605"},"collectionId": "do_11322165488181248012584","dialcodeRequired": "No","editorVersion": 3,"lastStatusChangedOn": "2021-02-22T06:37:55.314+0000","creator": "color4","os": ["All"],"questionCategories": ["MCQ"],"cloudStorageKey": "content/do_1132216902566133761410/artifact/1613975740738_do_11322168163282944012605.zip","se_FWIds": ["ekstep_ncert_k-12"],"marks": "1","bloomsLevel": ["Understand"],"pkgVersion": 1.0,"versionKey": "1613975872447","idealScreenDensity": "hdpi","framework": "ekstep_ncert_k-12","depth": 5,"s3Key": "ecar_files/do_1132216902566133761410/mcqmcq_1613975872529_do_1132216902566133761410_1.0.ecar","lastSubmittedOn": "2021-02-22T06:37:51.179+0000","createdBy": "0ce5b67e-b48e-489b-a818-e938e8bfc14b","se_topics": ["Animals"],"compatibilityLevel": 1,"itemSetPreviewUrl": "https://dockstorage.blob.core.windows.net/sunbird-content-dock/content/do_11322168163282944012605/artifact/do_11322168163282944012605_1613975739805.pdf","board": "CBSE","programId": "b2433a00-74cd-11eb-9f3c-f39a9ab9f5ce"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.464+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "Yes","identifier": "do_1132833371214970881710","lastStatusChangedOn": "2021-05-20T08:58:33.464+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113464","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 4,"compatibilityLevel": 1,"name": "dsffgdg","topic": [],"status": "Draft"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.468+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "No","identifier": "do_1132833371215298561714","lastStatusChangedOn": "2021-05-20T08:58:33.468+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113468","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 3,"compatibilityLevel": 1,"name": "5.2.1 Respiratory System","topic": ["Look and say","Role Of The Sense Organs"],"status": "Draft"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.476+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "No","identifier": "do_1132833371215953921722","lastStatusChangedOn": "2021-05-20T08:58:33.476+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 2,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113476","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 2,"compatibilityLevel": 1,"name": "5.2 Organ Systems","topic": [],"status": "Draft"},{"ownershipType": ["createdBy"],"parent": "do_2222","copyright": "Sunbird","previewUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132344630588948481134/test-874-kb.mp4","subject": ["Math"],"channel": "b00bc992ef25f1a9a8d63291e20efc8d","downloadUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132344630588948481134/untitled-content_1615535618825_do_1132344630588948481134_2.0.ecar","organisation": ["Sunbird"],"showNotification": true,"language": ["English"],"mimeType": "video/mp4","variants": {"spine": {"ecarUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/ecar_files/do_1132344630588948481134/untitled-content_1615535619590_do_1132344630588948481134_2.0_spine.ecar","size": 35301.0}},"objectType": "Content","se_mediums": ["English"],"gradeLevel": ["Grade 1"],"appIcon": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_1132344630588948481134/artifact/2a4b8abd789184932399d222d03d9b5c.thumb.jpg","primaryCategory": "Learning Resource","appId": "dev.sunbird.portal","contentEncoding": "identity","artifactUrl": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/assets/do_1132344630588948481134/test-874-kb.mp4","lockKey": "1d28d983-2704-44bd-803e-5feb4e62da62","sYS_INTERNAL_LAST_UPDATED_ON": "2021-03-12T08:10:34.367+0000","contentType": "Resource","se_gradeLevels": ["Grade 1"],"trackable": {"enabled": "No","autoBatch": "No"},"identifier": "do_1132344630588948481134","lastUpdatedBy": "95e4942d-cbe8-477d-aebd-ad8e6de4bfc8","audience": ["Student"],"visibility": "Default","consumerId": "273f3b18-5dda-4a27-984a-060c7cd398d3","index": 3,"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"lastPublishedBy": "8454cb21-3ce9-4e30-85b5-fade097880d8","version": 2,"se_subjects": ["Math"],"license": "CC BY 4.0","prevState": "Review","size": 883817.0,"lastPublishedOn": "2021-03-12T07:53:38.825+0000","name": "Untitled Content","status": "Live","code": "8851e754-6e20-44d4-9070-e1a9664163ad","credentials": {"enabled": "No"},"prevStatus": "Review","description": "updated desrciption","streamingUrl": "https://sunbirddevmedia-inct.streaming.media.azure.net/40ae07aa-069e-4056-8f2b-014bc9a2d21b/test-874-kb.ism/manifest(format=m3u8-aapl-v3)","medium": ["English"],"posterImage": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/do_11299104587967692816/artifact/2a4b8abd789184932399d222d03d9b5c.jpg","idealScreenSize": "normal","createdOn": "2021-03-12T07:44:01.371+0000","se_boards": ["NCERT"],"copyrightYear": 2020,"contentDisposition": "inline","licenseterms": "By creating any type of content (resources, books, courses etc.) on DIKSHA, you consent to publish it under the Creative Commons License Framework. Please choose the applicable creative commons license you wish to apply to your content.","lastUpdatedOn": "2021-03-12T07:53:38.505+0000","dialcodeRequired": "No","lastStatusChangedOn": "2021-03-12T07:53:38.494+0000","createdFor": ["ORG_001"],"creator": "Reviewer User","os": ["All"],"se_FWIds": ["NCFCOPY"],"pkgVersion": 2.0,"versionKey": "1615535618583","idealScreenDensity": "hdpi","framework": "NCFCOPY","depth": 2,"s3Key": "ecar_files/do_1132344630588948481134/untitled-content_1615535618825_do_1132344630588948481134_2.0.ecar","lastSubmittedOn": "2021-03-12T07:53:10.005+0000","createdBy": "95e4942d-cbe8-477d-aebd-ad8e6de4bfc8","compatibilityLevel": 1,"board": "NCERT","resourceType": "Learn"}],"contentDisposition": "inline","lastUpdatedOn": "2021-05-20T08:58:33.470+0000","contentEncoding": "gzip","contentType": "TextBookUnit","dialcodeRequired": "No","identifier": "do_2222","lastStatusChangedOn": "2021-05-20T08:58:33.470+0000","audience": ["Student"],"os": ["All"],"visibility": "Parent","discussionForum": {"enabled": "Yes"},"index": 1,"mediaType": "content","osId": "org.ekstep.launcher","languageCode": ["en"],"version": 2,"versionKey": "1621501113470","license": "CC BY 4.0","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 1,"compatibilityLevel": 1,"name": "5. Human Body","topic": [],"status": "Draft"}],"appId": "dev.sunbird.portal","contentEncoding": "gzip","sYS_INTERNAL_LAST_UPDATED_ON": "2021-05-20T09:12:06.988+0000","contentType": "TextBook","trackable": {"enabled": "No","autoBatch": "No"},"identifier": "$contentId","audience": ["Student"],"visibility": "Default","consumerId": "01814e02-fc27-4165-ae53-3d1816e55817","childNodes": ["do_1132339274094346241120","do_1132833371215872001720","do_1132833371215134721712","do_2222","do_113223967141863424174","do_1132833371214970881710","do_1132833371215708161718","do_1132372524622561281279","do_1132338069147811841118","do_1132833371215298561714","do_1132833371215953921722","do_11322383952751820816","do_1132216902566133761410","do_1132344630588948481134"],"discussionForum": {"enabled": "Yes"},"mediaType": "content","osId": "org.ekstep.quiz.app","languageCode": ["en"],"version": 2,"license": "CC BY 4.0","name": "TestCSVUpload","status": "Draft","code": "org.sunbird.yhqB6L","credentials": {"enabled": "No"},"description": "Enter description for TextBook","medium": ["English"],"idealScreenSize": "normal","createdOn": "2021-05-19T15:00:44.279+0000","contentDisposition": "inline","additionalCategories": ["Textbook"],"lastUpdatedOn": "2021-05-20T07:10:32.805+0000","dialcodeRequired": "No","lastStatusChangedOn": "2021-05-19T15:00:44.279+0000","createdFor": ["0126825293972439041"],"creator": "Book Creator","os": ["All"],"versionKey": "1621501113536","idealScreenDensity": "hdpi","framework": "tn_k-12","depth": 0,"createdBy": "8454cb21-3ce9-4e30-85b5-fade097880d8","compatibilityLevel": 1,"userConsent": "Yes","board": "State (Tamil Nadu)","resourceType": "Book"}""".stripMargin val response = new Response response.put("hierarchy", hierarchyString) } From 96ba80b11e0b8e15e3a947bf2757264b271dc716 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 7 Sep 2022 11:30:07 +0530 Subject: [PATCH 084/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../sunbird/content/actors/ContentActor.scala | 4 +- .../org/sunbird/content/dial/DIALErrors.scala | 2 + .../sunbird/content/dial/DIALManager.scala | 120 +++++++++--------- .../content/util/ContentConstants.scala | 2 + .../content/dial/DIALManagerTest.scala | 4 +- 5 files changed, 65 insertions(+), 67 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala index 0ac9ef335..89d19882f 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala @@ -181,9 +181,9 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe def linkDIALCode(request: Request): Future[Response] = DIALManager.link(request) - def reserveDialCode(request: Request): Future[Response] = DIALManager.reserve(request) + def reserveDialCode(request: Request): Future[Response] = DIALManager.reserveOrRelease(request, ContentConstants.RESERVE) - def releaseDialCode(request: Request): Future[Response] = DIALManager.release(request) + def releaseDialCode(request: Request): Future[Response] = DIALManager.reserveOrRelease(request, ContentConstants.RELEASE) def importContent(request: Request): Future[Response] = importMgr.importObject(request) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala index 3ecd0acdb..bb7622e91 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala @@ -16,6 +16,7 @@ object DIALErrors { val ERR_CONTENT_RETIRED_OBJECT_ID: String = "ERR_CONTENT_RETIRED_OBJECT_ID" val ERR_CONTENT_MISSING_RESERVED_DIAL_CODES: String = "ERR_CONTENT_MISSING_RESERVED_DIAL_CODES" val ERR_ALL_DIALCODES_UTILIZED: String = "ERR_ALL_DIALCODES_UTILIZED" + val ERR_INVALID_OPERATION: String = "ERR_INVALID_OPERATION" //Error Messages val ERR_INVALID_REQ_MSG: String = "Invalid Request! Please Provide Valid Request." @@ -38,4 +39,5 @@ object DIALErrors { val ERR_CONTENT_RETIRED_OBJECT_ID_MSG: String = "Invalid Request. Cannot update 'Retired' content." val ERR_CONTENT_MISSING_RESERVED_DIAL_CODES_MSG: String = "Invalid Request. Content does not have reserved DIAL codes." val ERR_ALL_DIALCODES_UTILIZED_MSG: String = "Error! All Reserved DIAL Codes are Utilized." + val ERR_INVALID_OPERATION_MSG: String = "Invalid operation request!" } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 10fc83866..755ebfb56 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -261,7 +261,7 @@ object DIALManager { throw new ClientException(DIALErrors.ERR_DUPLICATE_DIAL_CODES, DIALErrors.ERR_DUPLICATE_DIAL_CODES_MSG + duplicateDIALCodes) } - def reserve(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { + def reserveOrRelease(request: Request, operation: String)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { val channelId: String = request.getContext.getOrDefault(DIALConstants.CHANNEL, "").asInstanceOf[String] val contentId: String = request.get(ContentConstants.IDENTIFIER).asInstanceOf[String] @@ -278,79 +278,73 @@ object DIALManager { validateChannel(contentMetadata.get(DIALConstants.CHANNEL).asInstanceOf[String], channelId) validateContentForReserveAndReleaseDialcodes(contentMetadata) validateCountForReservingAndReleasingDialCode(request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]]) - validateContentStatus(contentMetadata) - - val reservedDialCodes = if(contentMetadata.containsKey(DIALConstants.RESERVED_DIALCODES)) ScalaJsonUtils.deserialize[Map[String, Integer]](contentMetadata.get(DIALConstants.RESERVED_DIALCODES).asInstanceOf[String]) else Map.empty[String, Integer] - val updateDialCodes = getUpdateDIALCodes(reservedDialCodes, request, channelId, contentId) - - if(updateDialCodes.size > reservedDialCodes.size) { - val updateReq = getDIALReserveUpdateRequest(req, request, rootNode, updateDialCodes) - DataNode.update(updateReq).map(updatedNode => { - val response = ResponseHandler.OK() - val updatedSuccessResponse = getDIALReserveUpdateResponse(response, updateDialCodes.size.asInstanceOf[Integer], contentId, updatedNode) - updatedSuccessResponse.getResult.put(DIALConstants.VERSION_KEY, updatedNode.getMetadata.get(DIALConstants.VERSION_KEY)) - updatedSuccessResponse - }) - } else { - val errorResponse = ResponseHandler.ERROR(ResponseCode.CLIENT_ERROR, DIALErrors.ERR_INVALID_COUNT, DIALErrors.ERR_DIAL_INVALID_COUNT_RESPONSE) - val updatedErrorResponse = getDIALReserveUpdateResponse(errorResponse, reservedDialCodes.size.asInstanceOf[Integer], contentId, rootNode) - Future(updatedErrorResponse) - } + + if(operation.nonEmpty && operation.equalsIgnoreCase(ContentConstants.RESERVE)) { + reserve(request, channelId, contentId, rootNode, contentMetadata) + } else if(operation.nonEmpty && operation.equalsIgnoreCase(ContentConstants.RELEASE)) { + release(request, contentId, rootNode, contentMetadata) + } else throw new ClientException(DIALErrors.ERR_INVALID_OPERATION, DIALErrors.ERR_INVALID_OPERATION_MSG) + }) } - def release(request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { - val channelId: String = request.getContext.getOrDefault(DIALConstants.CHANNEL, "").asInstanceOf[String] - val contentId: String = request.get(ContentConstants.IDENTIFIER).asInstanceOf[String] + def reserve(request: Request, channelId: String, contentId: String, rootNode: Node, contentMetadata: util.Map[String, AnyRef])(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { + validateContentStatus(contentMetadata) - if (contentId == null || contentId.isEmpty) throw new ClientException(DIALErrors.ERR_CONTENT_BLANK_OBJECT_ID, DIALErrors.ERR_CONTENT_BLANK_OBJECT_ID_MSG) + val reservedDialCodes = if(contentMetadata.containsKey(DIALConstants.RESERVED_DIALCODES)) ScalaJsonUtils.deserialize[Map[String, Integer]](contentMetadata.get(DIALConstants.RESERVED_DIALCODES).asInstanceOf[String]) else Map.empty[String, Integer] + val updateDialCodes = getUpdateDIALCodes(reservedDialCodes, request, channelId, contentId) - val req = new Request() - req.setContext(request.getContext) - req.put(DIALConstants.IDENTIFIER, contentId) - req.put(ContentConstants.ROOT_ID, contentId) - req.put(ContentConstants.MODE, ContentConstants.EDIT_MODE) - DataNode.read(req).flatMap(rootNode => { - val contentMetadata = rootNode.getMetadata - - validateChannel(contentMetadata.get(DIALConstants.CHANNEL).asInstanceOf[String], channelId) - validateContentForReserveAndReleaseDialcodes(contentMetadata) - validateCountForReservingAndReleasingDialCode(request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]]) + if(updateDialCodes.size > reservedDialCodes.size) { + val updateReq = getDIALReserveUpdateRequest(request, rootNode, updateDialCodes) + DataNode.update(updateReq).map(updatedNode => { + val response = ResponseHandler.OK() + val updatedSuccessResponse = getDIALReserveUpdateResponse(response, updateDialCodes.size.asInstanceOf[Integer], contentId, updatedNode) + updatedSuccessResponse.getResult.put(DIALConstants.VERSION_KEY, updatedNode.getMetadata.get(DIALConstants.VERSION_KEY)) + updatedSuccessResponse + }) + } else { + val errorResponse = ResponseHandler.ERROR(ResponseCode.CLIENT_ERROR, DIALErrors.ERR_INVALID_COUNT, DIALErrors.ERR_DIAL_INVALID_COUNT_RESPONSE) + val updatedErrorResponse = getDIALReserveUpdateResponse(errorResponse, reservedDialCodes.size.asInstanceOf[Integer], contentId, rootNode) + Future(updatedErrorResponse) + } + } - val reservedDialCodes = if(contentMetadata.containsKey(DIALConstants.RESERVED_DIALCODES)) ScalaJsonUtils.deserialize[Map[String, Integer]](contentMetadata.get(DIALConstants.RESERVED_DIALCODES).asInstanceOf[String]) - else throw new ClientException(DIALErrors.ERR_CONTENT_MISSING_RESERVED_DIAL_CODES, DIALErrors.ERR_CONTENT_MISSING_RESERVED_DIAL_CODES_MSG) + def release(request: Request, contentId: String, rootNode: Node, contentMetadata: util.Map[String, AnyRef])(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[Response] = { + val reservedDialCodes = if(contentMetadata.containsKey(DIALConstants.RESERVED_DIALCODES)) ScalaJsonUtils.deserialize[Map[String, Integer]](contentMetadata.get(DIALConstants.RESERVED_DIALCODES).asInstanceOf[String]) + else throw new ClientException(DIALErrors.ERR_CONTENT_MISSING_RESERVED_DIAL_CODES, DIALErrors.ERR_CONTENT_MISSING_RESERVED_DIAL_CODES_MSG) - populateAssignedDialCodes(contentId, contentMetadata, req).map(assignedDialCodes => { - val toReleaseDIALCodes = reservedDialCodes.keySet -- assignedDialCodes.toSet + populateAssignedDialCodes(contentId, contentMetadata, request).map(assignedDialCodes => { + val toReleaseDIALCodes = reservedDialCodes.keySet -- assignedDialCodes.toSet - if(toReleaseDIALCodes.isEmpty) throw new ClientException(DIALErrors.ERR_ALL_DIALCODES_UTILIZED, DIALErrors.ERR_ALL_DIALCODES_UTILIZED_MSG) + if(toReleaseDIALCodes.isEmpty) throw new ClientException(DIALErrors.ERR_ALL_DIALCODES_UTILIZED, DIALErrors.ERR_ALL_DIALCODES_UTILIZED_MSG) - val reqDialcodesCount = request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]].get(DIALConstants.COUNT).asInstanceOf[Integer] + val reqDialcodesCount = request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]].get(DIALConstants.COUNT).asInstanceOf[Integer] - val updatedReleaseDialcodes = if (toReleaseDIALCodes.size > reqDialcodesCount) { - toReleaseDIALCodes.take(reqDialcodesCount) - } else toReleaseDIALCodes + val updatedReleaseDialcodes = if (toReleaseDIALCodes.size > reqDialcodesCount) { + toReleaseDIALCodes.take(reqDialcodesCount) + } else toReleaseDIALCodes - val updatedReserveDialCodes = reservedDialCodes.filter(rec => !updatedReleaseDialcodes.contains(rec._1)).keySet.zipWithIndex.map { case (dialCode, idx) => - (dialCode -> idx.asInstanceOf[Integer]) - }.toMap + val updatedReserveDialCodes = reservedDialCodes.filter(rec => !updatedReleaseDialcodes.contains(rec._1)).keySet.zipWithIndex.map { case (dialCode, idx) => + (dialCode -> idx.asInstanceOf[Integer]) + }.toMap - val updateReq = new Request() - updateReq.setContext(request.getContext) - updateReq.getContext.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) - updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) - updateReq.put(DIALConstants.VERSION_KEY,rootNode.getMetadata.get(ContentConstants.VERSION_KEY)) - updateReq.put(DIALConstants.RESERVED_DIALCODES, if(updatedReserveDialCodes.nonEmpty) updatedReserveDialCodes.asJava else null) - DataNode.update(updateReq).map(node => { - ResponseHandler.OK.putAll(Map(ContentConstants.IDENTIFIER -> node.getIdentifier.replace(ContentConstants.IMAGE_SUFFIX, ""), - ContentConstants.VERSION_KEY -> node.getMetadata.get(ContentConstants.VERSION_KEY), - DIALConstants.RESERVED_DIALCODES -> node.getMetadata.get(DIALConstants.RESERVED_DIALCODES)).asJava) - }) - }).flatMap(f=>f) - }) + val updateReq = new Request() + updateReq.setContext(request.getContext) + updateReq.getContext.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) + updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) + updateReq.put(DIALConstants.VERSION_KEY,rootNode.getMetadata.get(ContentConstants.VERSION_KEY)) + updateReq.put(DIALConstants.RESERVED_DIALCODES, if(updatedReserveDialCodes.nonEmpty) updatedReserveDialCodes.asJava else null) + DataNode.update(updateReq).map(node => { + ResponseHandler.OK.putAll(Map(ContentConstants.IDENTIFIER -> node.getIdentifier.replace(ContentConstants.IMAGE_SUFFIX, ""), + ContentConstants.VERSION_KEY -> node.getMetadata.get(ContentConstants.VERSION_KEY), + DIALConstants.RESERVED_DIALCODES -> node.getMetadata.get(DIALConstants.RESERVED_DIALCODES)).asJava) + }) + }).flatMap(f=>f) } - def populateAssignedDialCodes(contentId: String, contentMetadata: util.Map[String, AnyRef], request: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[List[String]] = { + def populateAssignedDialCodes(contentId: String, contentMetadata: util.Map[String, AnyRef], req: Request)(implicit oec: OntologyEngineContext, ec: ExecutionContext): Future[List[String]] = { + val request = new Request() + request.setContext(req.getContext) request.getContext.put(ContentConstants.SCHEMA_NAME, ContentConstants.COLLECTION_SCHEMA_NAME) request.getContext.put(ContentConstants.VERSION, ContentConstants.SCHEMA_VERSION) request.put(ContentConstants.ROOT_ID, contentMetadata.getOrDefault(ContentConstants.IDENTIFIER,"").asInstanceOf[String]) @@ -462,9 +456,9 @@ object DIALManager { } } - def getDIALReserveUpdateRequest(req: Request, request: Request, rootNode: Node, updateDialCodes: Map[String, Integer]): Request = { - val updateReq = new Request(req) - updateReq.setContext(request.getContext) + def getDIALReserveUpdateRequest(req: Request, rootNode: Node, updateDialCodes: Map[String, Integer]): Request = { + val updateReq = new Request() + updateReq.setContext(req.getContext) updateReq.getContext.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) updateReq.put(ContentConstants.IDENTIFIER, rootNode.getIdentifier) updateReq.put(DIALConstants.VERSION_KEY,rootNode.getMetadata.get("versionKey")) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala index ffc31a8d2..aa199a481 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala @@ -75,4 +75,6 @@ object ContentConstants { val ENV: String = "env" val KAFKA_PUBLISH_TOPIC: String = "kafka.publish.request.topic" val PROCESSING: String = "Processing" + val RESERVE: String = "reserve" + val RELEASE: String = "release" } diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index c17f31cf0..cbc801156 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -280,7 +280,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory val request = getReserveDIALRequest(contentId) - val response = DIALManager.reserve(request) + val response = DIALManager.reserveOrRelease(request, "reserve") response.map(result => { assert(result.getResponseCode.toString=="OK") }) @@ -300,7 +300,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory val request = getReleaseDIALRequest(contentId) - val response = DIALManager.release(request) + val response = DIALManager.reserveOrRelease(request, "release") response.map(result => { assert(result.getResponseCode.toString=="OK") }) From f0c762b2ef2c9876788459f3bcdcaae685f30e56 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 7 Sep 2022 12:17:17 +0530 Subject: [PATCH 085/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../test/controllers/v4/CollectionSpec.scala | 23 +++++++++++++++++++ .../test/controllers/v4/ContentSpec.scala | 22 ++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/content-api/content-service/test/controllers/v4/CollectionSpec.scala b/content-api/content-service/test/controllers/v4/CollectionSpec.scala index ae90503db..ec0f38969 100644 --- a/content-api/content-service/test/controllers/v4/CollectionSpec.scala +++ b/content-api/content-service/test/controllers/v4/CollectionSpec.scala @@ -167,4 +167,27 @@ class CollectionSpec extends BaseSpec { status(result) must equalTo(OK) } } + + "Collection Controller with valid request " should { + "return success response for dialcode reserve API" in { + val controller = app.injector.instanceOf[controllers.v4.CollectionController] + val json: JsValue = Json.parse("""{"request": {"dialcodes": {"count": 5, "qrCodeSpec": { "errorCorrectionLevel": "H" }}}}""".stripMargin) + val fakeRequest = FakeRequest("POST", "/collection/v4/dialcode/reserve/do_123").withJsonBody(json) + val result = controller.reserveDialCode("do_123")(fakeRequest) + isOK(result) + status(result) must equalTo(OK) + } + } + + "Collection Controller with valid request " should { + "return success response for dialcode release API" in { + val controller = app.injector.instanceOf[controllers.v4.CollectionController] + val json: JsValue = Json.parse("""{"request": {"dialcodes": {"count": 1}}}""".stripMargin) + val fakeRequest = FakeRequest("POST", "/collection/v4/dialcode/release/do_123").withJsonBody(json) + val result = controller.releaseDialCode("do_123")(fakeRequest) + isOK(result) + status(result) must equalTo(OK) + } + } + } diff --git a/content-api/content-service/test/controllers/v4/ContentSpec.scala b/content-api/content-service/test/controllers/v4/ContentSpec.scala index aeb8e6238..b3bec6705 100644 --- a/content-api/content-service/test/controllers/v4/ContentSpec.scala +++ b/content-api/content-service/test/controllers/v4/ContentSpec.scala @@ -191,4 +191,26 @@ class ContentSpec extends BaseSpec { } } + "Content Controller with valid request " should { + "return success response for dialcode reserve API" in { + val controller = app.injector.instanceOf[controllers.v4.CollectionController] + val json: JsValue = Json.parse("""{"request": {"dialcodes": {"count": 5, "qrCodeSpec": { "errorCorrectionLevel": "H" }}}}""".stripMargin) + val fakeRequest = FakeRequest("POST", "/collection/v4/dialcode/reserve/do_123").withJsonBody(json) + val result = controller.reserveDialCode("do_123")(fakeRequest) + isOK(result) + status(result) must equalTo(OK) + } + } + + "Content Controller with valid request " should { + "return success response for dialcode release API" in { + val controller = app.injector.instanceOf[controllers.v4.CollectionController] + val json: JsValue = Json.parse("""{"request": {"dialcodes": {"count": 1}}}""".stripMargin) + val fakeRequest = FakeRequest("POST", "/collection/v4/dialcode/release/do_123").withJsonBody(json) + val result = controller.releaseDialCode("do_123")(fakeRequest) + isOK(result) + status(result) must equalTo(OK) + } + } + } From b7d1722a3e5428996de8ddd4ff93cfeac5d8672b Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 7 Sep 2022 17:09:58 +0530 Subject: [PATCH 086/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../src/main/scala/org/sunbird/content/dial/DIALErrors.scala | 2 ++ .../src/main/scala/org/sunbird/content/dial/DIALManager.scala | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala index bb7622e91..c96e00f5e 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALErrors.scala @@ -17,6 +17,7 @@ object DIALErrors { val ERR_CONTENT_MISSING_RESERVED_DIAL_CODES: String = "ERR_CONTENT_MISSING_RESERVED_DIAL_CODES" val ERR_ALL_DIALCODES_UTILIZED: String = "ERR_ALL_DIALCODES_UTILIZED" val ERR_INVALID_OPERATION: String = "ERR_INVALID_OPERATION" + val ERR_COUNT_GREATER_THAN_RESERVED_DIAL_CODES: String = "ERR_COUNT_GREATER_THAN_RESERVED_DIAL_CODES" //Error Messages val ERR_INVALID_REQ_MSG: String = "Invalid Request! Please Provide Valid Request." @@ -40,4 +41,5 @@ object DIALErrors { val ERR_CONTENT_MISSING_RESERVED_DIAL_CODES_MSG: String = "Invalid Request. Content does not have reserved DIAL codes." val ERR_ALL_DIALCODES_UTILIZED_MSG: String = "Error! All Reserved DIAL Codes are Utilized." val ERR_INVALID_OPERATION_MSG: String = "Invalid operation request!" + val ERR_COUNT_GREATER_THAN_RESERVED_DIAL_CODES_MSG: String = "Invalid Request. Count greater than reserved DIAL codes." } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 755ebfb56..7a53b456e 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -313,6 +313,10 @@ object DIALManager { val reservedDialCodes = if(contentMetadata.containsKey(DIALConstants.RESERVED_DIALCODES)) ScalaJsonUtils.deserialize[Map[String, Integer]](contentMetadata.get(DIALConstants.RESERVED_DIALCODES).asInstanceOf[String]) else throw new ClientException(DIALErrors.ERR_CONTENT_MISSING_RESERVED_DIAL_CODES, DIALErrors.ERR_CONTENT_MISSING_RESERVED_DIAL_CODES_MSG) + val countInRequest = request.get(DIALConstants.COUNT).asInstanceOf[Integer] + if(reservedDialCodes.keySet.size < countInRequest) + throw new ClientException(DIALErrors.ERR_COUNT_GREATER_THAN_RESERVED_DIAL_CODES, DIALErrors.ERR_COUNT_GREATER_THAN_RESERVED_DIAL_CODES_MSG) + populateAssignedDialCodes(contentId, contentMetadata, request).map(assignedDialCodes => { val toReleaseDIALCodes = reservedDialCodes.keySet -- assignedDialCodes.toSet From fc492fbfd4a86ae4845a1d970cfd595a786860a4 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 7 Sep 2022 17:25:18 +0530 Subject: [PATCH 087/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../scala/org/sunbird/content/dial/DIALManager.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 7a53b456e..61bfee6b2 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -313,8 +313,8 @@ object DIALManager { val reservedDialCodes = if(contentMetadata.containsKey(DIALConstants.RESERVED_DIALCODES)) ScalaJsonUtils.deserialize[Map[String, Integer]](contentMetadata.get(DIALConstants.RESERVED_DIALCODES).asInstanceOf[String]) else throw new ClientException(DIALErrors.ERR_CONTENT_MISSING_RESERVED_DIAL_CODES, DIALErrors.ERR_CONTENT_MISSING_RESERVED_DIAL_CODES_MSG) - val countInRequest = request.get(DIALConstants.COUNT).asInstanceOf[Integer] - if(reservedDialCodes.keySet.size < countInRequest) + val countInRequest = request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]].get(DIALConstants.COUNT).asInstanceOf[Integer] + if(reservedDialCodes.keys.size < countInRequest) throw new ClientException(DIALErrors.ERR_COUNT_GREATER_THAN_RESERVED_DIAL_CODES, DIALErrors.ERR_COUNT_GREATER_THAN_RESERVED_DIAL_CODES_MSG) populateAssignedDialCodes(contentId, contentMetadata, request).map(assignedDialCodes => { @@ -407,9 +407,9 @@ object DIALManager { throw new ClientException(DIALErrors.ERR_CONTENT_RETIRED_OBJECT_ID, DIALErrors.ERR_CONTENT_RETIRED_OBJECT_ID_MSG) } - def validateCountForReservingAndReleasingDialCode(request: util.Map[String, AnyRef]): Unit = { - if (null == request.get(DIALConstants.COUNT) || !request.get(DIALConstants.COUNT).isInstanceOf[Integer]) throw new ClientException(DIALErrors.ERR_INVALID_COUNT, DIALErrors.ERR_INVALID_COUNT_MSG) - val count = request.get(DIALConstants.COUNT).asInstanceOf[Integer] + def validateCountForReservingAndReleasingDialCode(requestDIALCodesMap: util.Map[String, AnyRef]): Unit = { + if (null == requestDIALCodesMap.get(DIALConstants.COUNT) || !requestDIALCodesMap.get(DIALConstants.COUNT).isInstanceOf[Integer]) throw new ClientException(DIALErrors.ERR_INVALID_COUNT, DIALErrors.ERR_INVALID_COUNT_MSG) + val count = requestDIALCodesMap.get(DIALConstants.COUNT).asInstanceOf[Integer] val maxCount = if (Platform.config.hasPath("reserve_dialcode.max_count")) Platform.config.getInt("reserve_dialcode.max_count") else 250 if (count < 1 || count > maxCount) throw new ClientException(DIALErrors.ERR_INVALID_COUNT_RANGE, DIALErrors.ERR_INVALID_COUNT_RANGE_MSG + maxCount + ".") } From 3a278b8348ef63debd484e88e3b5f50ddcb4d284 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 7 Sep 2022 17:30:47 +0530 Subject: [PATCH 088/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- ...ease DIAL Code API.postman_collection.json | 907 ++++++++++++++++++ ...elease DIAL Code API.postman_test_run.json | 488 ++++++++++ 2 files changed, 1395 insertions(+) create mode 100644 content-api/api-tests/Collections/Release DIAL Code API.postman_collection.json create mode 100644 content-api/api-tests/Reports/Release DIAL Code API.postman_test_run.json diff --git a/content-api/api-tests/Collections/Release DIAL Code API.postman_collection.json b/content-api/api-tests/Collections/Release DIAL Code API.postman_collection.json new file mode 100644 index 000000000..2e825716c --- /dev/null +++ b/content-api/api-tests/Collections/Release DIAL Code API.postman_collection.json @@ -0,0 +1,907 @@ +{ + "info": { + "_postman_id": "d76732b8-56b7-4a54-84f1-4c43e694dcd9", + "name": "Release DIAL Code API", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Pre-requisite", + "item": [ + { + "name": "Collection Create", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.environment.set(\"collection_id\", jsonResponse.result.identifier);", + "pm.globals.set(\"versionKey\", jsonResponse.result.versionKey);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Sample Collection\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.content-collection\",\n \"primaryCategory\": \"Digital Textbook\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [] + }, + { + "name": "Collection Create wo reserved DIAL codes", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "let jsonResponse = pm.response.json()", + "", + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "// Set global variable", + "pm.environment.set(\"collection_id_wo_reserved_dial_codes\", jsonResponse.result.identifier);", + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disabledSystemHeaders": {} + }, + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "The Content Type entity is the media type of the resource.Possible media types can be application/json." + }, + { + "key": "X-Authenticated-User-token", + "value": "{{keycloak_access_token}}", + "description": "Represents the authorized User ID to execute the API." + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}", + "description": "To make use of the API, you require authorization. Raise a request to the administrator for the use of the API. You will receive the authorization key. Specify the key received, here." + }, + { + "key": "X-Channel-Id", + "value": "{{channel_id}}", + "type": "text", + "description": "Represents a physical location (e.g: state) uniquely to which the user belongs." + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": {\n \"name\": \"Sample Collection\",\n \"code\": \"1242e9ea-660a-4536-a142-cc242a7a4162\",\n \"mimeType\": \"application/vnd.ekstep.content-collection\",\n \"primaryCategory\": \"Digital Textbook\"\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/content/v4/create", + "host": [ + "{{host}}" + ], + "path": [ + "content", + "v4", + "create" + ] + }, + "description": "This API is associated with creating content on the Sunbird Platform. Mandatory fields (name, code, mimeType and primaryCategory) cannot be null or empty.\n\nThe body refers to the format of the request.\n\n* The body contains metadata about the content to be updated.\n* Please refer for supported [metadata](https://github.com/project-sunbird/knowledge-platform/blob/master/schemas/content/1.0/schema.json)" + }, + "response": [] + }, + { + "name": "TOC Upload", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "//Verification", + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200)", + "});", + "", + "const responseJson = pm.response.json();", + "const unitIdentifiers = _.values(responseJson.result.identifiers)", + "", + "pm.globals.set(\"unitA\", unitIdentifiers[_.size(unitIdentifiers) - 2]);", + "pm.globals.set(\"unitB\", unitIdentifiers[_.size(unitIdentifiers) - 3]);", + "pm.globals.set(\"unitC\", unitIdentifiers[_.size(unitIdentifiers) - 4]);", + "console.log(pm.globals.get(\"unitA\") + \", \" + pm.globals.get(\"unitB\") + \", \" + pm.globals.get(\"unitC\"))", + "", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "x-authenticated-user-token", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "fileUrl", + "value": "https://sunbirddev.blob.core.windows.net/sunbird-content-dev/content/hierarchy/do_113316820811522048194/createtoc.csv", + "type": "text" + } + ] + }, + "url": { + "raw": "{{host}}/collection/v4/import/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "import", + "{{collection_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Reserve DIAL code", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "const responseJson = pm.response.json();", + "", + "var reservedDialcodesObj = JSON.parse(responseJson.result.reservedDialcodes);", + "const reservedDialCodesList = _.keys(reservedDialcodesObj)", + "", + "pm.globals.set(\"originalReservedDIALCodes\", reservedDialCodesList)", + "pm.globals.set(\"dialcodeA\", reservedDialCodesList[_.size(reservedDialCodesList) - 2]);", + "pm.globals.set(\"dialcodeB\", reservedDialCodesList[_.size(reservedDialCodesList) - 3]);", + "pm.globals.set(\"dialcodeC\", reservedDialCodesList[_.size(reservedDialCodesList) - 4]);", + "", + "console.log(pm.globals.get(\"dialcodeA\") + \", \" + pm.globals.get(\"dialcodeB\") + \", \" + pm.globals.get(\"dialcodeC\"))" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "pm.globals.set(\"ReservedDialCodesCount\", 8);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": {{ReservedDialCodesCount}},\n \"qrCodeSpec\": {\n \"errorCorrectionLevel\": \"H\"\n }\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/dialcode/reserve/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "dialcode", + "reserve", + "{{collection_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Link DIAL code", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "setTimeout(function(){}, 1000);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "x-authenticated-user-token", + "value": "{{keycloak_access_token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"content\": [{\n \"identifier\": [\"{{unitA}}\"],\n \"dialcode\": [\"{{dialcodeA}}\"]\n },\n {\n \"identifier\": [\"{{unitB}}\"],\n \"dialcode\": [\"{{dialcodeB}}\"]\n },\n {\n \"identifier\": [\"{{unitC}}\"],\n \"dialcode\": [\"{{dialcodeC}}\"]\n }]\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/dialcode/link/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "dialcode", + "link", + "{{collection_id}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Positive", + "item": [ + { + "name": "Release DIAL code", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Response returns with reservedDialcodes with one less\", function () {", + " const responseJson = pm.response.json();", + " ", + " var reservedDialcodesObj = JSON.parse(responseJson.result.reservedDialcodes);", + " const reservedDialCodesList = _.keys(reservedDialcodesObj)", + " var expectedCount = pm.globals.get(\"ReservedDialCodesCount\")-1", + " console.log(\"expected Count:: \" + expectedCount)", + " console.log(\"returned Count:: \" + _.size(reservedDialCodesList))", + " pm.expect(_.size(reservedDialCodesList) == expectedCount)", + "", + " var orgReservedDIALList = pm.globals.get(\"originalReservedDIALCodes\")", + " var releasedDialcode = _.difference(orgReservedDIALList, reservedDialCodesList)", + " console.log(\"releasedDialcode:: \" + releasedDialcode)", + "", + " pm.expect((releasedDialcode != pm.globals.get(\"dialcodeA\")) && ", + " (releasedDialcode != pm.globals.get(\"dialcodeB\")) && ", + " (releasedDialcode != pm.globals.get(\"dialcodeC\")))", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 5\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/dialcode/release/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "dialcode", + "release", + "{{collection_id}}" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Negative", + "item": [ + { + "name": "Release DIAL code Invalid Channel Id header", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws ERR_INVALID_CHANNEL\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_INVALID_CHANNEL\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "dummy" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 1\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/dialcode/release/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "dialcode", + "release", + "{{collection_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Release DIAL code with Zero count", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws ERR_INVALID_COUNT_RANGE\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_INVALID_COUNT_RANGE\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 0\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/dialcode/release/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "dialcode", + "release", + "{{collection_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Release DIAL code with negative count", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws ERR_INVALID_COUNT_RANGE\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_INVALID_COUNT_RANGE\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": -2\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/dialcode/release/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "dialcode", + "release", + "{{collection_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Release DIAL code with count greater than max limit(250)", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws ERR_INVALID_COUNT_RANGE\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_INVALID_COUNT_RANGE\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 251\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/dialcode/release/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "dialcode", + "release", + "{{collection_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Release DIAL code with invalid collection Id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 404\", function () {", + " pm.response.to.have.status(404);", + "});", + "", + "pm.test(\"Response throws RESOURCE_NOT_FOUND\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"RESOURCE_NOT_FOUND\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"NOT_FOUND\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 25\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/dialcode/release/do_dummy_id", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "dialcode", + "release", + "do_dummy_id" + ] + } + }, + "response": [] + }, + { + "name": "Release DIAL code for collection wo reserved DIAL codes", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws ERR_CONTENT_MISSING_RESERVED_DIAL_CODES\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_CONTENT_MISSING_RESERVED_DIAL_CODES\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 2\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/dialcode/release/{{collection_id_wo_reserved_dial_codes}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "dialcode", + "release", + "{{collection_id_wo_reserved_dial_codes}}" + ] + } + }, + "response": [] + }, + { + "name": "Release DIAL code with count greater than reserved DIAL codes count", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws ERR_COUNT_GREATER_THAN_RESERVED_DIAL_CODES\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_COUNT_GREATER_THAN_RESERVED_DIAL_CODES\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 25\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/dialcode/release/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "dialcode", + "release", + "{{collection_id}}" + ] + } + }, + "response": [] + }, + { + "name": "Release DIAL code with count same as linked DIAL codes", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "", + "pm.test(\"Response throws ERR_ALL_DIALCODES_UTILIZED\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.responseCode).equals(\"CLIENT_ERROR\")", + " ", + " const params = responseJson.params;", + " pm.expect(params.status).equals(\"failed\")", + " pm.expect(params.err).equals(\"ERR_ALL_DIALCODES_UTILIZED\") ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{kong_api_key}}" + }, + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "X-Channel-ID", + "value": "{{channel_id}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"request\": {\n \"dialcodes\": {\n \"count\": 2\n }\n }\n}" + }, + "url": { + "raw": "{{host}}/collection/v4/dialcode/release/{{collection_id}}", + "host": [ + "{{host}}" + ], + "path": [ + "collection", + "v4", + "dialcode", + "release", + "{{collection_id}}" + ] + } + }, + "response": [] + } + ] + } + ] +} \ No newline at end of file diff --git a/content-api/api-tests/Reports/Release DIAL Code API.postman_test_run.json b/content-api/api-tests/Reports/Release DIAL Code API.postman_test_run.json new file mode 100644 index 000000000..0595d0940 --- /dev/null +++ b/content-api/api-tests/Reports/Release DIAL Code API.postman_test_run.json @@ -0,0 +1,488 @@ +{ + "id": "0f65eca4-84c1-4ad3-9ca7-4c0c035fe6a1", + "name": "Release DIAL Code API", + "timestamp": "2022-09-07T11:58:49.914Z", + "collection_id": "13387833-d76732b8-56b7-4a54-84f1-4c43e694dcd9", + "folder_id": 0, + "environment_id": "0e0b136d-70cc-437e-a0df-ccba162408d9", + "totalPass": 21, + "totalFail": 0, + "results": [ + { + "id": "32d3736c-e0f7-4d97-9230-4a4c8d8a80eb", + "name": "Collection Create", + "url": "http://localhost:9000/content/v4/create", + "time": 49, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Status code is 200": true + }, + "testPassFailCounts": { + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 49 + ], + "allTests": [ + { + "Status code is 200": true + } + ] + }, + { + "id": "ce3e135b-72fc-4561-badc-5094ecab1ab2", + "name": "Collection Create wo reserved DIAL codes", + "url": "http://localhost:9000/content/v4/create", + "time": 28, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Status code is 200": true + }, + "testPassFailCounts": { + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 28 + ], + "allTests": [ + { + "Status code is 200": true + } + ] + }, + { + "id": "1f0520aa-3f59-4c3e-be73-2574ea09a123", + "name": "TOC Upload", + "url": "http://localhost:9000/collection/v4/import/do_113619625412968448149", + "time": 533, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Status code is 200": true + }, + "testPassFailCounts": { + "Status code is 200": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 533 + ], + "allTests": [ + { + "Status code is 200": true + } + ] + }, + { + "id": "c7ebfb77-7f9e-483b-afd6-4b6b44067e8b", + "name": "Reserve DIAL code", + "url": "http://localhost:9000/collection/v4/dialcode/reserve/do_113619625412968448149", + "time": 1702, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": {}, + "testPassFailCounts": {}, + "times": [ + 1702 + ], + "allTests": [ + {} + ] + }, + { + "id": "5a0c02b8-ab74-4d12-9ce3-06ba874311b9", + "name": "Link DIAL code", + "url": "http://localhost:9000/collection/v4/dialcode/link/do_113619625412968448149", + "time": 199, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": {}, + "testPassFailCounts": {}, + "times": [ + 199 + ], + "allTests": [ + {} + ] + }, + { + "id": "48eaac17-ecf6-45e2-ad72-b95ef26d9e55", + "name": "Release DIAL code", + "url": "http://localhost:9000/collection/v4/dialcode/release/do_113619625412968448149", + "time": 101, + "responseCode": { + "code": 200, + "name": "OK" + }, + "tests": { + "Status code is 200": true, + "Response returns with reservedDialcodes with one less": true + }, + "testPassFailCounts": { + "Status code is 200": { + "pass": 1, + "fail": 0 + }, + "Response returns with reservedDialcodes with one less": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 101 + ], + "allTests": [ + { + "Status code is 200": true, + "Response returns with reservedDialcodes with one less": true + } + ] + }, + { + "id": "cec90850-4020-4b24-a4f3-76b2c52b9da6", + "name": "Release DIAL code Invalid Channel Id header", + "url": "http://localhost:9000/collection/v4/dialcode/release/do_113619625412968448149", + "time": 24, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Status code is 400": true, + "Response throws ERR_INVALID_CHANNEL": true + }, + "testPassFailCounts": { + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws ERR_INVALID_CHANNEL": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 24 + ], + "allTests": [ + { + "Status code is 400": true, + "Response throws ERR_INVALID_CHANNEL": true + } + ] + }, + { + "id": "60202782-e345-4c4c-8f1e-939cd7ee8f0b", + "name": "Release DIAL code with Zero count", + "url": "http://localhost:9000/collection/v4/dialcode/release/do_113619625412968448149", + "time": 30, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Status code is 400": true, + "Response throws ERR_INVALID_COUNT_RANGE": true + }, + "testPassFailCounts": { + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws ERR_INVALID_COUNT_RANGE": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 30 + ], + "allTests": [ + { + "Status code is 400": true, + "Response throws ERR_INVALID_COUNT_RANGE": true + } + ] + }, + { + "id": "28f49920-9a42-441b-90b6-34260a2cd834", + "name": "Release DIAL code with negative count", + "url": "http://localhost:9000/collection/v4/dialcode/release/do_113619625412968448149", + "time": 31, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Status code is 400": true, + "Response throws ERR_INVALID_COUNT_RANGE": true + }, + "testPassFailCounts": { + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws ERR_INVALID_COUNT_RANGE": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 31 + ], + "allTests": [ + { + "Status code is 400": true, + "Response throws ERR_INVALID_COUNT_RANGE": true + } + ] + }, + { + "id": "b0dd02cf-d5b8-44bb-acd7-367bdc5f9592", + "name": "Release DIAL code with count greater than max limit(250)", + "url": "http://localhost:9000/collection/v4/dialcode/release/do_113619625412968448149", + "time": 35, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Status code is 400": true, + "Response throws ERR_INVALID_COUNT_RANGE": true + }, + "testPassFailCounts": { + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws ERR_INVALID_COUNT_RANGE": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 35 + ], + "allTests": [ + { + "Status code is 400": true, + "Response throws ERR_INVALID_COUNT_RANGE": true + } + ] + }, + { + "id": "208caab7-3f00-47ab-ae97-838e9b4815b4", + "name": "Release DIAL code with invalid collection Id", + "url": "http://localhost:9000/collection/v4/dialcode/release/do_dummy_id", + "time": 35, + "responseCode": { + "code": 404, + "name": "Not Found" + }, + "tests": { + "Status code is 404": true, + "Response throws RESOURCE_NOT_FOUND": true + }, + "testPassFailCounts": { + "Status code is 404": { + "pass": 1, + "fail": 0 + }, + "Response throws RESOURCE_NOT_FOUND": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 35 + ], + "allTests": [ + { + "Status code is 404": true, + "Response throws RESOURCE_NOT_FOUND": true + } + ] + }, + { + "id": "9a169a58-785e-468e-b8fe-014b0d3898d9", + "name": "Release DIAL code for collection wo reserved DIAL codes", + "url": "http://localhost:9000/collection/v4/dialcode/release/do_113619625413853184150", + "time": 55, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Status code is 400": true, + "Response throws ERR_CONTENT_MISSING_RESERVED_DIAL_CODES": true + }, + "testPassFailCounts": { + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws ERR_CONTENT_MISSING_RESERVED_DIAL_CODES": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 55 + ], + "allTests": [ + { + "Status code is 400": true, + "Response throws ERR_CONTENT_MISSING_RESERVED_DIAL_CODES": true + } + ] + }, + { + "id": "5d662783-fe26-41db-a2b6-66ed08be9430", + "name": "Release DIAL code with count greater than reserved DIAL codes count", + "url": "http://localhost:9000/collection/v4/dialcode/release/do_113619625412968448149", + "time": 31, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Status code is 400": true, + "Response throws ERR_COUNT_GREATER_THAN_RESERVED_DIAL_CODES": true + }, + "testPassFailCounts": { + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws ERR_COUNT_GREATER_THAN_RESERVED_DIAL_CODES": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 31 + ], + "allTests": [ + { + "Status code is 400": true, + "Response throws ERR_COUNT_GREATER_THAN_RESERVED_DIAL_CODES": true + } + ] + }, + { + "id": "2610536f-2c69-41c1-be92-6df6b4a153dc", + "name": "Release DIAL code with count same as linked DIAL codes", + "url": "http://localhost:9000/collection/v4/dialcode/release/do_113619625412968448149", + "time": 89, + "responseCode": { + "code": 400, + "name": "Bad Request" + }, + "tests": { + "Status code is 400": true, + "Response throws ERR_ALL_DIALCODES_UTILIZED": true + }, + "testPassFailCounts": { + "Status code is 400": { + "pass": 1, + "fail": 0 + }, + "Response throws ERR_ALL_DIALCODES_UTILIZED": { + "pass": 1, + "fail": 0 + } + }, + "times": [ + 89 + ], + "allTests": [ + { + "Status code is 400": true, + "Response throws ERR_ALL_DIALCODES_UTILIZED": true + } + ] + } + ], + "count": 1, + "totalTime": 2942, + "collection": { + "requests": [ + { + "id": "32d3736c-e0f7-4d97-9230-4a4c8d8a80eb", + "method": "POST" + }, + { + "id": "ce3e135b-72fc-4561-badc-5094ecab1ab2", + "method": "POST" + }, + { + "id": "1f0520aa-3f59-4c3e-be73-2574ea09a123", + "method": "POST" + }, + { + "id": "c7ebfb77-7f9e-483b-afd6-4b6b44067e8b", + "method": "POST" + }, + { + "id": "5a0c02b8-ab74-4d12-9ce3-06ba874311b9", + "method": "POST" + }, + { + "id": "48eaac17-ecf6-45e2-ad72-b95ef26d9e55", + "method": "POST" + }, + { + "id": "cec90850-4020-4b24-a4f3-76b2c52b9da6", + "method": "POST" + }, + { + "id": "60202782-e345-4c4c-8f1e-939cd7ee8f0b", + "method": "POST" + }, + { + "id": "28f49920-9a42-441b-90b6-34260a2cd834", + "method": "POST" + }, + { + "id": "b0dd02cf-d5b8-44bb-acd7-367bdc5f9592", + "method": "POST" + }, + { + "id": "208caab7-3f00-47ab-ae97-838e9b4815b4", + "method": "POST" + }, + { + "id": "9a169a58-785e-468e-b8fe-014b0d3898d9", + "method": "POST" + }, + { + "id": "5d662783-fe26-41db-a2b6-66ed08be9430", + "method": "POST" + }, + { + "id": "2610536f-2c69-41c1-be92-6df6b4a153dc", + "method": "POST" + } + ] + } +} \ No newline at end of file From 2821a10f5d697ba4ec46283f7a0e62499a5bb965 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 7 Sep 2022 17:34:25 +0530 Subject: [PATCH 089/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../content-service/test/controllers/v4/ContentSpec.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content-api/content-service/test/controllers/v4/ContentSpec.scala b/content-api/content-service/test/controllers/v4/ContentSpec.scala index b3bec6705..02244b35b 100644 --- a/content-api/content-service/test/controllers/v4/ContentSpec.scala +++ b/content-api/content-service/test/controllers/v4/ContentSpec.scala @@ -195,7 +195,7 @@ class ContentSpec extends BaseSpec { "return success response for dialcode reserve API" in { val controller = app.injector.instanceOf[controllers.v4.CollectionController] val json: JsValue = Json.parse("""{"request": {"dialcodes": {"count": 5, "qrCodeSpec": { "errorCorrectionLevel": "H" }}}}""".stripMargin) - val fakeRequest = FakeRequest("POST", "/collection/v4/dialcode/reserve/do_123").withJsonBody(json) + val fakeRequest = FakeRequest("POST", "/content/v4/dialcode/reserve/do_123").withJsonBody(json) val result = controller.reserveDialCode("do_123")(fakeRequest) isOK(result) status(result) must equalTo(OK) @@ -206,7 +206,7 @@ class ContentSpec extends BaseSpec { "return success response for dialcode release API" in { val controller = app.injector.instanceOf[controllers.v4.CollectionController] val json: JsValue = Json.parse("""{"request": {"dialcodes": {"count": 1}}}""".stripMargin) - val fakeRequest = FakeRequest("POST", "/collection/v4/dialcode/release/do_123").withJsonBody(json) + val fakeRequest = FakeRequest("POST", "/content/v4/dialcode/release/do_123").withJsonBody(json) val result = controller.releaseDialCode("do_123")(fakeRequest) isOK(result) status(result) must equalTo(OK) From f984da3d8f6d0845704a33863362087fc08a60af Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 7 Sep 2022 20:05:21 +0530 Subject: [PATCH 090/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../test/scala/org/sunbird/content/dial/DIALManagerTest.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala index cbc801156..8b54cd6d6 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/dial/DIALManagerTest.scala @@ -627,7 +627,7 @@ class DIALManagerTest extends AsyncFlatSpec with Matchers with AsyncMockFactory request.setContext(getContext()) request.getContext.put("identifier",identifier) request.put("identifier",identifier) - request.putAll(getReserveRequest()) + request.putAll(getReleaseRequest()) request } From 6906a14a2cd438df4d7569d99c0c76a48f969091 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Wed, 7 Sep 2022 20:44:41 +0530 Subject: [PATCH 091/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../content-service/test/controllers/v4/ContentSpec.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content-api/content-service/test/controllers/v4/ContentSpec.scala b/content-api/content-service/test/controllers/v4/ContentSpec.scala index 02244b35b..e69c69181 100644 --- a/content-api/content-service/test/controllers/v4/ContentSpec.scala +++ b/content-api/content-service/test/controllers/v4/ContentSpec.scala @@ -193,7 +193,7 @@ class ContentSpec extends BaseSpec { "Content Controller with valid request " should { "return success response for dialcode reserve API" in { - val controller = app.injector.instanceOf[controllers.v4.CollectionController] + val controller = app.injector.instanceOf[controllers.v4.ContentController] val json: JsValue = Json.parse("""{"request": {"dialcodes": {"count": 5, "qrCodeSpec": { "errorCorrectionLevel": "H" }}}}""".stripMargin) val fakeRequest = FakeRequest("POST", "/content/v4/dialcode/reserve/do_123").withJsonBody(json) val result = controller.reserveDialCode("do_123")(fakeRequest) @@ -204,7 +204,7 @@ class ContentSpec extends BaseSpec { "Content Controller with valid request " should { "return success response for dialcode release API" in { - val controller = app.injector.instanceOf[controllers.v4.CollectionController] + val controller = app.injector.instanceOf[controllers.v4.ContentController] val json: JsValue = Json.parse("""{"request": {"dialcodes": {"count": 1}}}""".stripMargin) val fakeRequest = FakeRequest("POST", "/content/v4/dialcode/release/do_123").withJsonBody(json) val result = controller.releaseDialCode("do_123")(fakeRequest) From 40462ff73136cacd3f3381214886c84b4ae72d45 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 13 Sep 2022 11:28:37 +0530 Subject: [PATCH 092/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../org/sunbird/content/dial/DIALManager.scala | 15 +++++++-------- .../sunbird/content/util/ContentConstants.scala | 1 + content-api/content-service/conf/application.conf | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 61bfee6b2..b5d3eada4 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -279,12 +279,11 @@ object DIALManager { validateContentForReserveAndReleaseDialcodes(contentMetadata) validateCountForReservingAndReleasingDialCode(request.getRequest.get(DIALConstants.DIALCODES).asInstanceOf[util.Map[String, AnyRef]]) - if(operation.nonEmpty && operation.equalsIgnoreCase(ContentConstants.RESERVE)) { - reserve(request, channelId, contentId, rootNode, contentMetadata) - } else if(operation.nonEmpty && operation.equalsIgnoreCase(ContentConstants.RELEASE)) { - release(request, contentId, rootNode, contentMetadata) - } else throw new ClientException(DIALErrors.ERR_INVALID_OPERATION, DIALErrors.ERR_INVALID_OPERATION_MSG) - + operation match { + case ContentConstants.RESERVE => reserve(request, channelId, contentId, rootNode, contentMetadata) + case ContentConstants.RELEASE => release(request, contentId, rootNode, contentMetadata) + case _ => throw new ClientException(DIALErrors.ERR_INVALID_OPERATION, DIALErrors.ERR_INVALID_OPERATION_MSG) + } }) } @@ -403,8 +402,8 @@ object DIALManager { val validMimeType = if (Platform.config.hasPath("reserve_dialcode.mimeType")) Platform.config.getStringList("reserve_dialcode.mimeType") else util.Arrays.asList(ContentConstants.COLLECTION_MIME_TYPE) if (!validMimeType.contains(metaData.get(ContentConstants.MIME_TYPE))) throw new ClientException(DIALErrors.ERR_CONTENT_MIMETYPE, DIALErrors.ERR_CONTENT_MIMETYPE_MSG) - if(metaData.get(ContentConstants.STATUS).asInstanceOf[String].equalsIgnoreCase("Retired")) - throw new ClientException(DIALErrors.ERR_CONTENT_RETIRED_OBJECT_ID, DIALErrors.ERR_CONTENT_RETIRED_OBJECT_ID_MSG) + val validContentStatus = if (Platform.config.hasPath("reserve_dialcode.valid_content_status")) Platform.config.getStringList("reserve_dialcode.valid_content_status") else util.Arrays.asList(ContentConstants.DRAFT) + if(!validContentStatus.contains(metaData.get(ContentConstants.STATUS).asInstanceOf[String])) throw new ClientException(DIALErrors.ERR_CONTENT_RETIRED_OBJECT_ID, DIALErrors.ERR_CONTENT_RETIRED_OBJECT_ID_MSG) } def validateCountForReservingAndReleasingDialCode(requestDIALCodesMap: util.Map[String, AnyRef]): Unit = { diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala index aa199a481..8ae26a27a 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala @@ -77,4 +77,5 @@ object ContentConstants { val PROCESSING: String = "Processing" val RESERVE: String = "reserve" val RELEASE: String = "release" + val DRAFT: String = "Draft" } diff --git a/content-api/content-service/conf/application.conf b/content-api/content-service/conf/application.conf index 910dd9406..5a77be1c5 100644 --- a/content-api/content-service/conf/application.conf +++ b/content-api/content-service/conf/application.conf @@ -612,6 +612,7 @@ dial_service { reserve_dialcode { mimeType = ["application/vnd.ekstep.content-collection"] max_count = 250 + valid_content_status = ["Draft","Live"] } content.link_dialcode.validation=true From 7924fe67e1f3dff40ddf67da08445f3311f74446 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Tue, 13 Sep 2022 11:29:58 +0530 Subject: [PATCH 093/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../src/main/scala/org/sunbird/content/dial/DIALManager.scala | 2 +- .../main/scala/org/sunbird/content/util/ContentConstants.scala | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index b5d3eada4..5bb14c093 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -402,7 +402,7 @@ object DIALManager { val validMimeType = if (Platform.config.hasPath("reserve_dialcode.mimeType")) Platform.config.getStringList("reserve_dialcode.mimeType") else util.Arrays.asList(ContentConstants.COLLECTION_MIME_TYPE) if (!validMimeType.contains(metaData.get(ContentConstants.MIME_TYPE))) throw new ClientException(DIALErrors.ERR_CONTENT_MIMETYPE, DIALErrors.ERR_CONTENT_MIMETYPE_MSG) - val validContentStatus = if (Platform.config.hasPath("reserve_dialcode.valid_content_status")) Platform.config.getStringList("reserve_dialcode.valid_content_status") else util.Arrays.asList(ContentConstants.DRAFT) + val validContentStatus = if (Platform.config.hasPath("reserve_dialcode.valid_content_status")) Platform.config.getStringList("reserve_dialcode.valid_content_status") else util.Arrays.asList(ContentConstants.DRAFT, ContentConstants.LIVE) if(!validContentStatus.contains(metaData.get(ContentConstants.STATUS).asInstanceOf[String])) throw new ClientException(DIALErrors.ERR_CONTENT_RETIRED_OBJECT_ID, DIALErrors.ERR_CONTENT_RETIRED_OBJECT_ID_MSG) } diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala index 8ae26a27a..6ddc98881 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/util/ContentConstants.scala @@ -78,4 +78,5 @@ object ContentConstants { val RESERVE: String = "reserve" val RELEASE: String = "release" val DRAFT: String = "Draft" + val LIVE: String = "Live" } From 8db5754e56693becd7559638ca19c1367a598e64 Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Mon, 19 Sep 2022 10:02:59 +0530 Subject: [PATCH 094/105] Issue #KN-231 test: Improved unit test coverage. --- .../sunbird/content/actors/ContentActor.scala | 3 +- .../content/actors/TestContentActor.scala | 2 +- .../sunbird/cloudstore/StorageService.scala | 67 ++++++++++++++++++- 3 files changed, 68 insertions(+), 4 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala index df9047ff8..fabc95d43 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/actors/ContentActor.scala @@ -144,7 +144,6 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe def uploadPreSignedUrl(request: Request): Future[Response] = { val `type`: String = request.get("type").asInstanceOf[String].toLowerCase() val fileName: String = request.get("fileName").asInstanceOf[String] - val mimeType: String = request.get("mimeType").asInstanceOf[String] val filePath: String = request.getRequest.getOrDefault("filePath","").asInstanceOf[String] .replaceAll("^/+|/+$", "") val identifier: String = request.get("identifier").asInstanceOf[String] @@ -153,7 +152,7 @@ class ContentActor @Inject() (implicit oec: OntologyEngineContext, ss: StorageSe val objectKey = if (StringUtils.isEmpty(filePath)) "content" + File.separator + `type` + File.separator + identifier + File.separator + Slug.makeSlug(fileName, true) else filePath + File.separator + "content" + File.separator + `type` + File.separator + identifier + File.separator + Slug.makeSlug(fileName, true) val expiry = Platform.config.getString("cloud_storage.upload.url.ttl") - val preSignedURL = ss.getSignedURL(objectKey, Option.apply(expiry.toInt), Option.apply("w"), Option.apply(mimeType)) + val preSignedURL = ss.getSignedURL(objectKey, Option.apply(expiry.toInt), Option.apply("w")) ResponseHandler.OK().put("identifier", identifier).put("pre_signed_url", preSignedURL) .put("url_expiry", expiry) }) recoverWith { case e: CompletionException => throw e.getCause } diff --git a/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala b/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala index 52b413a43..5c15e56d2 100644 --- a/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala +++ b/content-api/content-actors/src/test/scala/org/sunbird/content/actors/TestContentActor.scala @@ -94,7 +94,7 @@ class TestContentActor extends BaseSpec with MockFactory { (oec.graphService _).expects().returns(graphDB) (graphDB.getNodeByUniqueId(_: String, _: String, _: Boolean, _: Request)).expects(*, *, *, *).returns(Future(getValidNode())) implicit val ss: StorageService = mock[StorageService] - (ss.getSignedURL(_: String, _: Option[Int], _: Option[String], _: Option[String])).expects(*, *, *, *).returns("cloud store url") + (ss.getSignedURL(_: String, _: Option[Int], _: Option[String])).expects(*, *, *).returns("cloud store url") val request = getContentRequest() request.getRequest.putAll(mapAsJavaMap(Map("fileName" -> "presigned_url", "filePath" -> "/data/cloudstore/", "type" -> "assets", "identifier" -> "do_1234"))) request.setOperation("uploadPreSignedUrl") diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala index f03a79627..fbb2c2197 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala @@ -9,6 +9,8 @@ import org.sunbird.cloud.storage.factory.StorageServiceFactory import org.sunbird.common.exception.ServerException import org.sunbird.common.Slug +import java.net.URLConnection +import java.util import scala.concurrent.{ExecutionContext, Future} class StorageService { @@ -87,7 +89,7 @@ class StorageService { def getSignedURL(key: String, ttl: Option[Int], permission: Option[String], contentType: Option[String] = None): String = { storageType match { - case "gcloud" => getService.getPutSignedURL(getContainerName, key, ttl, permission, contentType) + case "gcloud" => getService.getPutSignedURL(getContainerName, key, ttl, permission, Option.apply(getMimeType(key))) case _ => getService.getSignedURL (getContainerName, key, ttl, permission) } } @@ -101,4 +103,67 @@ class StorageService { "" } } + + def getMimeType(fileName: String): String = { // 1. first use java's built-in utils + val mimeTypes = URLConnection.getFileNameMap + var contentType = mimeTypes.getContentTypeFor(fileName) + // 2. nothing found -> lookup our in extension map to find types like ".doc" or ".docx" + if (contentType == null) { + val extension = fileName.substring(fileName.lastIndexOf('.') + 1, fileName.length) + contentType = fileExtensionMap.getOrDefault(extension, "application/octet-stream") + } + contentType + } + + private val fileExtensionMap: util.Map[String, String] = new java.util.HashMap().asInstanceOf[java.util.Map[String, String]] + + // MS Office + fileExtensionMap.put("doc", "application/msword") + fileExtensionMap.put("dot", "application/msword") + fileExtensionMap.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document") + fileExtensionMap.put("dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template") + fileExtensionMap.put("docm", "application/vnd.ms-word.document.macroEnabled.12") + fileExtensionMap.put("dotm", "application/vnd.ms-word.template.macroEnabled.12") + fileExtensionMap.put("xls", "application/vnd.ms-excel") + fileExtensionMap.put("xlt", "application/vnd.ms-excel") + fileExtensionMap.put("xla", "application/vnd.ms-excel") + fileExtensionMap.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") + fileExtensionMap.put("xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template") + fileExtensionMap.put("xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12") + fileExtensionMap.put("xltm", "application/vnd.ms-excel.template.macroEnabled.12") + fileExtensionMap.put("xlam", "application/vnd.ms-excel.addin.macroEnabled.12") + fileExtensionMap.put("xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12") + fileExtensionMap.put("ppt", "application/vnd.ms-powerpoint") + fileExtensionMap.put("pot", "application/vnd.ms-powerpoint") + fileExtensionMap.put("pps", "application/vnd.ms-powerpoint") + fileExtensionMap.put("ppa", "application/vnd.ms-powerpoint") + fileExtensionMap.put("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation") + fileExtensionMap.put("potx", "application/vnd.openxmlformats-officedocument.presentationml.template") + fileExtensionMap.put("ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow") + fileExtensionMap.put("ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12") + fileExtensionMap.put("pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12") + fileExtensionMap.put("potm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12") + fileExtensionMap.put("ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12") + // Open Office + fileExtensionMap.put("odt", "application/vnd.oasis.opendocument.text") + fileExtensionMap.put("ott", "application/vnd.oasis.opendocument.text-template") + fileExtensionMap.put("oth", "application/vnd.oasis.opendocument.text-web") + fileExtensionMap.put("odm", "application/vnd.oasis.opendocument.text-master") + fileExtensionMap.put("odg", "application/vnd.oasis.opendocument.graphics") + fileExtensionMap.put("otg", "application/vnd.oasis.opendocument.graphics-template") + fileExtensionMap.put("odp", "application/vnd.oasis.opendocument.presentation") + fileExtensionMap.put("otp", "application/vnd.oasis.opendocument.presentation-template") + fileExtensionMap.put("ods", "application/vnd.oasis.opendocument.spreadsheet") + fileExtensionMap.put("ots", "application/vnd.oasis.opendocument.spreadsheet-template") + fileExtensionMap.put("odc", "application/vnd.oasis.opendocument.chart") + fileExtensionMap.put("odf", "application/vnd.oasis.opendocument.formula") + fileExtensionMap.put("odb", "application/vnd.oasis.opendocument.database") + fileExtensionMap.put("odi", "application/vnd.oasis.opendocument.image") + fileExtensionMap.put("oxt", "application/vnd.openofficeorg.extension") + // Other + fileExtensionMap.put("rtf", "application/rtf") + fileExtensionMap.put("pdf", "application/pdf") + fileExtensionMap.put("h5p", "application/octet-stream") + fileExtensionMap.put("csv", "text/csv") + fileExtensionMap.put("epub", "application/epub+zip") } From 8affd4650ce954a9b6a843ec79c805bd5b591554 Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Mon, 19 Sep 2022 10:37:01 +0530 Subject: [PATCH 095/105] Issue #KN-231 test: Improved unit test coverage. --- .../src/main/scala/org/sunbird/cloudstore/StorageService.scala | 2 +- .../test/scala/org/sunbird/cloudstore/StorageServiceTest.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala index fbb2c2197..3744ae902 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala @@ -87,7 +87,7 @@ class StorageService { getService.deleteObject(getContainerName, key, isDirectory) } - def getSignedURL(key: String, ttl: Option[Int], permission: Option[String], contentType: Option[String] = None): String = { + def getSignedURL(key: String, ttl: Option[Int], permission: Option[String]): String = { storageType match { case "gcloud" => getService.getPutSignedURL(getContainerName, key, ttl, permission, Option.apply(getMimeType(key))) case _ => getService.getSignedURL (getContainerName, key, ttl, permission) diff --git a/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala b/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala index 47ba320e1..66481b690 100644 --- a/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala +++ b/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala @@ -19,7 +19,7 @@ class StorageServiceTest extends AsyncFlatSpec with Matchers { "getSignedURL" should "return the signed url" in { val objectKey = "content" + File.separator + "asset" + File.separator + "do_53245" + File.separator + "abc.png" - val preSignedURL = ss.getSignedURL(objectKey, Option.apply(600), Option.apply("w"), Option.apply("")) + val preSignedURL = ss.getSignedURL(objectKey, Option.apply(600), Option.apply("w")) assert(preSignedURL.contains(objectKey)) } From f17859f0378ef4819e52798038b2d30a687abc82 Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Fri, 23 Sep 2022 18:17:47 +0530 Subject: [PATCH 096/105] Issue #KN-231 test: Used the tika to detect the mimetype from filename. --- .../sunbird/cloudstore/StorageService.scala | 74 ++----------------- 1 file changed, 7 insertions(+), 67 deletions(-) diff --git a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala index 3744ae902..3904888a0 100644 --- a/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala +++ b/platform-modules/mimetype-manager/src/main/scala/org/sunbird/cloudstore/StorageService.scala @@ -1,16 +1,13 @@ package org.sunbird.cloudstore -import java.io.File import org.apache.commons.lang3.StringUtils +import org.apache.tika.Tika import org.sunbird.cloud.storage.BaseStorageService -import org.sunbird.common.Platform -import org.sunbird.cloud.storage.factory.StorageConfig -import org.sunbird.cloud.storage.factory.StorageServiceFactory +import org.sunbird.cloud.storage.factory.{StorageConfig, StorageServiceFactory} +import org.sunbird.common.{Platform, Slug} import org.sunbird.common.exception.ServerException -import org.sunbird.common.Slug -import java.net.URLConnection -import java.util +import java.io.File import scala.concurrent.{ExecutionContext, Future} class StorageService { @@ -104,66 +101,9 @@ class StorageService { } } - def getMimeType(fileName: String): String = { // 1. first use java's built-in utils - val mimeTypes = URLConnection.getFileNameMap - var contentType = mimeTypes.getContentTypeFor(fileName) - // 2. nothing found -> lookup our in extension map to find types like ".doc" or ".docx" - if (contentType == null) { - val extension = fileName.substring(fileName.lastIndexOf('.') + 1, fileName.length) - contentType = fileExtensionMap.getOrDefault(extension, "application/octet-stream") - } - contentType + def getMimeType(fileName: String): String = { + val tika: Tika = new Tika() + tika.detect(fileName) } - private val fileExtensionMap: util.Map[String, String] = new java.util.HashMap().asInstanceOf[java.util.Map[String, String]] - - // MS Office - fileExtensionMap.put("doc", "application/msword") - fileExtensionMap.put("dot", "application/msword") - fileExtensionMap.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document") - fileExtensionMap.put("dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template") - fileExtensionMap.put("docm", "application/vnd.ms-word.document.macroEnabled.12") - fileExtensionMap.put("dotm", "application/vnd.ms-word.template.macroEnabled.12") - fileExtensionMap.put("xls", "application/vnd.ms-excel") - fileExtensionMap.put("xlt", "application/vnd.ms-excel") - fileExtensionMap.put("xla", "application/vnd.ms-excel") - fileExtensionMap.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") - fileExtensionMap.put("xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template") - fileExtensionMap.put("xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12") - fileExtensionMap.put("xltm", "application/vnd.ms-excel.template.macroEnabled.12") - fileExtensionMap.put("xlam", "application/vnd.ms-excel.addin.macroEnabled.12") - fileExtensionMap.put("xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12") - fileExtensionMap.put("ppt", "application/vnd.ms-powerpoint") - fileExtensionMap.put("pot", "application/vnd.ms-powerpoint") - fileExtensionMap.put("pps", "application/vnd.ms-powerpoint") - fileExtensionMap.put("ppa", "application/vnd.ms-powerpoint") - fileExtensionMap.put("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation") - fileExtensionMap.put("potx", "application/vnd.openxmlformats-officedocument.presentationml.template") - fileExtensionMap.put("ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow") - fileExtensionMap.put("ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12") - fileExtensionMap.put("pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12") - fileExtensionMap.put("potm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12") - fileExtensionMap.put("ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12") - // Open Office - fileExtensionMap.put("odt", "application/vnd.oasis.opendocument.text") - fileExtensionMap.put("ott", "application/vnd.oasis.opendocument.text-template") - fileExtensionMap.put("oth", "application/vnd.oasis.opendocument.text-web") - fileExtensionMap.put("odm", "application/vnd.oasis.opendocument.text-master") - fileExtensionMap.put("odg", "application/vnd.oasis.opendocument.graphics") - fileExtensionMap.put("otg", "application/vnd.oasis.opendocument.graphics-template") - fileExtensionMap.put("odp", "application/vnd.oasis.opendocument.presentation") - fileExtensionMap.put("otp", "application/vnd.oasis.opendocument.presentation-template") - fileExtensionMap.put("ods", "application/vnd.oasis.opendocument.spreadsheet") - fileExtensionMap.put("ots", "application/vnd.oasis.opendocument.spreadsheet-template") - fileExtensionMap.put("odc", "application/vnd.oasis.opendocument.chart") - fileExtensionMap.put("odf", "application/vnd.oasis.opendocument.formula") - fileExtensionMap.put("odb", "application/vnd.oasis.opendocument.database") - fileExtensionMap.put("odi", "application/vnd.oasis.opendocument.image") - fileExtensionMap.put("oxt", "application/vnd.openofficeorg.extension") - // Other - fileExtensionMap.put("rtf", "application/rtf") - fileExtensionMap.put("pdf", "application/pdf") - fileExtensionMap.put("h5p", "application/octet-stream") - fileExtensionMap.put("csv", "text/csv") - fileExtensionMap.put("epub", "application/epub+zip") } From 2c95ba7e9ecc63f5058fff98fc633e9bd3a2a36e Mon Sep 17 00:00:00 2001 From: AmiableAnil Date: Fri, 23 Sep 2022 18:56:15 +0530 Subject: [PATCH 097/105] Issue #KN-231 test: Improved the unit test. --- .../cloudstore/StorageServiceTest.scala | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala b/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala index 66481b690..071a9e20c 100644 --- a/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala +++ b/platform-modules/mimetype-manager/src/test/scala/org/sunbird/cloudstore/StorageServiceTest.scala @@ -27,4 +27,29 @@ class StorageServiceTest extends AsyncFlatSpec with Matchers { val uri = ss.getUri("content/abc.json") assert(uri != null) } + + "getMimeType" should "return the mimetype application/epub+zip for epub" in { + val result = ss.getMimeType("test.alert.epub") + assert(result == "application/epub+zip") + } + + "getMimeType" should "return the mimetype application/octet-stream for h5p" in { + val result = ss.getMimeType("test.alert.h5p") + assert(result == "application/octet-stream") + } + + "getMimeType" should "return the mimetype text/csv for csv" in { + val result = ss.getMimeType("test.alert.csv") + assert(result == "text/csv") + } + + "getMimeType" should "return the mimetype application/pdf for pdf" in { + val result = ss.getMimeType("test.alert.pdf") + assert(result == "application/pdf") + } + + "getMimeType" should "return the mimetype application/zip for zip" in { + val result = ss.getMimeType("test.alert.zip") + assert(result == "application/zip") + } } From c6e093ab8e1f841f013ca4a2ccfd55a234012825 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Thu, 6 Oct 2022 15:29:51 +0530 Subject: [PATCH 098/105] Issue #KN-257 feat: Content Release DIAL codes API refactor. --- .../scala/org/sunbird/content/dial/DIALManager.scala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 5bb14c093..5177b1dc2 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -357,8 +357,13 @@ object DIALManager { val imageCollectionHierarchy = getImageHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] val imageChildrenHierarchy = imageCollectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList val imageChildrenAssignedDIALList = getAssignedDIALcodes(imageChildrenHierarchy) - val contentImageAssignedDIALList = if(imageCollectionHierarchy.containsKey(DIALConstants.DIALCODES) && imageCollectionHierarchy.get(DIALConstants.DIALCODES) != null) - imageChildrenAssignedDIALList ++ imageCollectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] + val contentImageAssignedDIALList = if(imageCollectionHierarchy.containsKey(DIALConstants.DIALCODES) && imageCollectionHierarchy.get(DIALConstants.DIALCODES) != null) { + val hierarchyDialCode: List[String] = imageCollectionHierarchy.get(DIALConstants.DIALCODES) match { + case strVal: String => ScalaJsonUtils.deserialize(strVal).asInstanceOf[List[String]] + case anyVal => anyVal.asInstanceOf[List[String]] + } + imageChildrenAssignedDIALList ++ hierarchyDialCode + } else imageChildrenAssignedDIALList request.put(ContentConstants.ROOT_ID, contentId) From fd8f7c5a0926e521aab46bf86438ecad75939646 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 7 Oct 2022 11:09:26 +0530 Subject: [PATCH 099/105] Issue #KN-547 debug: Collection hierarchy dialcodes coming as string --- .../src/main/scala/org/sunbird/content/dial/DIALManager.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 5177b1dc2..7c05ab339 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -10,6 +10,7 @@ import org.sunbird.graph.dac.model.Node import org.sunbird.graph.nodes.DataNode import org.sunbird.graph.utils.ScalaJsonUtils import org.sunbird.managers.HierarchyManager +import org.sunbird.telemetry.logger.TelemetryManager import java.util import scala.collection.JavaConverters._ @@ -358,6 +359,7 @@ object DIALManager { val imageChildrenHierarchy = imageCollectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList val imageChildrenAssignedDIALList = getAssignedDIALcodes(imageChildrenHierarchy) val contentImageAssignedDIALList = if(imageCollectionHierarchy.containsKey(DIALConstants.DIALCODES) && imageCollectionHierarchy.get(DIALConstants.DIALCODES) != null) { + TelemetryManager.info("DIALManager:: populateAssignedDialCodes:: collection DIAL codes:: " + imageCollectionHierarchy.get(DIALConstants.DIALCODES).toString) val hierarchyDialCode: List[String] = imageCollectionHierarchy.get(DIALConstants.DIALCODES) match { case strVal: String => ScalaJsonUtils.deserialize(strVal).asInstanceOf[List[String]] case anyVal => anyVal.asInstanceOf[List[String]] From d77e55d181186d68235dcbee69086bdab6506ff8 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 7 Oct 2022 12:41:44 +0530 Subject: [PATCH 100/105] Issue #KN-547 debug: Collection hierarchy dialcodes coming as string --- .../scala/org/sunbird/content/dial/DIALManager.scala | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 7c05ab339..65f3d551f 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -356,14 +356,13 @@ object DIALManager { HierarchyManager.getHierarchy(request).flatMap(getImageHierarchyResponse => { val imageCollectionHierarchy = getImageHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] + TelemetryManager.info("DIALManager:: populateAssignedDialCodes:: imageCollectionHierarchy:: " + imageCollectionHierarchy) val imageChildrenHierarchy = imageCollectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList val imageChildrenAssignedDIALList = getAssignedDIALcodes(imageChildrenHierarchy) val contentImageAssignedDIALList = if(imageCollectionHierarchy.containsKey(DIALConstants.DIALCODES) && imageCollectionHierarchy.get(DIALConstants.DIALCODES) != null) { - TelemetryManager.info("DIALManager:: populateAssignedDialCodes:: collection DIAL codes:: " + imageCollectionHierarchy.get(DIALConstants.DIALCODES).toString) - val hierarchyDialCode: List[String] = imageCollectionHierarchy.get(DIALConstants.DIALCODES) match { - case strVal: String => ScalaJsonUtils.deserialize(strVal).asInstanceOf[List[String]] - case anyVal => anyVal.asInstanceOf[List[String]] - } + TelemetryManager.info("DIALManager:: populateAssignedDialCodes:: collection DIAL codes:: " + imageCollectionHierarchy.get(DIALConstants.DIALCODES)) + val hierarchyDialCodeStr = ScalaJsonUtils.serialize(imageCollectionHierarchy.get(DIALConstants.DIALCODES)) + val hierarchyDialCode = ScalaJsonUtils.deserialize(hierarchyDialCodeStr).asInstanceOf[List[String]] imageChildrenAssignedDIALList ++ hierarchyDialCode } else imageChildrenAssignedDIALList From 64d13ad12cef8f4df02a05a9482a1014230b120b Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 7 Oct 2022 13:51:08 +0530 Subject: [PATCH 101/105] Issue #KN-547 debug: Collection hierarchy dialcodes coming as string --- .../main/scala/org/sunbird/content/dial/DIALManager.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 65f3d551f..1262be12a 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -361,8 +361,10 @@ object DIALManager { val imageChildrenAssignedDIALList = getAssignedDIALcodes(imageChildrenHierarchy) val contentImageAssignedDIALList = if(imageCollectionHierarchy.containsKey(DIALConstants.DIALCODES) && imageCollectionHierarchy.get(DIALConstants.DIALCODES) != null) { TelemetryManager.info("DIALManager:: populateAssignedDialCodes:: collection DIAL codes:: " + imageCollectionHierarchy.get(DIALConstants.DIALCODES)) - val hierarchyDialCodeStr = ScalaJsonUtils.serialize(imageCollectionHierarchy.get(DIALConstants.DIALCODES)) - val hierarchyDialCode = ScalaJsonUtils.deserialize(hierarchyDialCodeStr).asInstanceOf[List[String]] + val hierarchyDialCode = imageCollectionHierarchy.get(DIALConstants.DIALCODES) match { + case javaStr: java.lang.String => ScalaJsonUtils.deserialize[List[String]](javaStr) + case anyVal => anyVal.asInstanceOf[List[String]] + } imageChildrenAssignedDIALList ++ hierarchyDialCode } else imageChildrenAssignedDIALList From 76ad98db9bd96978246743f49483a7f6aa9f5b85 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 7 Oct 2022 14:42:45 +0530 Subject: [PATCH 102/105] Issue #KN-547 debug: Collection hierarchy dialcodes coming as string --- .../main/scala/org/sunbird/content/dial/DIALManager.scala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 1262be12a..9a1deaf91 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -361,10 +361,9 @@ object DIALManager { val imageChildrenAssignedDIALList = getAssignedDIALcodes(imageChildrenHierarchy) val contentImageAssignedDIALList = if(imageCollectionHierarchy.containsKey(DIALConstants.DIALCODES) && imageCollectionHierarchy.get(DIALConstants.DIALCODES) != null) { TelemetryManager.info("DIALManager:: populateAssignedDialCodes:: collection DIAL codes:: " + imageCollectionHierarchy.get(DIALConstants.DIALCODES)) - val hierarchyDialCode = imageCollectionHierarchy.get(DIALConstants.DIALCODES) match { - case javaStr: java.lang.String => ScalaJsonUtils.deserialize[List[String]](javaStr) - case anyVal => anyVal.asInstanceOf[List[String]] - } + val hierarchyDialCodeStr = ScalaJsonUtils.serialize(imageCollectionHierarchy.get(DIALConstants.DIALCODES)) + TelemetryManager.info("DIALManager:: populateAssignedDialCodes:: hierarchyDialCodeStr:: " + hierarchyDialCodeStr) + val hierarchyDialCode = ScalaJsonUtils.deserialize[List[String]](hierarchyDialCodeStr) imageChildrenAssignedDIALList ++ hierarchyDialCode } else imageChildrenAssignedDIALList From 4529c4fc6eb570ddac719367264ec2fa3aa49e98 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 7 Oct 2022 15:26:00 +0530 Subject: [PATCH 103/105] Issue #KN-547 fix: Collection hierarchy dialcodes coming as string --- .../org/sunbird/content/dial/DIALManager.scala | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index 9a1deaf91..c50ea16c5 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -356,15 +356,12 @@ object DIALManager { HierarchyManager.getHierarchy(request).flatMap(getImageHierarchyResponse => { val imageCollectionHierarchy = getImageHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] - TelemetryManager.info("DIALManager:: populateAssignedDialCodes:: imageCollectionHierarchy:: " + imageCollectionHierarchy) val imageChildrenHierarchy = imageCollectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList val imageChildrenAssignedDIALList = getAssignedDIALcodes(imageChildrenHierarchy) val contentImageAssignedDIALList = if(imageCollectionHierarchy.containsKey(DIALConstants.DIALCODES) && imageCollectionHierarchy.get(DIALConstants.DIALCODES) != null) { - TelemetryManager.info("DIALManager:: populateAssignedDialCodes:: collection DIAL codes:: " + imageCollectionHierarchy.get(DIALConstants.DIALCODES)) - val hierarchyDialCodeStr = ScalaJsonUtils.serialize(imageCollectionHierarchy.get(DIALConstants.DIALCODES)) - TelemetryManager.info("DIALManager:: populateAssignedDialCodes:: hierarchyDialCodeStr:: " + hierarchyDialCodeStr) - val hierarchyDialCode = ScalaJsonUtils.deserialize[List[String]](hierarchyDialCodeStr) - imageChildrenAssignedDIALList ++ hierarchyDialCode + val collectionDialCodeStr = ScalaJsonUtils.serialize(imageCollectionHierarchy.get(DIALConstants.DIALCODES)) + val collectionDialCode = ScalaJsonUtils.deserialize[List[String]](collectionDialCodeStr) + imageChildrenAssignedDIALList ++ collectionDialCode } else imageChildrenAssignedDIALList @@ -375,9 +372,11 @@ object DIALManager { val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList val childrenAssignedDIALList = getAssignedDIALcodes(childrenHierarchy) - val contentAssignedDIALList = if(collectionHierarchy.containsKey(DIALConstants.DIALCODES) && collectionHierarchy.get(DIALConstants.DIALCODES) != null) - childrenAssignedDIALList ++ collectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] - else childrenAssignedDIALList + val contentAssignedDIALList = if(collectionHierarchy.containsKey(DIALConstants.DIALCODES) && collectionHierarchy.get(DIALConstants.DIALCODES) != null) { + val collectionDialCodeStr = ScalaJsonUtils.serialize(collectionHierarchy.get(DIALConstants.DIALCODES)) + val collectionDialCode = ScalaJsonUtils.deserialize[List[String]](collectionDialCodeStr) + childrenAssignedDIALList ++ collectionDialCode + } else childrenAssignedDIALList Future(contentImageAssignedDIALList ++ contentAssignedDIALList) }) From 2b9501efa7eb830fc3f81856fa51ee6172501bb6 Mon Sep 17 00:00:00 2001 From: Jayaprakash8887 Date: Fri, 7 Oct 2022 15:26:39 +0530 Subject: [PATCH 104/105] Issue #KN-547 fix: Collection hierarchy dialcodes coming as string --- .../main/scala/org/sunbird/content/dial/DIALManager.scala | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala index c50ea16c5..2bffec273 100644 --- a/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala +++ b/content-api/content-actors/src/main/scala/org/sunbird/content/dial/DIALManager.scala @@ -372,11 +372,9 @@ object DIALManager { val collectionHierarchy = getHierarchyResponse.getResult.getOrDefault(ContentConstants.CONTENT, new java.util.HashMap[String, AnyRef]()).asInstanceOf[java.util.Map[String, AnyRef]] val childrenHierarchy = collectionHierarchy.get(ContentConstants.CHILDREN).asInstanceOf[util.List[util.Map[String, AnyRef]]].asScala.toList val childrenAssignedDIALList = getAssignedDIALcodes(childrenHierarchy) - val contentAssignedDIALList = if(collectionHierarchy.containsKey(DIALConstants.DIALCODES) && collectionHierarchy.get(DIALConstants.DIALCODES) != null) { - val collectionDialCodeStr = ScalaJsonUtils.serialize(collectionHierarchy.get(DIALConstants.DIALCODES)) - val collectionDialCode = ScalaJsonUtils.deserialize[List[String]](collectionDialCodeStr) - childrenAssignedDIALList ++ collectionDialCode - } else childrenAssignedDIALList + val contentAssignedDIALList = if(collectionHierarchy.containsKey(DIALConstants.DIALCODES) && collectionHierarchy.get(DIALConstants.DIALCODES) != null) + childrenAssignedDIALList ++ collectionHierarchy.getOrDefault(DIALConstants.DIALCODES, List.empty[String]).asInstanceOf[List[String]] + else childrenAssignedDIALList Future(contentImageAssignedDIALList ++ contentAssignedDIALList) }) From 5ee124ff31976268c8f0af261bb075bf3d521fdd Mon Sep 17 00:00:00 2001 From: Anil Gupta Date: Fri, 7 Oct 2022 16:35:07 +0530 Subject: [PATCH 105/105] Issue #KN-231 chore: Bump up the cloud-store-sdk to 1.4.3 --- platform-modules/mimetype-manager/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform-modules/mimetype-manager/pom.xml b/platform-modules/mimetype-manager/pom.xml index 80a17876b..ea978cbd5 100644 --- a/platform-modules/mimetype-manager/pom.xml +++ b/platform-modules/mimetype-manager/pom.xml @@ -30,7 +30,7 @@ org.sunbird cloud-store-sdk - 1.4.1 + 1.4.3 org.scala-lang @@ -143,4 +143,4 @@ - \ No newline at end of file +