From fa1d2b88efb50b9671bf35c58dea2d5e7f63d21a Mon Sep 17 00:00:00 2001 From: saipradeep_ravipati <saipradeep.ravipati@tarento.com> Date: Tue, 25 Apr 2023 14:32:02 +0530 Subject: [PATCH] Added validate-api for OGHR question assestment requirement --- pom.xml | 1 + validate-api/pom.xml | 59 + validate-api/validate-actors/pom.xml | 123 ++ .../org/sunbird/actors/HealthActor.scala | 20 + .../src/test/resources/application.conf | 416 +++++++ .../scala/org/sunbird/actors/BaseSpec.scala | 78 ++ .../validate-hierarchy-manager/pom.xml | 136 +++ .../src/test/resources/application.conf | 423 +++++++ .../src/test/resources/cassandra-unit.yaml | 590 ++++++++++ .../src/test/resources/logback.xml | 28 + .../scala/org/sunbird/managers/BaseSpec.scala | 101 ++ .../app/controllers/BaseController.scala | 73 ++ .../app/controllers/HealthController.scala | 31 + .../QuestionValidateController.java | 37 + .../app/filters/AccessLogFilter.scala | 45 + .../app/handlers/SignalHandler.scala | 33 + .../app/modules/AssessmentModule.scala | 16 + .../app/utils/ActorNames.scala | 7 + .../validate-service/app/utils/ApiId.scala | 9 + .../validate-service/app/utils/Attrs.java | 21 + .../app/utils/JavaJsonUtils.scala | 38 + .../validate-service/app/utils/JsonKey.java | 1020 +++++++++++++++++ .../app/utils/QuestionOperations.scala | 6 + .../app/utils/RequestContext.java | 87 ++ .../validate-service/conf/application.conf | 407 +++++++ .../validate-service/conf/logback.xml | 28 + validate-api/validate-service/conf/routes | 8 + validate-api/validate-service/pom.xml | 188 +++ .../test/controllers/base/BaseSpec.scala | 38 + .../controllers/v3/HealthControllerSpec.scala | 18 + .../test/modules/TestModule.scala | 26 + 31 files changed, 4111 insertions(+) create mode 100644 validate-api/pom.xml create mode 100644 validate-api/validate-actors/pom.xml create mode 100644 validate-api/validate-actors/src/main/scala/org/sunbird/actors/HealthActor.scala create mode 100644 validate-api/validate-actors/src/test/resources/application.conf create mode 100644 validate-api/validate-actors/src/test/scala/org/sunbird/actors/BaseSpec.scala create mode 100644 validate-api/validate-hierarchy-manager/pom.xml create mode 100644 validate-api/validate-hierarchy-manager/src/test/resources/application.conf create mode 100755 validate-api/validate-hierarchy-manager/src/test/resources/cassandra-unit.yaml create mode 100644 validate-api/validate-hierarchy-manager/src/test/resources/logback.xml create mode 100644 validate-api/validate-hierarchy-manager/src/test/scala/org/sunbird/managers/BaseSpec.scala create mode 100644 validate-api/validate-service/app/controllers/BaseController.scala create mode 100644 validate-api/validate-service/app/controllers/HealthController.scala create mode 100644 validate-api/validate-service/app/controllers/QuestionValidateController.java create mode 100644 validate-api/validate-service/app/filters/AccessLogFilter.scala create mode 100644 validate-api/validate-service/app/handlers/SignalHandler.scala create mode 100644 validate-api/validate-service/app/modules/AssessmentModule.scala create mode 100644 validate-api/validate-service/app/utils/ActorNames.scala create mode 100644 validate-api/validate-service/app/utils/ApiId.scala create mode 100644 validate-api/validate-service/app/utils/Attrs.java create mode 100644 validate-api/validate-service/app/utils/JavaJsonUtils.scala create mode 100644 validate-api/validate-service/app/utils/JsonKey.java create mode 100644 validate-api/validate-service/app/utils/QuestionOperations.scala create mode 100644 validate-api/validate-service/app/utils/RequestContext.java create mode 100644 validate-api/validate-service/conf/application.conf create mode 100644 validate-api/validate-service/conf/logback.xml create mode 100644 validate-api/validate-service/conf/routes create mode 100644 validate-api/validate-service/pom.xml create mode 100644 validate-api/validate-service/test/controllers/base/BaseSpec.scala create mode 100644 validate-api/validate-service/test/controllers/v3/HealthControllerSpec.scala create mode 100644 validate-api/validate-service/test/modules/TestModule.scala diff --git a/pom.xml b/pom.xml index 0558992df..d5ecfe39b 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,7 @@ <module>taxonomy-api</module> <module>platform-modules</module> <module>search-api</module> + <module>validate-api</module> </modules> </profile> <profile> diff --git a/validate-api/pom.xml b/validate-api/pom.xml new file mode 100644 index 000000000..fc043cb92 --- /dev/null +++ b/validate-api/pom.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>knowledge-platform</artifactId> + <groupId>org.sunbird</groupId> + <version>1.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>validate-api</artifactId> + <packaging>pom</packaging> + <name>validate-api</name> + <modules> + <module>validate-actors</module> + <module>validate-service</module> + <module>validate-hierarchy-manager</module> + </modules> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <scala.major.version>2.11</scala.major.version> + </properties> + + <build> + <pluginManagement> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <version>3.3.0</version> + <configuration> + <descriptors> + <descriptor>src/assembly/bin.xml</descriptor> + </descriptors> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + <configuration> + <release>11</release> + </configuration> + </plugin> + <plugin> + <groupId>org.scoverage</groupId> + <artifactId>scoverage-maven-plugin</artifactId> + <configuration> + <scalaVersion>${scala.version}</scalaVersion> + <aggregate>true</aggregate> + <highlighting>true</highlighting> + </configuration> + </plugin> + </plugins> + </pluginManagement> + </build> + +</project> diff --git a/validate-api/validate-actors/pom.xml b/validate-api/validate-actors/pom.xml new file mode 100644 index 000000000..99a3ea676 --- /dev/null +++ b/validate-api/validate-actors/pom.xml @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>validate-api</artifactId> + <groupId>org.sunbird</groupId> + <version>1.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>validate-actors</artifactId> + + <dependencies> + <dependency> + <groupId>org.scala-lang</groupId> + <artifactId>scala-library</artifactId> + <version>${scala.version}</version> + </dependency> + <dependency> + <groupId>javax.inject</groupId> + <artifactId>javax.inject</artifactId> + <version>1</version> + </dependency> + <dependency> + <groupId>org.sunbird</groupId> + <artifactId>actor-core</artifactId> + <version>1.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.sunbird</groupId> + <artifactId>graph-engine_2.11</artifactId> + <version>1.0-SNAPSHOT</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.sunbird</groupId> + <artifactId>validate-hierarchy-manager</artifactId> + <version>1.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.sunbird</groupId> + <artifactId>import-manager</artifactId> + <version>1.0-SNAPSHOT</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.scalatest</groupId> + <artifactId>scalatest_${scala.maj.version}</artifactId> + <version>${scalatest.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.scalamock</groupId> + <artifactId>scalamock_${scala.maj.version}</artifactId> + <version>4.4.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.typesafe.akka</groupId> + <artifactId>akka-testkit_${scala.maj.version}</artifactId> + <version>2.5.22</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <sourceDirectory>src/main/scala</sourceDirectory> + <testSourceDirectory>src/test/scala</testSourceDirectory> + <plugins> + <plugin> + <groupId>net.alchim31.maven</groupId> + <artifactId>scala-maven-plugin</artifactId> + <version>4.4.0</version> + <configuration> + <scalaVersion>${scala.version}</scalaVersion> + <checkMultipleScalaVersions>false</checkMultipleScalaVersions> + </configuration> + <executions> + <execution> + <id>scala-compile-first</id> + <phase>process-resources</phase> + <goals> + <goal>add-source</goal> + <goal>compile</goal> + </goals> + </execution> + <execution> + <id>scala-test-compile</id> + <phase>process-test-resources</phase> + <goals> + <goal>testCompile</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.scalatest</groupId> + <artifactId>scalatest-maven-plugin</artifactId> + <version>2.0.0</version> + <executions> + <execution> + <id>test</id> + <phase>test</phase> + <goals> + <goal>test</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.scoverage</groupId> + <artifactId>scoverage-maven-plugin</artifactId> + <version>${scoverage.plugin.version}</version> + <configuration> + <scalaVersion>${scala.version}</scalaVersion> + <aggregate>true</aggregate> + <highlighting>true</highlighting> + </configuration> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file diff --git a/validate-api/validate-actors/src/main/scala/org/sunbird/actors/HealthActor.scala b/validate-api/validate-actors/src/main/scala/org/sunbird/actors/HealthActor.scala new file mode 100644 index 000000000..3072bb928 --- /dev/null +++ b/validate-api/validate-actors/src/main/scala/org/sunbird/actors/HealthActor.scala @@ -0,0 +1,20 @@ +package org.sunbird.actors + +import javax.inject.Inject +import org.sunbird.actor.core.BaseActor +import org.sunbird.common.dto.{Request, Response} +import org.sunbird.graph.OntologyEngineContext +import org.sunbird.graph.health.HealthCheckManager + +import scala.concurrent.{ExecutionContext, Future} + + +class HealthActor @Inject() (implicit oec: OntologyEngineContext) extends BaseActor { + + implicit val ec: ExecutionContext = getContext().dispatcher + + @throws[Throwable] + override def onReceive(request: Request): Future[Response] = { + HealthCheckManager.checkAllSystemHealth() + } +} diff --git a/validate-api/validate-actors/src/test/resources/application.conf b/validate-api/validate-actors/src/test/resources/application.conf new file mode 100644 index 000000000..24d3a74f2 --- /dev/null +++ b/validate-api/validate-actors/src/test/resources/application.conf @@ -0,0 +1,416 @@ +# This is the main configuration file for the application. +# https://www.playframework.com/documentation/latest/ConfigFile +# ~~~~~ +# Play uses HOCON as its configuration file format. HOCON has a number +# of advantages over other config formats, but there are two things that +# can be used when modifying settings. +# +# You can include other configuration files in this main application.conf file: +#include "extra-config.conf" +# +# You can declare variables and substitute for them: +#mykey = ${some.value} +# +# And if an environment variable exists when there is no other substitution, then +# HOCON will fall back to substituting environment variable: +#mykey = ${JAVA_HOME} + +## Akka +# https://www.playframework.com/documentation/latest/ScalaAkka#Configuration +# https://www.playframework.com/documentation/latest/JavaAkka#Configuration +# ~~~~~ +# Play uses Akka internally and exposes Akka Streams and actors in Websockets and +# other streaming HTTP responses. +akka { + # "akka.log-config-on-start" is extraordinarly useful because it log the complete + # configuration at INFO level, including defaults and overrides, so it s worth + # putting at the very top. + # + # Put the following in your conf/logback.xml file: + # + # <logger name="akka.actor" level="INFO" /> + # + # And then uncomment this line to debug the configuration. + # + #log-config-on-start = true +} + +## Secret key +# http://www.playframework.com/documentation/latest/ApplicationSecret +# ~~~~~ +# The secret key is used to sign Play's session cookie. +# This must be changed for production, but we don't recommend you change it in this file. +play.http.secret.key = a-long-secret-to-calm-the-rage-of-the-entropy-gods + +## Modules +# https://www.playframework.com/documentation/latest/Modules +# ~~~~~ +# Control which modules are loaded when Play starts. Note that modules are +# the replacement for "GlobalSettings", which are deprecated in 2.5.x. +# Please see https://www.playframework.com/documentation/latest/GlobalSettings +# for more information. +# +# You can also extend Play functionality by using one of the publically available +# Play modules: https://playframework.com/documentation/latest/ModuleDirectory +play.modules { + # By default, Play will load any class called Module that is defined + # in the root package (the "app" directory), or you can define them + # explicitly below. + # If there are any built-in modules that you want to enable, you can list them here. + #enabled += my.application.Module + + # If there are any built-in modules that you want to disable, you can list them here. + #disabled += "" +} + +## IDE +# https://www.playframework.com/documentation/latest/IDE +# ~~~~~ +# Depending on your IDE, you can add a hyperlink for errors that will jump you +# directly to the code location in the IDE in dev mode. The following line makes +# use of the IntelliJ IDEA REST interface: +#play.editor="http://localhost:63342/api/file/?file=%s&line=%s" + +## Internationalisation +# https://www.playframework.com/documentation/latest/JavaI18N +# https://www.playframework.com/documentation/latest/ScalaI18N +# ~~~~~ +# Play comes with its own i18n settings, which allow the user's preferred language +# to map through to internal messages, or allow the language to be stored in a cookie. +play.i18n { + # The application languages + langs = [ "en" ] + + # Whether the language cookie should be secure or not + #langCookieSecure = true + + # Whether the HTTP only attribute of the cookie should be set to true + #langCookieHttpOnly = true +} + +## Play HTTP settings +# ~~~~~ +play.http { + ## Router + # https://www.playframework.com/documentation/latest/JavaRouting + # https://www.playframework.com/documentation/latest/ScalaRouting + # ~~~~~ + # Define the Router object to use for this application. + # This router will be looked up first when the application is starting up, + # so make sure this is the entry point. + # Furthermore, it's assumed your route file is named properly. + # So for an application router like `my.application.Router`, + # you may need to define a router file `conf/my.application.routes`. + # Default to Routes in the root package (aka "apps" folder) (and conf/routes) + #router = my.application.Router + + ## Action Creator + # https://www.playframework.com/documentation/latest/JavaActionCreator + # ~~~~~ + #actionCreator = null + + ## ErrorHandler + # https://www.playframework.com/documentation/latest/JavaRouting + # https://www.playframework.com/documentation/latest/ScalaRouting + # ~~~~~ + # If null, will attempt to load a class called ErrorHandler in the root package, + #errorHandler = null + + ## Session & Flash + # https://www.playframework.com/documentation/latest/JavaSessionFlash + # https://www.playframework.com/documentation/latest/ScalaSessionFlash + # ~~~~~ + session { + # Sets the cookie to be sent only over HTTPS. + #secure = true + + # Sets the cookie to be accessed only by the server. + #httpOnly = true + + # Sets the max-age field of the cookie to 5 minutes. + # NOTE: this only sets when the browser will discard the cookie. Play will consider any + # cookie value with a valid signature to be a valid session forever. To implement a server side session timeout, + # you need to put a timestamp in the session and check it at regular intervals to possibly expire it. + #maxAge = 300 + + # Sets the domain on the session cookie. + #domain = "example.com" + } + + flash { + # Sets the cookie to be sent only over HTTPS. + #secure = true + + # Sets the cookie to be accessed only by the server. + #httpOnly = true + } +} + +## Netty Provider +# https://www.playframework.com/documentation/latest/SettingsNetty +# ~~~~~ +play.server.netty { + # Whether the Netty wire should be logged + log.wire = true + + # If you run Play on Linux, you can use Netty's native socket transport + # for higher performance with less garbage. + transport = "native" +} + +## WS (HTTP Client) +# https://www.playframework.com/documentation/latest/ScalaWS#Configuring-WS +# ~~~~~ +# The HTTP client primarily used for REST APIs. The default client can be +# configured directly, but you can also create different client instances +# with customized settings. You must enable this by adding to build.sbt: +# +# libraryDependencies += ws // or javaWs if using java +# +play.ws { + # Sets HTTP requests not to follow 302 requests + #followRedirects = false + + # Sets the maximum number of open HTTP connections for the client. + #ahc.maxConnectionsTotal = 50 + + ## WS SSL + # https://www.playframework.com/documentation/latest/WsSSL + # ~~~~~ + ssl { + # Configuring HTTPS with Play WS does not require programming. You can + # set up both trustManager and keyManager for mutual authentication, and + # turn on JSSE debugging in development with a reload. + #debug.handshake = true + #trustManager = { + # stores = [ + # { type = "JKS", path = "exampletrust.jks" } + # ] + #} + } +} + +## Cache +# https://www.playframework.com/documentation/latest/JavaCache +# https://www.playframework.com/documentation/latest/ScalaCache +# ~~~~~ +# Play comes with an integrated cache API that can reduce the operational +# overhead of repeated requests. You must enable this by adding to build.sbt: +# +# libraryDependencies += cache +# +play.cache { + # If you want to bind several caches, you can bind the individually + #bindCaches = ["db-cache", "user-cache", "session-cache"] +} + +## Filter Configuration +# https://www.playframework.com/documentation/latest/Filters +# ~~~~~ +# There are a number of built-in filters that can be enabled and configured +# to give Play greater security. +# +play.filters { + + # Enabled filters are run automatically against Play. + # CSRFFilter, AllowedHostFilters, and SecurityHeadersFilters are enabled by default. + enabled = [] + + # Disabled filters remove elements from the enabled list. + # disabled += filters.CSRFFilter + + + ## CORS filter configuration + # https://www.playframework.com/documentation/latest/CorsFilter + # ~~~~~ + # CORS is a protocol that allows web applications to make requests from the browser + # across different domains. + # NOTE: You MUST apply the CORS configuration before the CSRF filter, as CSRF has + # dependencies on CORS settings. + cors { + # Filter paths by a whitelist of path prefixes + #pathPrefixes = ["/some/path", ...] + + # The allowed origins. If null, all origins are allowed. + #allowedOrigins = ["http://www.example.com"] + + # The allowed HTTP methods. If null, all methods are allowed + #allowedHttpMethods = ["GET", "POST"] + } + + ## Security headers filter configuration + # https://www.playframework.com/documentation/latest/SecurityHeaders + # ~~~~~ + # Defines security headers that prevent XSS attacks. + # If enabled, then all options are set to the below configuration by default: + headers { + # The X-Frame-Options header. If null, the header is not set. + #frameOptions = "DENY" + + # The X-XSS-Protection header. If null, the header is not set. + #xssProtection = "1; mode=block" + + # The X-Content-Type-Options header. If null, the header is not set. + #contentTypeOptions = "nosniff" + + # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set. + #permittedCrossDomainPolicies = "master-only" + + # The Content-Security-Policy header. If null, the header is not set. + #contentSecurityPolicy = "default-src 'self'" + } + + ## Allowed hosts filter configuration + # https://www.playframework.com/documentation/latest/AllowedHostsFilter + # ~~~~~ + # Play provides a filter that lets you configure which hosts can access your application. + # This is useful to prevent cache poisoning attacks. + hosts { + # Allow requests to example.com, its subdomains, and localhost:9000. + #allowed = [".example.com", "localhost:9000"] + } +} + +# Learning-Service Configuration +content.metadata.visibility.parent=["textbookunit", "courseunit", "lessonplanunit"] + +# Cassandra Configuration +content.keyspace.name=content_store +content.keyspace.table=content_data +#TODO: Add Configuration for assessment. e.g: question_data +orchestrator.keyspace.name=script_store +orchestrator.keyspace.table=script_data +cassandra.lp.connection="127.0.0.1:9042,127.0.0.2:9042,127.0.0.3:9042" +cassandra.lpa.connection="127.0.0.1:9042,127.0.0.2:9042,127.0.0.3:9042" + +# Redis Configuration +redis.host=localhost +redis.port=6379 +redis.maxConnections=128 + +#Condition to enable publish locally +content.publish_task.enabled=true + +#directory location where store unzip file +dist.directory=/data/tmp/dist/ +output.zipfile=/data/tmp/story.zip +source.folder=/data/tmp/temp2/ +save.directory=/data/tmp/temp/ + +# Content 2 vec analytics URL +CONTENT_TO_VEC_URL="http://172.31.27.233:9000/content-to-vec" + +# FOR CONTENT WORKFLOW PIPELINE (CWP) + +#--Content Workflow Pipeline Mode +OPERATION_MODE=TEST + +#--Maximum Content Package File Size Limit in Bytes (50 MB) +MAX_CONTENT_PACKAGE_FILE_SIZE_LIMIT=52428800 + +#--Maximum Asset File Size Limit in Bytes (20 MB) +MAX_ASSET_FILE_SIZE_LIMIT=20971520 + +#--No of Retry While File Download Fails +RETRY_ASSET_DOWNLOAD_COUNT=1 + +#Google-vision-API +google.vision.tagging.enabled = false + +#Orchestrator env properties +env="https://dev.ekstep.in/api/learning" + +#Current environment +cloud_storage.env=dev + + +#Folder configuration +cloud_storage.content.folder=content +cloud_storage.asset.folder=assets +cloud_storage.artefact.folder=artifact +cloud_storage.bundle.folder=bundle +cloud_storage.media.folder=media +cloud_storage.ecar.folder=ecar_files + +# Media download configuration +content.media.base.url="https://dev.open-sunbird.org" +plugin.media.base.url="https://dev.open-sunbird.org" + +# Configuration +graph.dir=/data/testingGraphDB +akka.request_timeout=30 +environment.id=10000000 +graph.ids=["domain"] +graph.passport.key.base=31b6fd1c4d64e745c867e61a45edc34a +route.domain="bolt://localhost:7687" +route.bolt.write.domain="bolt://localhost:7687" +route.bolt.read.domain="bolt://localhost:7687" +route.bolt.comment.domain="bolt://localhost:7687" +route.all="bolt://localhost:7687" +route.bolt.write.all="bolt://localhost:7687" +route.bolt.read.all="bolt://localhost:7687" +route.bolt.comment.all="bolt://localhost:7687" + +shard.id=1 +platform.auth.check.enabled=false +platform.cache.ttl=3600000 + + +framework.max_term_creation_limit=200 + +# Enable Suggested Framework in Get Channel API. +channel.fetch.suggested_frameworks=true + + +#Top N Config for Search Telemetry +telemetry_env=dev +telemetry.search.topn=5 + +installation.id=ekstep + + +channel.default="in.ekstep" + + +# Language-Code Configuration +platform.language.codes=["as","bn","en","gu","hi","hoc","jun","ka","mai","mr","unx","or","san","sat","ta","te","urd", "pj"] + + +framework.categories_cached=["subject", "medium", "gradeLevel", "board"] +framework.cache.ttl=86400 +framework.cache.read=false + + +# Max size(width/height) of thumbnail in pixels +max.thumbnail.size.pixels=150 + +schema.base_path="../../schemas/" + +assessment.skip.validation=true +uestion.keyspace="dev_question_store" +questionset.keyspace="dev_hierarchy_store" +cassandra { + lp { + connection: "127.0.0.1:9042,127.0.0.1:9042,127.0.0.1:9042" + } + lpa { + connection: "127.0.0.1:9042" + } +} +questionset.keyspace = "dev_hierarchy_store" + +import { + request_size_limit = 200 + output_topic_name = "local.auto.creation.job.request" + required_props { + question = ["name", "code", "mimeType", "framework", "channel"] + questionset = ["name", "code", "mimeType", "framework", "channel"] + } + remove_props { + question = [] + questionset = [] + } +} + + + diff --git a/validate-api/validate-actors/src/test/scala/org/sunbird/actors/BaseSpec.scala b/validate-api/validate-actors/src/test/scala/org/sunbird/actors/BaseSpec.scala new file mode 100644 index 000000000..b1abb5a29 --- /dev/null +++ b/validate-api/validate-actors/src/test/scala/org/sunbird/actors/BaseSpec.scala @@ -0,0 +1,78 @@ +package org.sunbird.actors + +import java.util +import java.util.concurrent.TimeUnit + +import akka.actor.{ActorSystem, Props} +import akka.testkit.TestKit +import org.scalatest.{FlatSpec, Matchers} +import org.sunbird.common.dto.{Request, Response} +import org.sunbird.graph.OntologyEngineContext +import org.sunbird.graph.dac.model.Node + +import scala.concurrent.duration.FiniteDuration + +class BaseSpec extends FlatSpec with Matchers { + val system = ActorSystem.create("system") + + def testUnknownOperation(props: Props, request: Request)(implicit oec: OntologyEngineContext) = { + request.setOperation("unknown") + val response = callActor(request, props) + assert("failed".equals(response.getParams.getStatus)) + } + + def callActor(request: Request, props: Props): Response = { + val probe = new TestKit(system) + val actorRef = system.actorOf(props) + actorRef.tell(request, probe.testActor) + probe.expectMsgType[Response](FiniteDuration.apply(100, TimeUnit.SECONDS)) + } + + def getNode(objectType: String, metadata: Option[util.Map[String, AnyRef]]): Node = { + val node = new Node("domain", "DATA_NODE", objectType) + node.setGraphId("domain") + val nodeMetadata = metadata.getOrElse(new util.HashMap[String, AnyRef]() {{ + put("name", "Sunbird Node") + put("code", "sunbird-node") + put("status", "Draft") + }}) + node.setNodeType("DATA_NODE") + node.setMetadata(nodeMetadata) + node.setObjectType(objectType) + node.setIdentifier("test_id") + node + } + def getCategoryNode(): util.List[Node] = { + val node = new Node() + node.setIdentifier("board") + node.setNodeType("DATA_NODE") + node.setObjectType("Category") + node.setMetadata(new util.HashMap[String, AnyRef]() { + { + put("code", "board") + put("orgIdFieldName", "boardIds") + put("targetIdFieldName", "targetBoardIds") + put("searchIdFieldName", "se_boardIds") + put("searchLabelFieldName", "se_boards") + put("status", "Live") + } + }) + util.Arrays.asList(node) + } + + def getNode(identifier: String, objectType: String, metadata: Option[util.Map[String, AnyRef]]): Node = { + val node = new Node("domain", "DATA_NODE", objectType) + node.setGraphId("domain") + val nodeMetadata = metadata.getOrElse(new util.HashMap[String, AnyRef]() {{ + put("name", "Question 1") + put("code", "ques.1") + put("status", "Draft") + put("primaryCategory", "Multiple Choice Question") + }}) + node.setNodeType("DATA_NODE") + node.setMetadata(nodeMetadata) + node.setObjectType(objectType) + node.setIdentifier(identifier) + node + } +} diff --git a/validate-api/validate-hierarchy-manager/pom.xml b/validate-api/validate-hierarchy-manager/pom.xml new file mode 100644 index 000000000..05de0ff39 --- /dev/null +++ b/validate-api/validate-hierarchy-manager/pom.xml @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>validate-api</artifactId> + <groupId>org.sunbird</groupId> + <version>1.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>validate-hierarchy-manager</artifactId> + <version>1.0-SNAPSHOT</version> + + <dependencies> + <dependency> + <groupId>org.sunbird</groupId> + <artifactId>graph-engine_2.11</artifactId> + <version>1.0-SNAPSHOT</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.sunbird</groupId> + <artifactId>platform-common</artifactId> + <version>1.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.scala-lang</groupId> + <artifactId>scala-library</artifactId> + <version>${scala.version}</version> + </dependency> + <dependency> + <groupId>org.scalatest</groupId> + <artifactId>scalatest_${scala.maj.version}</artifactId> + <version>3.1.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.neo4j</groupId> + <artifactId>neo4j-bolt</artifactId> + <version>3.5.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.neo4j</groupId> + <artifactId>neo4j-graphdb-api</artifactId> + <version>3.5.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.neo4j</groupId> + <artifactId>neo4j</artifactId> + <version>3.5.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.cassandraunit</groupId> + <artifactId>cassandra-unit</artifactId> + <version>3.11.2.0</version> + <scope>test</scope> + <exclusions> + <exclusion> + <artifactId>httpcore</artifactId> + <groupId>org.apache.httpcomponents</groupId> + </exclusion> + <exclusion> + <artifactId>httpclient</artifactId> + <groupId>org.apache.httpcomponents</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.mashape.unirest</groupId> + <artifactId>unirest-java</artifactId> + <version>1.4.9</version> + </dependency> + </dependencies> + + + <build> + <sourceDirectory>src/main/scala</sourceDirectory> + <testSourceDirectory>src/test/scala</testSourceDirectory> + <plugins> + <plugin> + <groupId>net.alchim31.maven</groupId> + <artifactId>scala-maven-plugin</artifactId> + <version>4.4.0</version> + <configuration> + <scalaVersion>${scala.version}</scalaVersion> + <checkMultipleScalaVersions>false</checkMultipleScalaVersions> + </configuration> + <executions> + <execution> + <id>scala-compile-first</id> + <phase>process-resources</phase> + <goals> + <goal>add-source</goal> + <goal>compile</goal> + </goals> + </execution> + <execution> + <id>scala-test-compile</id> + <phase>process-test-resources</phase> + <goals> + <goal>testCompile</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.scalatest</groupId> + <artifactId>scalatest-maven-plugin</artifactId> + <version>2.0.0</version> + <executions> + <execution> + <id>test</id> + <phase>test</phase> + <goals> + <goal>test</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.scoverage</groupId> + <artifactId>scoverage-maven-plugin</artifactId> + <version>${scoverage.plugin.version}</version> + <configuration> + <scalaVersion>${scala.version}</scalaVersion> + <aggregate>true</aggregate> + <highlighting>true</highlighting> + </configuration> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file diff --git a/validate-api/validate-hierarchy-manager/src/test/resources/application.conf b/validate-api/validate-hierarchy-manager/src/test/resources/application.conf new file mode 100644 index 000000000..82fe873b5 --- /dev/null +++ b/validate-api/validate-hierarchy-manager/src/test/resources/application.conf @@ -0,0 +1,423 @@ +# This is the main configuration file for the application. +# https://www.playframework.com/documentation/latest/ConfigFile +# ~~~~~ +# Play uses HOCON as its configuration file format. HOCON has a number +# of advantages over other config formats, but there are two things that +# can be used when modifying settings. +# +# You can include other configuration files in this main application.conf file: +#include "extra-config.conf" +# +# You can declare variables and substitute for them: +#mykey = ${some.value} +# +# And if an environment variable exists when there is no other substitution, then +# HOCON will fall back to substituting environment variable: +#mykey = ${JAVA_HOME} + +## Akka +# https://www.playframework.com/documentation/latest/ScalaAkka#Configuration +# https://www.playframework.com/documentation/latest/JavaAkka#Configuration +# ~~~~~ +# Play uses Akka internally and exposes Akka Streams and actors in Websockets and +# other streaming HTTP responses. +akka { + # "akka.log-config-on-start" is extraordinarly useful because it log the complete + # configuration at INFO level, including defaults and overrides, so it s worth + # putting at the very top. + # + # Put the following in your conf/logback.xml file: + # + # <logger name="akka.actor" level="INFO" /> + # + # And then uncomment this line to debug the configuration. + # + #log-config-on-start = true + default-dispatcher { + # This will be used if you have set "executor = "fork-join-executor"" + fork-join-executor { + # Min number of threads to cap factor-based parallelism number to + parallelism-min = 8 + + # The parallelism factor is used to determine thread pool size using the + # following formula: ceil(available processors * factor). Resulting size + # is then bounded by the parallelism-min and parallelism-max values. + parallelism-factor = 32.0 + + # Max number of threads to cap factor-based parallelism number to + parallelism-max = 64 + + # Setting to "FIFO" to use queue like peeking mode which "poll" or "LIFO" to use stack + # like peeking mode which "pop". + task-peeking-mode = "FIFO" + } + } + actors-dispatcher { + type = "Dispatcher" + executor = "fork-join-executor" + fork-join-executor { + parallelism-min = 8 + parallelism-factor = 32.0 + parallelism-max = 64 + } + # Throughput for default Dispatcher, set to 1 for as fair as possible + throughput = 1 + } + actor { + deployment { + /healthActor + { + router = smallest-mailbox-pool + nr-of-instances = 5 + dispatcher = actors-dispatcher + } + /itemSetActor + { + router = smallest-mailbox-pool + nr-of-instances = 2 + dispatcher = actors-dispatcher + } + /questionActor + { + router = smallest-mailbox-pool + nr-of-instances = 5 + dispatcher = actors-dispatcher + } + /questionSetActor + { + router = smallest-mailbox-pool + nr-of-instances = 5 + dispatcher = actors-dispatcher + } + } + } +} + +## Secret key +# http://www.playframework.com/documentation/latest/ApplicationSecret +# ~~~~~ +# The secret key is used to sign Play's session cookie. +# This must be changed for production, but we don't recommend you change it in this file. +play.http.secret.key= a-long-secret-to-calm-the-rage-of-the-entropy-gods + +## Modules +# https://www.playframework.com/documentation/latest/Modules +# ~~~~~ +# Control which modules are loaded when Play starts. Note that modules are +# the replacement for "GlobalSettings", which are deprecated in 2.5.x. +# Please see https://www.playframework.com/documentation/latest/GlobalSettings +# for more information. +# +# You can also extend Play functionality by using one of the publically available +# Play modules: https://playframework.com/documentation/latest/ModuleDirectory +play.modules { + # By default, Play will load any class called Module that is defined + # in the root package (the "app" directory), or you can define them + # explicitly below. + # If there are any built-in modules that you want to enable, you can list them here. + #enabled += my.application.Module + + # If there are any built-in modules that you want to disable, you can list them here. + #disabled += "" + enabled += modules.AssessmentModule +} + +## IDE +# https://www.playframework.com/documentation/latest/IDE +# ~~~~~ +# Depending on your IDE, you can add a hyperlink for errors that will jump you +# directly to the code location in the IDE in dev mode. The following line makes +# use of the IntelliJ IDEA REST interface: +#play.editor="http://localhost:63342/api/file/?file=%s&line=%s" + +## Internationalisation +# https://www.playframework.com/documentation/latest/JavaI18N +# https://www.playframework.com/documentation/latest/ScalaI18N +# ~~~~~ +# Play comes with its own i18n settings, which allow the user's preferred language +# to map through to internal messages, or allow the language to be stored in a cookie. +play.i18n { + # The application languages + langs = [ "en" ] + + # Whether the language cookie should be secure or not + #langCookieSecure = true + + # Whether the HTTP only attribute of the cookie should be set to true + #langCookieHttpOnly = true +} + +## Play HTTP settings +# ~~~~~ +play.http { + ## Router + # https://www.playframework.com/documentation/latest/JavaRouting + # https://www.playframework.com/documentation/latest/ScalaRouting + # ~~~~~ + # Define the Router object to use for this application. + # This router will be looked up first when the application is starting up, + # so make sure this is the entry point. + # Furthermore, it's assumed your route file is named properly. + # So for an application router like `my.application.Router`, + # you may need to define a router file `conf/my.application.routes`. + # Default to Routes in the root package (aka "apps" folder) (and conf/routes) + #router = my.application.Router + + ## Action Creator + # https://www.playframework.com/documentation/latest/JavaActionCreator + # ~~~~~ + #actionCreator = null + + ## ErrorHandler + # https://www.playframework.com/documentation/latest/JavaRouting + # https://www.playframework.com/documentation/latest/ScalaRouting + # ~~~~~ + # If null, will attempt to load a class called ErrorHandler in the root package, + #errorHandler = null + + ## Session & Flash + # https://www.playframework.com/documentation/latest/JavaSessionFlash + # https://www.playframework.com/documentation/latest/ScalaSessionFlash + # ~~~~~ + session { + # Sets the cookie to be sent only over HTTPS. + #secure = true + + # Sets the cookie to be accessed only by the server. + #httpOnly = true + + # Sets the max-age field of the cookie to 5 minutes. + # NOTE: this only sets when the browser will discard the cookie. Play will consider any + # cookie value with a valid signature to be a valid session forever. To implement a server side session timeout, + # you need to put a timestamp in the session and check it at regular intervals to possibly expire it. + #maxAge = 300 + + # Sets the domain on the session cookie. + #domain = "example.com" + } + + flash { + # Sets the cookie to be sent only over HTTPS. + #secure = true + + # Sets the cookie to be accessed only by the server. + #httpOnly = true + } +} + +play.server.http.idleTimeout = 60s +play.http.parser.maxDiskBuffer = 10MB +parsers.anyContent.maxLength = 10MB + +## Netty Provider +# https://www.playframework.com/documentation/latest/SettingsNetty +# ~~~~~ +play.server.netty { + # Whether the Netty wire should be logged + log.wire = true + + # If you run Play on Linux, you can use Netty's native socket transport + # for higher performance with less garbage. + transport = "native" +} + +## WS (HTTP Client) +# https://www.playframework.com/documentation/latest/ScalaWS#Configuring-WS +# ~~~~~ +# The HTTP client primarily used for REST APIs. The default client can be +# configured directly, but you can also create different client instances +# with customized settings. You must enable this by adding to build.sbt: +# +# libraryDependencies += ws // or javaWs if using java +# +play.ws { + # Sets HTTP requests not to follow 302 requests + #followRedirects = false + + # Sets the maximum number of open HTTP connections for the client. + #ahc.maxConnectionsTotal = 50 + + ## WS SSL + # https://www.playframework.com/documentation/latest/WsSSL + # ~~~~~ + ssl { + # Configuring HTTPS with Play WS does not require programming. You can + # set up both trustManager and keyManager for mutual authentication, and + # turn on JSSE debugging in development with a reload. + #debug.handshake = true + #trustManager = { + # stores = [ + # { type = "JKS", path = "exampletrust.jks" } + # ] + #} + } +} + +## Cache +# https://www.playframework.com/documentation/latest/JavaCache +# https://www.playframework.com/documentation/latest/ScalaCache +# ~~~~~ +# Play comes with an integrated cache API that can reduce the operational +# overhead of repeated requests. You must enable this by adding to build.sbt: +# +# libraryDependencies += cache +# +play.cache { + # If you want to bind several caches, you can bind the individually + #bindCaches = ["db-cache", "user-cache", "session-cache"] +} + +## Filter Configuration +# https://www.playframework.com/documentation/latest/Filters +# ~~~~~ +# There are a number of built-in filters that can be enabled and configured +# to give Play greater security. +# +play.filters { + + # Enabled filters are run automatically against Play. + # CSRFFilter, AllowedHostFilters, and SecurityHeadersFilters are enabled by default. + enabled = [filters.AccessLogFilter] + + # Disabled filters remove elements from the enabled list. + # disabled += filters.CSRFFilter + + + ## CORS filter configuration + # https://www.playframework.com/documentation/latest/CorsFilter + # ~~~~~ + # CORS is a protocol that allows web applications to make requests from the browser + # across different domains. + # NOTE: You MUST apply the CORS configuration before the CSRF filter, as CSRF has + # dependencies on CORS settings. + cors { + # Filter paths by a whitelist of path prefixes + #pathPrefixes = ["/some/path", ...] + + # The allowed origins. If null, all origins are allowed. + #allowedOrigins = ["http://www.example.com"] + + # The allowed HTTP methods. If null, all methods are allowed + #allowedHttpMethods = ["GET", "POST"] + } + + ## Security headers filter configuration + # https://www.playframework.com/documentation/latest/SecurityHeaders + # ~~~~~ + # Defines security headers that prevent XSS attacks. + # If enabled, then all options are set to the below configuration by default: + headers { + # The X-Frame-Options header. If null, the header is not set. + #frameOptions = "DENY" + + # The X-XSS-Protection header. If null, the header is not set. + #xssProtection = "1; mode=block" + + # The X-Content-Type-Options header. If null, the header is not set. + #contentTypeOptions = "nosniff" + + # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set. + #permittedCrossDomainPolicies = "master-only" + + # The Content-Security-Policy header. If null, the header is not set. + #contentSecurityPolicy = "default-src 'self'" + } + + ## Allowed hosts filter configuration + # https://www.playframework.com/documentation/latest/AllowedHostsFilter + # ~~~~~ + # Play provides a filter that lets you configure which hosts can access your application. + # This is useful to prevent cache poisoning attacks. + hosts { + # Allow requests to example.com, its subdomains, and localhost:9000. + #allowed = [".example.com", "localhost:9000"] + } +} + +play.http.parser.maxMemoryBuffer = 50MB +akka.http.parsing.max-content-length = 50MB +schema.base_path="../../schemas/" + +# Cassandra Configuration +cassandra.lp.connection="127.0.0.1:9042" +content.keyspace = "content_store" + +# Redis Configuration +redis.host="localhost" +redis.port=6379 +redis.maxConnections=128 + +# Graph Configuration +graph.dir=/data/testingGraphDB +akka.request_timeout=30 +environment.id=10000000 +graph.ids=["domain"] +graph.passport.key.base=31b6fd1c4d64e745c867e61a45edc34a +route.domain="bolt://localhost:7687" +route.bolt.write.domain="bolt://localhost:7687" +route.bolt.read.domain="bolt://localhost:7687" +route.bolt.comment.domain="bolt://localhost:7687" +route.all="bolt://localhost:7687" +route.bolt.write.all="bolt://localhost:7687" +route.bolt.read.all="bolt://localhost:7687" +route.bolt.comment.all="bolt://localhost:7687" + +shard.id=1 +platform.auth.check.enabled=false +platform.cache.ttl=3600000 + +#Top N Config for Search Telemetry +telemetry_env=dev + +installation.id=ekstep + + +languageCode { + assamese : "as" + bengali : "bn" + english : "en" + gujarati : "gu" + hindi : "hi" + kannada : "ka" + marathi : "mr" + odia : "or" + tamil : "ta" + telugu : "te" +} + +kafka { + urls : "localhost:9092" + topic.send.enable : true + topics.instruction : "sunbirddev.assessment.publish.request" +} +objectcategorydefinition.keyspace="category_store" +question { + keyspace = "question_store" + list.limit=20 +} +questionset.keyspace="hierarchy_store" + +cassandra { + lp { + connection: "localhost:9042" + } + lpa { + connection: "localhost:9042" + } +} +neo4j_objecttypes_enabled=["Question"] + +import { + request_size_limit = 200 + output_topic_name = "local.auto.creation.job.request" + required_props { + question = ["name", "code", "mimeType", "framework", "channel"] + questionset = ["name", "code", "mimeType", "framework", "channel"] + } + remove_props { + question = [] + questionset = [] + } +} + +root_node_visibility=["Default","Private"] \ No newline at end of file diff --git a/validate-api/validate-hierarchy-manager/src/test/resources/cassandra-unit.yaml b/validate-api/validate-hierarchy-manager/src/test/resources/cassandra-unit.yaml new file mode 100755 index 000000000..a965a8fe5 --- /dev/null +++ b/validate-api/validate-hierarchy-manager/src/test/resources/cassandra-unit.yaml @@ -0,0 +1,590 @@ +# Cassandra storage config YAML + +# NOTE: +# See http://wiki.apache.org/cassandra/StorageConfiguration for +# full explanations of configuration directives +# /NOTE + +# The name of the cluster. This is mainly used to prevent machines in +# one logical cluster from joining another. +cluster_name: 'Test Cluster' + +# You should always specify InitialToken when setting up a production +# cluster for the first time, and often when adding capacity later. +# The principle is that each node should be given an equal slice of +# the token ring; see http://wiki.apache.org/cassandra/Operations +# for more details. +# +# If blank, Cassandra will request a token bisecting the range of +# the heaviest-loaded existing node. If there is no load information +# available, such as is the case with a new cluster, it will pick +# a random token, which will lead to hot spots. +#initial_token: + +# See http://wiki.apache.org/cassandra/HintedHandoff +hinted_handoff_enabled: true +# this defines the maximum amount of time a dead host will have hints +# generated. After it has been dead this long, new hints for it will not be +# created until it has been seen alive and gone down again. +max_hint_window_in_ms: 10800000 # 3 hours +# Maximum throttle in KBs per second, per delivery thread. This will be +# reduced proportionally to the number of nodes in the cluster. (If there +# are two nodes in the cluster, each delivery thread will use the maximum +# rate; if there are three, each will throttle to half of the maximum, +# since we expect two nodes to be delivering hints simultaneously.) +hinted_handoff_throttle_in_kb: 1024 +# Number of threads with which to deliver hints; +# Consider increasing this number when you have multi-dc deployments, since +# cross-dc handoff tends to be slower +max_hints_delivery_threads: 2 + +hints_directory: target/embeddedCassandra/hints + +# The following setting populates the page cache on memtable flush and compaction +# WARNING: Enable this setting only when the whole node's data fits in memory. +# Defaults to: false +# populate_io_cache_on_flush: false + +# Authentication backend, implementing IAuthenticator; used to identify users +# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthenticator, +# PasswordAuthenticator}. +# +# - AllowAllAuthenticator performs no checks - set it to disable authentication. +# - PasswordAuthenticator relies on username/password pairs to authenticate +# users. It keeps usernames and hashed passwords in system_auth.credentials table. +# Please increase system_auth keyspace replication factor if you use this authenticator. +authenticator: AllowAllAuthenticator + +# Authorization backend, implementing IAuthorizer; used to limit access/provide permissions +# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthorizer, +# CassandraAuthorizer}. +# +# - AllowAllAuthorizer allows any action to any user - set it to disable authorization. +# - CassandraAuthorizer stores permissions in system_auth.permissions table. Please +# increase system_auth keyspace replication factor if you use this authorizer. +authorizer: AllowAllAuthorizer + +# Validity period for permissions cache (fetching permissions can be an +# expensive operation depending on the authorizer, CassandraAuthorizer is +# one example). Defaults to 2000, set to 0 to disable. +# Will be disabled automatically for AllowAllAuthorizer. +permissions_validity_in_ms: 2000 + + +# The partitioner is responsible for distributing rows (by key) across +# nodes in the cluster. Any IPartitioner may be used, including your +# own as long as it is on the classpath. Out of the box, Cassandra +# provides org.apache.cassandra.dht.{Murmur3Partitioner, RandomPartitioner +# ByteOrderedPartitioner, OrderPreservingPartitioner (deprecated)}. +# +# - RandomPartitioner distributes rows across the cluster evenly by md5. +# This is the default prior to 1.2 and is retained for compatibility. +# - Murmur3Partitioner is similar to RandomPartioner but uses Murmur3_128 +# Hash Function instead of md5. When in doubt, this is the best option. +# - ByteOrderedPartitioner orders rows lexically by key bytes. BOP allows +# scanning rows in key order, but the ordering can generate hot spots +# for sequential insertion workloads. +# - OrderPreservingPartitioner is an obsolete form of BOP, that stores +# - keys in a less-efficient format and only works with keys that are +# UTF8-encoded Strings. +# - CollatingOPP collates according to EN,US rules rather than lexical byte +# ordering. Use this as an example if you need custom collation. +# +# See http://wiki.apache.org/cassandra/Operations for more on +# partitioners and token selection. +partitioner: org.apache.cassandra.dht.Murmur3Partitioner + +# directories where Cassandra should store data on disk. +data_file_directories: + - target/embeddedCassandra/data + +# commit log +commitlog_directory: target/embeddedCassandra/commitlog + +cdc_raw_directory: target/embeddedCassandra/cdc + +# policy for data disk failures: +# stop: shut down gossip and Thrift, leaving the node effectively dead, but +# can still be inspected via JMX. +# best_effort: stop using the failed disk and respond to requests based on +# remaining available sstables. This means you WILL see obsolete +# data at CL.ONE! +# ignore: ignore fatal errors and let requests fail, as in pre-1.2 Cassandra +disk_failure_policy: stop + + +# Maximum size of the key cache in memory. +# +# Each key cache hit saves 1 seek and each row cache hit saves 2 seeks at the +# minimum, sometimes more. The key cache is fairly tiny for the amount of +# time it saves, so it's worthwhile to use it at large numbers. +# The row cache saves even more time, but must store the whole values of +# its rows, so it is extremely space-intensive. It's best to only use the +# row cache if you have hot rows or static rows. +# +# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup. +# +# Default value is empty to make it "auto" (min(5% of Heap (in MB), 100MB)). Set to 0 to disable key cache. +key_cache_size_in_mb: + +# Duration in seconds after which Cassandra should +# safe the keys cache. Caches are saved to saved_caches_directory as +# specified in this configuration file. +# +# Saved caches greatly improve cold-start speeds, and is relatively cheap in +# terms of I/O for the key cache. Row cache saving is much more expensive and +# has limited use. +# +# Default is 14400 or 4 hours. +key_cache_save_period: 14400 + +# Number of keys from the key cache to save +# Disabled by default, meaning all keys are going to be saved +# key_cache_keys_to_save: 100 + +# Maximum size of the row cache in memory. +# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup. +# +# Default value is 0, to disable row caching. +row_cache_size_in_mb: 0 + +# Duration in seconds after which Cassandra should +# safe the row cache. Caches are saved to saved_caches_directory as specified +# in this configuration file. +# +# Saved caches greatly improve cold-start speeds, and is relatively cheap in +# terms of I/O for the key cache. Row cache saving is much more expensive and +# has limited use. +# +# Default is 0 to disable saving the row cache. +row_cache_save_period: 0 + +# Number of keys from the row cache to save +# Disabled by default, meaning all keys are going to be saved +# row_cache_keys_to_save: 100 + +# saved caches +saved_caches_directory: target/embeddedCassandra/saved_caches + +# commitlog_sync may be either "periodic" or "batch." +# When in batch mode, Cassandra won't ack writes until the commit log +# has been fsynced to disk. It will wait up to +# commitlog_sync_batch_window_in_ms milliseconds for other writes, before +# performing the sync. +# +# commitlog_sync: batch +# commitlog_sync_batch_window_in_ms: 50 +# +# the other option is "periodic" where writes may be acked immediately +# and the CommitLog is simply synced every commitlog_sync_period_in_ms +# milliseconds. +commitlog_sync: periodic +commitlog_sync_period_in_ms: 10000 + +# The size of the individual commitlog file segments. A commitlog +# segment may be archived, deleted, or recycled once all the data +# in it (potentially from each columnfamily in the system) has been +# flushed to sstables. +# +# The default size is 32, which is almost always fine, but if you are +# archiving commitlog segments (see commitlog_archiving.properties), +# then you probably want a finer granularity of archiving; 8 or 16 MB +# is reasonable. +commitlog_segment_size_in_mb: 32 + +# any class that implements the SeedProvider interface and has a +# constructor that takes a Map<String, String> of parameters will do. +seed_provider: + # Addresses of hosts that are deemed contact points. + # Cassandra nodes use this list of hosts to find each other and learn + # the topology of the ring. You must change this if you are running + # multiple nodes! + - class_name: org.apache.cassandra.locator.SimpleSeedProvider + parameters: + # seeds is actually a comma-delimited list of addresses. + # Ex: "<ip1>,<ip2>,<ip3>" + - seeds: "127.0.0.1" + + +# For workloads with more data than can fit in memory, Cassandra's +# bottleneck will be reads that need to fetch data from +# disk. "concurrent_reads" should be set to (16 * number_of_drives) in +# order to allow the operations to enqueue low enough in the stack +# that the OS and drives can reorder them. +# +# On the other hand, since writes are almost never IO bound, the ideal +# number of "concurrent_writes" is dependent on the number of cores in +# your system; (8 * number_of_cores) is a good rule of thumb. +concurrent_reads: 32 +concurrent_writes: 32 + +# Total memory to use for memtables. Cassandra will flush the largest +# memtable when this much memory is used. +# If omitted, Cassandra will set it to 1/3 of the heap. +# memtable_total_space_in_mb: 2048 + +# Total space to use for commitlogs. +# If space gets above this value (it will round up to the next nearest +# segment multiple), Cassandra will flush every dirty CF in the oldest +# segment and remove it. +# commitlog_total_space_in_mb: 4096 + +# This sets the amount of memtable flush writer threads. These will +# be blocked by disk io, and each one will hold a memtable in memory +# while blocked. If you have a large heap and many data directories, +# you can increase this value for better flush performance. +# By default this will be set to the amount of data directories defined. +#memtable_flush_writers: 1 + +# the number of full memtables to allow pending flush, that is, +# waiting for a writer thread. At a minimum, this should be set to +# the maximum number of secondary indexes created on a single CF. +#memtable_flush_queue_size: 4 + +# Whether to, when doing sequential writing, fsync() at intervals in +# order to force the operating system to flush the dirty +# buffers. Enable this to avoid sudden dirty buffer flushing from +# impacting read latencies. Almost always a good idea on SSD:s; not +# necessarily on platters. +trickle_fsync: false +trickle_fsync_interval_in_kb: 10240 + +# TCP port, for commands and data +storage_port: 0 + +# SSL port, for encrypted communication. Unused unless enabled in +# encryption_options +ssl_storage_port: 7011 + +# Address to bind to and tell other Cassandra nodes to connect to. You +# _must_ change this if you want multiple nodes to be able to +# communicate! +# +# Leaving it blank leaves it up to InetAddress.getLocalHost(). This +# will always do the Right Thing *if* the node is properly configured +# (hostname, name resolution, etc), and the Right Thing is to use the +# address associated with the hostname (it might not be). +# +# Setting this to 0.0.0.0 is always wrong. +listen_address: 127.0.0.1 + +start_native_transport: true +# port for the CQL native transport to listen for clients on +native_transport_port: 9042 + +# Whether to start the thrift rpc server. +start_rpc: true + +# Address to broadcast to other Cassandra nodes +# Leaving this blank will set it to the same value as listen_address +# broadcast_address: 1.2.3.4 + +# The address to bind the Thrift RPC service to -- clients connect +# here. Unlike ListenAddress above, you *can* specify 0.0.0.0 here if +# you want Thrift to listen on all interfaces. +# +# Leaving this blank has the same effect it does for ListenAddress, +# (i.e. it will be based on the configured hostname of the node). +rpc_address: localhost +# port for Thrift to listen for clients on +rpc_port: 0 + +# enable or disable keepalive on rpc connections +rpc_keepalive: true + +# Cassandra provides three options for the RPC Server: +# +# sync -> One connection per thread in the rpc pool (see below). +# For a very large number of clients, memory will be your limiting +# factor; on a 64 bit JVM, 128KB is the minimum stack size per thread. +# Connection pooling is very, very strongly recommended. +# +# async -> Nonblocking server implementation with one thread to serve +# rpc connections. This is not recommended for high throughput use +# cases. Async has been tested to be about 50% slower than sync +# or hsha and is deprecated: it will be removed in the next major release. +# +# hsha -> Stands for "half synchronous, half asynchronous." The rpc thread pool +# (see below) is used to manage requests, but the threads are multiplexed +# across the different clients. +# +# The default is sync because on Windows hsha is about 30% slower. On Linux, +# sync/hsha performance is about the same, with hsha of course using less memory. +rpc_server_type: sync + +# Uncomment rpc_min|max|thread to set request pool size. +# You would primarily set max for the sync server to safeguard against +# misbehaved clients; if you do hit the max, Cassandra will block until one +# disconnects before accepting more. The defaults for sync are min of 16 and max +# unlimited. +# +# For the Hsha server, the min and max both default to quadruple the number of +# CPU cores. +# +# This configuration is ignored by the async server. +# +# rpc_min_threads: 16 +# rpc_max_threads: 2048 + +# uncomment to set socket buffer sizes on rpc connections +# rpc_send_buff_size_in_bytes: +# rpc_recv_buff_size_in_bytes: + +# Frame size for thrift (maximum field length). +# 0 disables TFramedTransport in favor of TSocket. This option +# is deprecated; we strongly recommend using Framed mode. +thrift_framed_transport_size_in_mb: 15 + +# The max length of a thrift message, including all fields and +# internal thrift overhead. +thrift_max_message_length_in_mb: 16 + +# Set to true to have Cassandra create a hard link to each sstable +# flushed or streamed locally in a backups/ subdirectory of the +# Keyspace data. Removing these links is the operator's +# responsibility. +incremental_backups: false + +# Whether or not to take a snapshot before each compaction. Be +# careful using this option, since Cassandra won't clean up the +# snapshots for you. Mostly useful if you're paranoid when there +# is a data format change. +snapshot_before_compaction: false + +# Whether or not a snapshot is taken of the data before keyspace truncation +# or dropping of column families. The STRONGLY advised default of true +# should be used to provide data safety. If you set this flag to false, you will +# lose data on truncation or drop. +auto_snapshot: false + +# Add column indexes to a row after its contents reach this size. +# Increase if your column values are large, or if you have a very large +# number of columns. The competing causes are, Cassandra has to +# deserialize this much of the row to read a single column, so you want +# it to be small - at least if you do many partial-row reads - but all +# the index data is read for each access, so you don't want to generate +# that wastefully either. +column_index_size_in_kb: 64 + +# Size limit for rows being compacted in memory. Larger rows will spill +# over to disk and use a slower two-pass compaction process. A message +# will be logged specifying the row key. +#in_memory_compaction_limit_in_mb: 64 + +# Number of simultaneous compactions to allow, NOT including +# validation "compactions" for anti-entropy repair. Simultaneous +# compactions can help preserve read performance in a mixed read/write +# workload, by mitigating the tendency of small sstables to accumulate +# during a single long running compactions. The default is usually +# fine and if you experience problems with compaction running too +# slowly or too fast, you should look at +# compaction_throughput_mb_per_sec first. +# +# This setting has no effect on LeveledCompactionStrategy. +# +# concurrent_compactors defaults to the number of cores. +# Uncomment to make compaction mono-threaded, the pre-0.8 default. +#concurrent_compactors: 1 + +# Multi-threaded compaction. When enabled, each compaction will use +# up to one thread per core, plus one thread per sstable being merged. +# This is usually only useful for SSD-based hardware: otherwise, +# your concern is usually to get compaction to do LESS i/o (see: +# compaction_throughput_mb_per_sec), not more. +#multithreaded_compaction: false + +# Throttles compaction to the given total throughput across the entire +# system. The faster you insert data, the faster you need to compact in +# order to keep the sstable count down, but in general, setting this to +# 16 to 32 times the rate you are inserting data is more than sufficient. +# Setting this to 0 disables throttling. Note that this account for all types +# of compaction, including validation compaction. +compaction_throughput_mb_per_sec: 16 + +# Track cached row keys during compaction, and re-cache their new +# positions in the compacted sstable. Disable if you use really large +# key caches. +#compaction_preheat_key_cache: true + +# Throttles all outbound streaming file transfers on this node to the +# given total throughput in Mbps. This is necessary because Cassandra does +# mostly sequential IO when streaming data during bootstrap or repair, which +# can lead to saturating the network connection and degrading rpc performance. +# When unset, the default is 200 Mbps or 25 MB/s. +# stream_throughput_outbound_megabits_per_sec: 200 + +# How long the coordinator should wait for read operations to complete +read_request_timeout_in_ms: 5000 +# How long the coordinator should wait for seq or index scans to complete +range_request_timeout_in_ms: 10000 +# How long the coordinator should wait for writes to complete +write_request_timeout_in_ms: 2000 +# How long a coordinator should continue to retry a CAS operation +# that contends with other proposals for the same row +cas_contention_timeout_in_ms: 1000 +# How long the coordinator should wait for truncates to complete +# (This can be much longer, because unless auto_snapshot is disabled +# we need to flush first so we can snapshot before removing the data.) +truncate_request_timeout_in_ms: 60000 +# The default timeout for other, miscellaneous operations +request_timeout_in_ms: 10000 + +# Enable operation timeout information exchange between nodes to accurately +# measure request timeouts. If disabled, replicas will assume that requests +# were forwarded to them instantly by the coordinator, which means that +# under overload conditions we will waste that much extra time processing +# already-timed-out requests. +# +# Warning: before enabling this property make sure to ntp is installed +# and the times are synchronized between the nodes. +cross_node_timeout: false + +# Enable socket timeout for streaming operation. +# When a timeout occurs during streaming, streaming is retried from the start +# of the current file. This _can_ involve re-streaming an important amount of +# data, so you should avoid setting the value too low. +# Default value is 0, which never timeout streams. +# streaming_socket_timeout_in_ms: 0 + +# phi value that must be reached for a host to be marked down. +# most users should never need to adjust this. +# phi_convict_threshold: 8 + +# endpoint_snitch -- Set this to a class that implements +# IEndpointSnitch. The snitch has two functions: +# - it teaches Cassandra enough about your network topology to route +# requests efficiently +# - it allows Cassandra to spread replicas around your cluster to avoid +# correlated failures. It does this by grouping machines into +# "datacenters" and "racks." Cassandra will do its best not to have +# more than one replica on the same "rack" (which may not actually +# be a physical location) +# +# IF YOU CHANGE THE SNITCH AFTER DATA IS INSERTED INTO THE CLUSTER, +# YOU MUST RUN A FULL REPAIR, SINCE THE SNITCH AFFECTS WHERE REPLICAS +# ARE PLACED. +# +# Out of the box, Cassandra provides +# - SimpleSnitch: +# Treats Strategy order as proximity. This improves cache locality +# when disabling read repair, which can further improve throughput. +# Only appropriate for single-datacenter deployments. +# - PropertyFileSnitch: +# Proximity is determined by rack and data center, which are +# explicitly configured in cassandra-topology.properties. +# - RackInferringSnitch: +# Proximity is determined by rack and data center, which are +# assumed to correspond to the 3rd and 2nd octet of each node's +# IP address, respectively. Unless this happens to match your +# deployment conventions (as it did Facebook's), this is best used +# as an example of writing a custom Snitch class. +# - Ec2Snitch: +# Appropriate for EC2 deployments in a single Region. Loads Region +# and Availability Zone information from the EC2 API. The Region is +# treated as the Datacenter, and the Availability Zone as the rack. +# Only private IPs are used, so this will not work across multiple +# Regions. +# - Ec2MultiRegionSnitch: +# Uses public IPs as broadcast_address to allow cross-region +# connectivity. (Thus, you should set seed addresses to the public +# IP as well.) You will need to open the storage_port or +# ssl_storage_port on the public IP firewall. (For intra-Region +# traffic, Cassandra will switch to the private IP after +# establishing a connection.) +# +# You can use a custom Snitch by setting this to the full class name +# of the snitch, which will be assumed to be on your classpath. +endpoint_snitch: SimpleSnitch + +# controls how often to perform the more expensive part of host score +# calculation +dynamic_snitch_update_interval_in_ms: 100 +# controls how often to reset all host scores, allowing a bad host to +# possibly recover +dynamic_snitch_reset_interval_in_ms: 600000 +# if set greater than zero and read_repair_chance is < 1.0, this will allow +# 'pinning' of replicas to hosts in order to increase cache capacity. +# The badness threshold will control how much worse the pinned host has to be +# before the dynamic snitch will prefer other replicas over it. This is +# expressed as a double which represents a percentage. Thus, a value of +# 0.2 means Cassandra would continue to prefer the static snitch values +# until the pinned host was 20% worse than the fastest. +dynamic_snitch_badness_threshold: 0.1 + +# request_scheduler -- Set this to a class that implements +# RequestScheduler, which will schedule incoming client requests +# according to the specific policy. This is useful for multi-tenancy +# with a single Cassandra cluster. +# NOTE: This is specifically for requests from the client and does +# not affect inter node communication. +# org.apache.cassandra.scheduler.NoScheduler - No scheduling takes place +# org.apache.cassandra.scheduler.RoundRobinScheduler - Round robin of +# client requests to a node with a separate queue for each +# request_scheduler_id. The scheduler is further customized by +# request_scheduler_options as described below. +request_scheduler: org.apache.cassandra.scheduler.NoScheduler + +# Scheduler Options vary based on the type of scheduler +# NoScheduler - Has no options +# RoundRobin +# - throttle_limit -- The throttle_limit is the number of in-flight +# requests per client. Requests beyond +# that limit are queued up until +# running requests can complete. +# The value of 80 here is twice the number of +# concurrent_reads + concurrent_writes. +# - default_weight -- default_weight is optional and allows for +# overriding the default which is 1. +# - weights -- Weights are optional and will default to 1 or the +# overridden default_weight. The weight translates into how +# many requests are handled during each turn of the +# RoundRobin, based on the scheduler id. +# +# request_scheduler_options: +# throttle_limit: 80 +# default_weight: 5 +# weights: +# Keyspace1: 1 +# Keyspace2: 5 + +# request_scheduler_id -- An identifer based on which to perform +# the request scheduling. Currently the only valid option is keyspace. +# request_scheduler_id: keyspace + +# index_interval controls the sampling of entries from the primrary +# row index in terms of space versus time. The larger the interval, +# the smaller and less effective the sampling will be. In technicial +# terms, the interval coresponds to the number of index entries that +# are skipped between taking each sample. All the sampled entries +# must fit in memory. Generally, a value between 128 and 512 here +# coupled with a large key cache size on CFs results in the best trade +# offs. This value is not often changed, however if you have many +# very small rows (many to an OS page), then increasing this will +# often lower memory usage without a impact on performance. +index_interval: 128 + +# Enable or disable inter-node encryption +# Default settings are TLS v1, RSA 1024-bit keys (it is imperative that +# users generate their own keys) TLS_RSA_WITH_AES_128_CBC_SHA as the cipher +# suite for authentication, key exchange and encryption of the actual data transfers. +# NOTE: No custom encryption options are enabled at the moment +# The available internode options are : all, none, dc, rack +# +# If set to dc cassandra will encrypt the traffic between the DCs +# If set to rack cassandra will encrypt the traffic between the racks +# +# The passwords used in these options must match the passwords used when generating +# the keystore and truststore. For instructions on generating these files, see: +# http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#CreateKeystore +# +encryption_options: + internode_encryption: none + keystore: conf/.keystore + keystore_password: cassandra + truststore: conf/.truststore + truststore_password: cassandra + # More advanced defaults below: + # protocol: TLS + # algorithm: SunX509 + # store_type: JKS + # cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA] \ No newline at end of file diff --git a/validate-api/validate-hierarchy-manager/src/test/resources/logback.xml b/validate-api/validate-hierarchy-manager/src/test/resources/logback.xml new file mode 100644 index 000000000..73529d622 --- /dev/null +++ b/validate-api/validate-hierarchy-manager/src/test/resources/logback.xml @@ -0,0 +1,28 @@ +<configuration> + + <conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" /> + + <!-- transaction-event-trigger START --> + <timestamp key="timestamp" datePattern="yyyy-MM-dd"/> + <!-- common transactions logs --> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>%d %msg%n</pattern> + </encoder> + </appender> + + <appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender"> + <appender-ref ref="STDOUT" /> + </appender> + + + <logger name="play" level="INFO" /> + <logger name="DefaultPlatformLogger" level="INFO" /> + <!-- Telemetry Loggers--> + <logger name="TelemetryEventLogger" level="INFO" /> + + <root level="INFO"> + <appender-ref ref="ASYNCSTDOUT" /> + </root> + +</configuration> \ No newline at end of file diff --git a/validate-api/validate-hierarchy-manager/src/test/scala/org/sunbird/managers/BaseSpec.scala b/validate-api/validate-hierarchy-manager/src/test/scala/org/sunbird/managers/BaseSpec.scala new file mode 100644 index 000000000..01bad4b13 --- /dev/null +++ b/validate-api/validate-hierarchy-manager/src/test/scala/org/sunbird/managers/BaseSpec.scala @@ -0,0 +1,101 @@ +package org.sunbird.managers + +import java.io.{File, IOException} + +import com.datastax.driver.core.{ResultSet, Session} +import org.apache.commons.io.FileUtils +import org.cassandraunit.utils.EmbeddedCassandraServerHelper +import org.neo4j.graphdb.GraphDatabaseService +import org.neo4j.graphdb.factory.GraphDatabaseFactory +import org.neo4j.graphdb.factory.GraphDatabaseSettings.Connector.ConnectorType +import org.neo4j.kernel.configuration.BoltConnector +import org.scalatest.{AsyncFlatSpec, BeforeAndAfterAll, BeforeAndAfterEach, Matchers} +import org.sunbird.cassandra.CassandraConnector +import org.sunbird.common.Platform + +class BaseSpec extends AsyncFlatSpec with Matchers with BeforeAndAfterAll with BeforeAndAfterEach{ + + var graphDb: GraphDatabaseService = null + var session: Session = null + + def setUpEmbeddedNeo4j(): Unit = { + if(null == graphDb) { + val bolt: BoltConnector = new BoltConnector("0") + graphDb = new GraphDatabaseFactory() + .newEmbeddedDatabaseBuilder(new File(Platform.config.getString("graph.dir"))) + .setConfig(bolt.`type`, ConnectorType.BOLT.name()) + .setConfig(bolt.enabled, "true").setConfig(bolt.listen_address, "localhost:7687").newGraphDatabase + registerShutdownHook(graphDb) + } + } + + private def registerShutdownHook(graphDb: GraphDatabaseService): Unit = { + Runtime.getRuntime.addShutdownHook(new Thread() { + override def run(): Unit = { + try { + tearEmbeddedNeo4JSetup + } catch { + case e: Exception => + e.printStackTrace() + } + } + }) + } + + + @throws[Exception] + private def tearEmbeddedNeo4JSetup(): Unit = { + if (null != graphDb) graphDb.shutdown + Thread.sleep(2000) + deleteEmbeddedNeo4j(new File(Platform.config.getString("graph.dir"))) + } + + private def deleteEmbeddedNeo4j(emDb: File): Unit = { + try{ + FileUtils.deleteDirectory(emDb) + }catch{ + case e: Exception => + e.printStackTrace() + } + } + + + def setUpEmbeddedCassandra(): Unit = { + System.setProperty("cassandra.unsafesystem", "true") + EmbeddedCassandraServerHelper.startEmbeddedCassandra("/cassandra-unit.yaml", 100000L) + } + + override def beforeAll(): Unit = { + tearEmbeddedNeo4JSetup() + setUpEmbeddedNeo4j() + setUpEmbeddedCassandra() + } + + override def afterAll(): Unit = { + tearEmbeddedNeo4JSetup() + if(null != session && !session.isClosed) + session.close() + EmbeddedCassandraServerHelper.cleanEmbeddedCassandra() + } + + + def executeCassandraQuery(queries: String*): Unit = { + if(null == session || session.isClosed){ + session = CassandraConnector.getSession + } + for(query <- queries) { + session.execute(query) + } + } + + def readFromCassandra(query: String) : ResultSet = { + if(null == session || session.isClosed){ + session = CassandraConnector.getSession + } + session.execute(query) + } + + def createRelationData(): Unit = { + graphDb.execute("UNWIND [{identifier:\"Num:C3:SC2\",code:\"Num:C3:SC2\",keywords:[\"Subconcept\",\"Class 3\"],IL_SYS_NODE_TYPE:\"DATA_NODE\",subject:\"numeracy\",channel:\"in.ekstep\",description:\"Multiplication\",versionKey:\"1484389136575\",gradeLevel:[\"Grade 3\",\"Grade 4\"],IL_FUNC_OBJECT_TYPE:\"Concept\",name:\"Multiplication\",lastUpdatedOn:\"2016-06-15T17:15:45.951+0000\",IL_UNIQUE_ID:\"Num:C3:SC2\",status:\"Live\"}, {code:\"31d521da-61de-4220-9277-21ca7ce8335c\",previewUrl:\"https://ekstep-public-dev.s3-ap-south-1.amazonaws.com/assets/do_11232724509261824014/object-oriented-javascript.pdf\",downloadUrl:\"https://ekstep-public-dev.s3-ap-south-1.amazonaws.com/ecar_files/do_11232724509261824014/untitled-content_1504790847410_do_11232724509261824014_2.0.ecar\",channel:\"in.ekstep\",language:[\"English\"],variants:\"{\\\"spine\\\":{\\\"ecarUrl\\\":\\\"https://ekstep-public-dev.s3-ap-south-1.amazonaws.com/ecar_files/do_11232724509261824014/untitled-content_1504790848197_do_11232724509261824014_2.0_spine.ecar\\\",\\\"size\\\":890.0}}\",mimeType:\"application/pdf\",streamingUrl:\"https://ekstep-public-dev.s3-ap-south-1.amazonaws.com/assets/do_11232724509261824014/object-oriented-javascript.pdf\",idealScreenSize:\"normal\",createdOn:\"2017-09-07T13:24:20.720+0000\",contentDisposition:\"inline\",artifactUrl:\"https://ekstep-public-dev.s3-ap-south-1.amazonaws.com/assets/do_11232724509261824014/object-oriented-javascript.pdf\",contentEncoding:\"identity\",lastUpdatedOn:\"2017-09-07T13:25:53.595+0000\",SYS_INTERNAL_LAST_UPDATED_ON:\"2017-09-07T13:27:28.417+0000\",contentType:\"Resource\",lastUpdatedBy:\"Ekstep\",audience:[\"Student\"],visibility:\"Default\",os:[\"All\"],IL_SYS_NODE_TYPE:\"DATA_NODE\",consumerId:\"e84015d2-a541-4c07-a53f-e31d4553312b\",mediaType:\"content\",osId:\"org.ekstep.quiz.app\",lastPublishedBy:\"Ekstep\",pkgVersion:2,versionKey:\"1504790848417\",license:\"Creative Commons Attribution (CC BY)\",idealScreenDensity:\"hdpi\",s3Key:\"ecar_files/do_11232724509261824014/untitled-content_1504790847410_do_11232724509261824014_2.0.ecar\",size:4864851,lastPublishedOn:\"2017-09-07T13:27:27.410+0000\",createdBy:\"390\",compatibilityLevel:4,IL_FUNC_OBJECT_TYPE:\"Content\",name:\"Untitled Content\",publisher:\"EkStep\",IL_UNIQUE_ID:\"do_11232724509261824014\",status:\"Live\",resourceType:[\"Study material\"]}] as row CREATE (n:domain) SET n += row") + } +} diff --git a/validate-api/validate-service/app/controllers/BaseController.scala b/validate-api/validate-service/app/controllers/BaseController.scala new file mode 100644 index 000000000..a3b47974b --- /dev/null +++ b/validate-api/validate-service/app/controllers/BaseController.scala @@ -0,0 +1,73 @@ +package controllers + +import java.util.UUID + +import akka.actor.ActorRef +import akka.pattern.Patterns +import org.sunbird.common.DateUtils +import org.sunbird.common.dto.{Response, ResponseHandler} +import org.sunbird.common.exception.ResponseCode +import play.api.mvc._ +import utils.JavaJsonUtils + +import collection.JavaConverters._ +import scala.concurrent.{ExecutionContext, Future} + +abstract class BaseController(protected val cc: ControllerComponents)(implicit exec: ExecutionContext) extends AbstractController(cc) { + + def requestBody()(implicit request: Request[AnyContent]) = { + val body = request.body.asJson.getOrElse("{}").toString + JavaJsonUtils.deserialize[java.util.Map[String, Object]](body).getOrDefault("request", new java.util.HashMap()).asInstanceOf[java.util.Map[String, Object]] + } + + def commonHeaders()(implicit request: Request[AnyContent]): java.util.Map[String, Object] = { + val customHeaders = Map("x-channel-id" -> "channel", "X-Consumer-ID" -> "consumerId", "X-App-Id" -> "appId") + customHeaders.map(ch => { + val value = request.headers.get(ch._1) + if (value.isDefined && !value.isEmpty) { + collection.mutable.HashMap[String, Object](ch._2 -> value.get).asJava + } else { + collection.mutable.HashMap[String, Object]().asJava + } + }).reduce((a, b) => { + a.putAll(b) + return a + }) + } + + def getRequest(input: java.util.Map[String, AnyRef], context: java.util.Map[String, AnyRef], operation: String): org.sunbird.common.dto.Request = { + new org.sunbird.common.dto.Request(context, input, operation, null); + } + + def getResult(apiId: String, actor: ActorRef, request: org.sunbird.common.dto.Request) : Future[Result] = { + val future = Patterns.ask(actor, request, 30000) recoverWith {case e: Exception => Future(ResponseHandler.getErrorResponse(e))} + future.map(f => { + val result = f.asInstanceOf[Response] + result.setId(apiId) + setResponseEnvelope(result) + val response = JavaJsonUtils.serialize(result); + result.getResponseCode match { + case ResponseCode.OK => Ok(response).as("application/json") + case ResponseCode.CLIENT_ERROR => BadRequest(response).as("application/json") + case ResponseCode.RESOURCE_NOT_FOUND => NotFound(response).as("application/json") + case _ => play.api.mvc.Results.InternalServerError(response).as("application/json") + } + }) + } + + def setResponseEnvelope(response: Response) = { + response.setTs(DateUtils.formatCurrentDate("yyyy-MM-dd'T'HH:mm:ss'Z'XXX")) + response.getParams.setResmsgid(UUID.randomUUID().toString) + } + + def setRequestContext(request:org.sunbird.common.dto.Request, version: String, objectType: String, schemaName: String): Unit = { + var contextMap: java.util.Map[String, AnyRef] = new java.util.HashMap[String, AnyRef](){{ + put("graph_id", "domain") + put("version" , version) + put("objectType" , objectType) + put("schemaName", schemaName) + }}; + request.setObjectType(objectType); + request.setContext(contextMap) + } +} diff --git a/validate-api/validate-service/app/controllers/HealthController.scala b/validate-api/validate-service/app/controllers/HealthController.scala new file mode 100644 index 000000000..d278b7681 --- /dev/null +++ b/validate-api/validate-service/app/controllers/HealthController.scala @@ -0,0 +1,31 @@ +package controllers + +import akka.actor.{ActorRef, ActorSystem} +import handlers.SignalHandler +import javax.inject._ +import org.sunbird.common.JsonUtils +import org.sunbird.common.dto.ResponseHandler +import play.api.mvc._ +import utils.{ActorNames, ApiId} + +import scala.concurrent.{ExecutionContext, Future} + +class HealthController @Inject()(@Named(ActorNames.HEALTH_ACTOR) healthActor: ActorRef, cc: ControllerComponents, actorSystem: ActorSystem, signalHandler: SignalHandler)(implicit exec: ExecutionContext) extends BaseController(cc) { + + def health() = Action.async { implicit request => + if (signalHandler.isShuttingDown) { + Future { ServiceUnavailable } + } else { + getResult(ApiId.APPLICATION_HEALTH, healthActor, new org.sunbird.common.dto.Request()) + } + } + + def serviceHealth() = Action.async { implicit request => + if (signalHandler.isShuttingDown) + Future { ServiceUnavailable } + else { + val response = ResponseHandler.OK().setId(ApiId.APPLICATION_SERVICE_HEALTH).put("healthy", true) + Future { Ok(JsonUtils.serialize(response)).as("application/json") } + } + } +} diff --git a/validate-api/validate-service/app/controllers/QuestionValidateController.java b/validate-api/validate-service/app/controllers/QuestionValidateController.java new file mode 100644 index 000000000..c892eed16 --- /dev/null +++ b/validate-api/validate-service/app/controllers/QuestionValidateController.java @@ -0,0 +1,37 @@ +/** */ +package controllers; + +import com.fasterxml.jackson.databind.JsonNode; + +import play.mvc.Controller; +import play.mvc.Http; +import play.mvc.Result; +import play.mvc.Results; +import utils.Attrs; + +/** + * This controller will handler all the request related to learner state. + * + * @author Manzarul + */ +public class QuestionValidateController extends Controller { + + + + /** + * This method will update learner current state with last store state. + * + * @return Result + */ + public Result assessment(Http.Request httpRequest) { + JsonNode requestData = httpRequest.body().asJson(); + String loggingHeaders = httpRequest.attrs().getOptional(Attrs.X_LOGGING_HEADERS).orElse(null); + String requestedBy = httpRequest.attrs().getOptional(Attrs.USER_ID).orElse(null); + String requestedFor = httpRequest.attrs().getOptional(Attrs.REQUESTED_FOR).orElse(null); + String apiDebugLog = "UpdateContentState Request: " + requestData.toString() + " RequestedBy: " + requestedBy + " RequestedFor: " + requestedFor + " "; + + return Results.ok(); + } + + +} diff --git a/validate-api/validate-service/app/filters/AccessLogFilter.scala b/validate-api/validate-service/app/filters/AccessLogFilter.scala new file mode 100644 index 000000000..aad9f8419 --- /dev/null +++ b/validate-api/validate-service/app/filters/AccessLogFilter.scala @@ -0,0 +1,45 @@ +package filters + +import akka.util.ByteString +import javax.inject.Inject +import org.sunbird.telemetry.util.TelemetryAccessEventUtil +import play.api.Logging +import play.api.libs.streams.Accumulator +import play.api.mvc._ + +import scala.concurrent.ExecutionContext +import scala.collection.JavaConverters._ + +class AccessLogFilter @Inject() (implicit ec: ExecutionContext) extends EssentialFilter with Logging { + + val xHeaderNames = Map("x-session-id" -> "X-Session-ID", "X-Consumer-ID" -> "x-consumer-id", "x-device-id" -> "X-Device-ID", "x-app-id" -> "APP_ID", "x-authenticated-userid" -> "X-Authenticated-Userid", "x-channel-id" -> "X-Channel-Id") + + def apply(nextFilter: EssentialAction) = new EssentialAction { + def apply(requestHeader: RequestHeader) = { + + val startTime = System.currentTimeMillis + + val accumulator: Accumulator[ByteString, Result] = nextFilter(requestHeader) + + accumulator.map { result => + val endTime = System.currentTimeMillis + val requestTime = endTime - startTime + + val path = requestHeader.uri + if(!path.contains("/health")){ + val headers = requestHeader.headers.headers.groupBy(_._1).mapValues(_.map(_._2)) + val appHeaders = headers.filter(header => xHeaderNames.keySet.contains(header._1.toLowerCase)) + .map(entry => (xHeaderNames.get(entry._1.toLowerCase()).get, entry._2.head)) + val otherDetails = Map[String, Any]("StartTime" -> startTime, "env" -> "assessment", + "RemoteAddress" -> requestHeader.remoteAddress, + "ContentLength" -> result.body.contentLength.getOrElse(0), + "Status" -> result.header.status, "Protocol" -> "http", + "path" -> path, + "Method" -> requestHeader.method.toString) + TelemetryAccessEventUtil.writeTelemetryEventLog((otherDetails ++ appHeaders).asInstanceOf[Map[String, AnyRef]].asJava) + } + result.withHeaders("Request-Time" -> requestTime.toString) + } + } + } + } \ No newline at end of file diff --git a/validate-api/validate-service/app/handlers/SignalHandler.scala b/validate-api/validate-service/app/handlers/SignalHandler.scala new file mode 100644 index 000000000..4cad301c1 --- /dev/null +++ b/validate-api/validate-service/app/handlers/SignalHandler.scala @@ -0,0 +1,33 @@ +package handlers + +import java.util.concurrent.TimeUnit + +import akka.actor.ActorSystem +import javax.inject.{Inject, Singleton} +import org.slf4j.LoggerFactory +import play.api.inject.DefaultApplicationLifecycle +import sun.misc.Signal + +import scala.concurrent.duration.Duration + +@Singleton +class SignalHandler @Inject()(implicit actorSystem: ActorSystem, lifecycle: DefaultApplicationLifecycle) { + val LOG = LoggerFactory.getLogger(classOf[SignalHandler]) + val STOP_DELAY = Duration.create(30, TimeUnit.SECONDS) + var isShuttingDown = false + + println("Initializing SignalHandler...") + Signal.handle(new Signal("TERM"), new sun.misc.SignalHandler() { + override def handle(signal: Signal): Unit = { + // $COVERAGE-OFF$ Disabling scoverage as this code is impossible to test + isShuttingDown = true + println("Termination required, swallowing SIGTERM to allow current requests to finish. : " + System.currentTimeMillis()) + actorSystem.scheduler.scheduleOnce(STOP_DELAY)(() => { + println("ApplicationLifecycle stop triggered... : " + System.currentTimeMillis()) + lifecycle.stop() + })(actorSystem.dispatcher) + // $COVERAGE-ON + } + }) +} + diff --git a/validate-api/validate-service/app/modules/AssessmentModule.scala b/validate-api/validate-service/app/modules/AssessmentModule.scala new file mode 100644 index 000000000..067d502e9 --- /dev/null +++ b/validate-api/validate-service/app/modules/AssessmentModule.scala @@ -0,0 +1,16 @@ +package modules + +import com.google.inject.AbstractModule +import org.sunbird.actors.{HealthActor, ItemSetActor, QuestionActor, QuestionSetActor} +import play.libs.akka.AkkaGuiceSupport +import utils.ActorNames + +class AssessmentModule extends AbstractModule with AkkaGuiceSupport { + + override def configure() = { +// super.configure() + bindActor(classOf[HealthActor], ActorNames.HEALTH_ACTOR) + + println("Initialized application actors for assessment-service") + } +} diff --git a/validate-api/validate-service/app/utils/ActorNames.scala b/validate-api/validate-service/app/utils/ActorNames.scala new file mode 100644 index 000000000..3420a3cc5 --- /dev/null +++ b/validate-api/validate-service/app/utils/ActorNames.scala @@ -0,0 +1,7 @@ +package utils + +object ActorNames { + + final val HEALTH_ACTOR = "healthActor" + +} diff --git a/validate-api/validate-service/app/utils/ApiId.scala b/validate-api/validate-service/app/utils/ApiId.scala new file mode 100644 index 000000000..70aa790dc --- /dev/null +++ b/validate-api/validate-service/app/utils/ApiId.scala @@ -0,0 +1,9 @@ +package utils + +object ApiId { + + final val APPLICATION_HEALTH = "api.assessment.health" + final val APPLICATION_SERVICE_HEALTH = "api.assessment.service.health" + + +} diff --git a/validate-api/validate-service/app/utils/Attrs.java b/validate-api/validate-service/app/utils/Attrs.java new file mode 100644 index 000000000..956a9e0a8 --- /dev/null +++ b/validate-api/validate-service/app/utils/Attrs.java @@ -0,0 +1,21 @@ +package utils; + +import play.libs.typedmap.TypedKey; + +public class Attrs { + public static final TypedKey<String> USER_ID = TypedKey.<String>create(JsonKey.USER_ID); + public static final TypedKey<String> AUTH_WITH_MASTER_KEY = TypedKey.<String>create(JsonKey.AUTH_WITH_MASTER_KEY); + public static final TypedKey<String> REQUEST_ID = TypedKey.<String>create(JsonKey.REQUEST_ID); + public static final TypedKey<String> CONTEXT = TypedKey.<String>create(JsonKey.CONTEXT); + public static final TypedKey<String> REQUESTED_FOR = TypedKey.<String>create(JsonKey.REQUESTED_FOR); + public static final TypedKey<String> IS_AUTH_REQ = TypedKey.<String>create(JsonKey.IS_AUTH_REQ); + public static final TypedKey<String> SIGNUP_TYPE = TypedKey.<String>create(JsonKey.SIGNUP_TYPE); + public static final TypedKey<String> REQUEST_SOURCE = TypedKey.<String>create(JsonKey.REQUEST_SOURCE); + public static final TypedKey<String> CHANNEL = TypedKey.<String>create(JsonKey.CHANNEL); + public static final TypedKey<String> APP_ID = TypedKey.<String>create(JsonKey.APP_ID); + public static final TypedKey<String> DEVICE_ID = TypedKey.<String>create(JsonKey.DEVICE_ID); + public static final TypedKey<String> ACTOR_ID = TypedKey.<String>create(JsonKey.ACTOR_ID); + public static final TypedKey<String> ACTOR_TYPE = TypedKey.<String>create(JsonKey.ACTOR_TYPE); + public static final TypedKey<String> X_AUTH_TOKEN = TypedKey.<String>create(JsonKey.X_AUTH_TOKEN); + public static final TypedKey<String> X_LOGGING_HEADERS = TypedKey.<String>create(JsonKey.X_LOGGING_HEADERS); +} diff --git a/validate-api/validate-service/app/utils/JavaJsonUtils.scala b/validate-api/validate-service/app/utils/JavaJsonUtils.scala new file mode 100644 index 000000000..2093c2e33 --- /dev/null +++ b/validate-api/validate-service/app/utils/JavaJsonUtils.scala @@ -0,0 +1,38 @@ +package utils + +import java.lang.reflect.{ParameterizedType, Type} + +import com.fasterxml.jackson.core.`type`.TypeReference +import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper} + +object JavaJsonUtils { + + @transient val mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); +// mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false); +// mapper.setSerializationInclusion(Include.NON_NULL); + + @throws(classOf[Exception]) + def serialize(obj: AnyRef): String = { + mapper.writeValueAsString(obj); + } + + @throws(classOf[Exception]) + def deserialize[T: Manifest](value: String): T = mapper.readValue(value, typeReference[T]); + + private[this] def typeReference[T: Manifest] = new TypeReference[T] { + override def getType = typeFromManifest(manifest[T]) + } + + + private[this] def typeFromManifest(m: Manifest[_]): Type = { + if (m.typeArguments.isEmpty) { m.runtimeClass } + // $COVERAGE-OFF$Disabling scoverage as this code is impossible to test + else new ParameterizedType { + def getRawType = m.runtimeClass + def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray + def getOwnerType = null + } + // $COVERAGE-ON$ + } +} diff --git a/validate-api/validate-service/app/utils/JsonKey.java b/validate-api/validate-service/app/utils/JsonKey.java new file mode 100644 index 000000000..1c190f25b --- /dev/null +++ b/validate-api/validate-service/app/utils/JsonKey.java @@ -0,0 +1,1020 @@ +package utils; + +import java.util.Arrays; +import java.util.List; + +/** + * This class will contains all the key related to request and response. + * + * @author Manzarul + */ +public final class JsonKey { + public static final String ANONYMOUS = "Anonymous"; + public static final String UNAUTHORIZED = "Unauthorized"; + public static final String MW_SYSTEM_HOST = "sunbird_mw_system_host"; + public static final String MW_SYSTEM_PORT = "sunbird_mw_system_port"; + public static final String MW_SYSTEM_CLIENT_PORT = "sunbird_mw_system_client_port"; + public static final String ACCESS_TOKEN = "access_token"; + public static final String ACCESSTOKEN = "accessToken"; + public static final String ACCOUNT_KEY = "sunbird_account_key"; + public static final String ACCOUNT_NAME = "sunbird_account_name"; + public static final String DOWNLOAD_LINK_EXPIRY_TIMEOUT = "download_link_expiry_timeout"; + public static final String SIGNED_URL = "signedUrl"; + public static final String REPORTS = "reports"; + public static final String PROGRESS_REPORT_SIGNED_URL = "courseProgressReportUrl"; + public static final String ASSESSMENT_REPORT_BLOB_URL = "reportUrl"; + public static final String ASSESSMENT_REPORT_SIGNED_URL = "assessmentReportUrl"; + public static final String BULK_UPLOAD_STATUS = "Status"; + public static final String BULK_UPLOAD_ERROR = "Remarks"; + public static final String ACTION_GROUP = "action_group"; + public static final String ACTION_GROUPS = "actionGroups"; + public static final String ACTION_NAME = "actionName"; + public static final String ACTION_URL = "actionUrl"; + public static final String ACTIONS = "actions"; + public static final String ACTIVE = "active"; + public static final String ACTOR_ID = "actorId"; + public static final String ACTOR_SERVICE = "Actor service"; + public static final String ACTOR_TYPE = "actorType"; + public static final String ADD_TYPE = "addType"; + public static final String ADDED_AT = "addedAt"; + public static final String ADDED_BY = "addedBy"; + public static final String ADDED_BY_NAME = "addedByName"; + public static final String ADDITIONAL_INFO = "ADDITIONAL_INFO"; + public static final String ADDRESS = "address"; + public static final String ADDRESS_DB = "address"; + public static final String ADDRESS_ID = "addressId"; + public static final String ADDRESS_LINE1 = "addressLine1"; + public static final String ADDRESS_LINE2 = "addressLine2"; + public static final String ADDRESS_TYPE = "address type"; + public static final String AGGREGATIONS = "aggregations"; + public static final String ALL = "all"; + public static final String ALLOWED_LOGIN = "allowedLogin"; + public static final String ANNOUNCEMENT = "announcement"; + public static final String API_ACCESS = "api_access"; + public static final String API_ACTOR_PROVIDER = "api_actor_provider"; + public static final String API_CALL = "API_CALL"; + public static final String API_ID = "apiId"; + public static final String APP_ICON = "appIcon"; + public static final String APP_MAP = "appMap"; + public static final String APP_SECTIONS = "appSections"; + public static final String APP_URL = "appUrl"; + public static final String APPICON = "appIcon"; + public static final String APPLICABLE_FOR = "applicableFor"; + public static final String APPROOVE_DATE = "approvalDate"; + public static final String APPROVED_BY = "approvedBy"; + public static final String APPROVED_BY_NAME = "approvedByName"; + public static final String APPROVED_DATE = "approvedDate"; + public static final String ASSESSMENT = "assessment"; + public static final String ASSESSMENT_EVENTS = "assessments"; + public static final String ASSESSMENT_TS = "assessmentTs"; + public static final String ASSESSMENT_ANSWERS = "answers"; + public static final String ASSESSMENT_ATTEMPT_DATE = "attemptedDate"; + public static final String ASSESSMENT_EVAL_DB = "assessment_eval_db"; + public static final String ASSESSMENT_GRADE = "grade"; + public static final String ASSESSMENT_ITEM_DB = "assessment_item_db"; + public static final String ASSESSMENT_ITEM_ID = "assessmentItemId"; + public static final String ASSESSMENT_MAX_SCORE = "maxScore"; + public static final String ASSESSMENT_SCORE = "score"; + public static final String ASSESSMENT_STATUS = "assessmentStatus"; + public static final String ASSESSMENT_TYPE = "assessmentType"; + public static final String ATTEMPT_ID = "attemptId"; + public static final String ASSESSMENT_EVENTS_KEY = "events"; + public static final String ASSESSMENT_ACTOR = "actor"; + public static final String ATTEMPTED_COUNT = "attemptedCount"; + public static final String AUTH_TOKEN = "authToken"; + public static final String AUTH_USER_HEADER = "X-Authenticated-Userid"; + public static final String AUTH_WITH_MASTER_KEY = "authWithMasterKey"; + public static final String AUTHORIZATION = "Authorization"; + public static final String BACKGROUND_ACTOR_PROVIDER = "background_actor_provider"; + public static final String BAD_REQUEST = "badRequest"; + public static final String BATCH = "batch"; + public static final String BATCH_ID = "batchId"; + public static final String BEARER = "Bearer "; + public static final String BLOCKED = "blocked"; + public static final String BODY = "body"; + public static final String BULK_OP_DB = "BulkOpDb"; + public static final String BULK_UPLOAD_BATCH_DATA_SIZE = "bulk_upload_batch_data_size"; + public static final String BULK_USER_UPLOAD = "bulkUserUpload"; + public static final String CASSANDRA_IN_EMBEDDED_MODE = "cassandraInEmbeddedMode"; + public static final String CASSANDRA_SERVICE = "Cassandra service"; + public static final String CATEGORIES = "categories"; + public static final String CHANNEL = "channel"; + public static final String CHANNEL_REG_STATUS = "channelRegStatus"; + public static final String CHANNEL_REG_STATUS_ID = "003"; + public static final String CHANNELS = "channels"; + public static final String CHECKS = "checks"; + public static final String CHILD_OF = "childOf"; + public static final String CHILDREN = "children"; + public static final String CITY = "city"; + public static final String CLASS = "class"; + public static final String CLIENT_ID = "clientId"; + public static final String CLIENT_INFO_DB = "clientInfo_db"; + public static final String CLIENT_NAME = "clientName"; + public static final String CLIENT_NAMES = "client.names"; + public static final String CODE = "code"; + public static final String COMPLETED_COUNT = "completedCount"; + public static final String COMPLETENESS = "completeness"; + public static final String CONSUMER = "consumer"; + public static final String CONTACT_DETAILS = "contactDetail"; + public static final String CONTAINER = "container"; + public static final String CONTENT = "content"; + public static final String CONTENT_CREATOR = "CONTENT_CREATOR"; + public static final String CONTENT_ID = "contentId"; + public static final String CONTENT_IDS = "contentIds"; + public static final String CONTENT_LIST = "contentList"; + public static final String CONTENT_NAME = "contentName"; + public static final String CONTENT_PROGRESS = "progress"; + public static final String CONTENT_TYPE = "contentType"; + public static final String CONTENT_VERSION = "contentVersion"; + public static final String CONTENTS = "contents"; + public static final String CONTEXT = "context"; + public static final String CORRELATED_OBJECTS = "correlatedObjects"; + public static final String COUNT = "count"; + public static final String COUNT_DECREMENT_DATE = "countDecrementDate"; + public static final String COUNT_INCREMENT_DATE = "countIncrementDate"; + public static final String COUNTER_DECREMENT_STATUS = "countDecrementStatus"; + public static final String COUNTER_INCREMENT_STATUS = "countIncrementStatus"; + public static final String COUNTRY = "country"; + public static final String COUNTRY_CODE = "countryCode"; + public static final String COURSE = "course"; + public static final String COURSE_ADDITIONAL_INFO = "courseAdditionalInfo"; + public static final String COURSE_BATCH_DB = "courseBatchDB"; + public static final String COURSE_CREATED_FOR = "createdFor"; + public static final String COURSE_CREATOR = "courseCreator"; + public static final String COURSE_DURATION = "courseDuration"; + public static final String COURSE_ENROLL_DATE = "enrolledDate"; + public static final String COURSE_ID = "courseId"; + public static final String COURSE_IDS = "courseIds"; + public static final String COURSE_LIST = "courseList"; + public static final String COURSE_LOGO_URL = "courseLogoUrl"; + public static final String COURSE_MANAGEMENT_DB = "courseManagement_db"; + public static final String COURSE_NAME = "courseName"; + public static final String COURSE_PROGRESS = "progress"; + public static final String COURSE_PUBLISHED_STATUS = "course_publish_status"; + public static final String COURSE_VERSION = "courseVersion"; + public static final String CourseConsumption = "courseConsumption"; + public static final String CourseProgress = "courseProgress"; + public static final String COURSES = "courses"; + public static final String CREATE = "create"; + public static final String CREATED_BY = "createdBy"; + public static final String CREATED_DATE = "createdDate"; + public static final String CRITERIA = "criteria"; + public static final String CURRENT_LOGIN_TIME = "currentLoginTime"; + public static final String CURRENT_STATE = "CURRENT_STATE"; + public static final String DASHBOARD = "dashboard"; + public static final String DATA = "data"; + public static final String KEY = "key"; + public static final String KEYS = "keys"; + public static final String DATE = "date"; + public static final String DATE_HISTOGRAM = "DATE_HISTOGRAM"; + public static final String DATE_TIME = "dateTime"; + public static final String DB_IP = "db.ip"; + public static final String DB_KEYSPACE = "db.keyspace"; + public static final String DB_PASSWORD = "db.password"; + public static final String DB_PORT = "db.port"; + public static final String DB_USERNAME = "db.username"; + public static final String DEFAULT_ACTION_NAME = "Download Reports"; + public static final String DEFAULT_CONSUMER_ID = "internal"; + public static final String DEFAULT_ROOT_ORG_ID = "ORG_001"; + public static final String DEGREE = "degree"; + public static final String DELETE = "delete"; + public static final String DELTA = "delta"; + public static final String DESCRIPTION = "description"; + public static final String DOB = "dob"; + public static final String DOWNLOAD_URL = "downloadUrl"; + public static final String DUPLICATE = "duplicate"; + public static final String EDUCATION = "education"; + public static final String EDUCATION_DB = "user_education"; + public static final String EKS = "eks"; + public static final String SEARCH_SERVICE_API_BASE_URL = "sunbird_search_service_api_base_url"; + public static final String ANALYTICS_API_BASE_URL = "sunbird_analytics_api_base_url"; + public static final String EKSTEP_AUTHORIZATION = "ekstep_authorization"; + public static final String EKSTEP_BASE_URL = "ekstep_api_base_url"; + public static final String EKSTEP_CONTENT_SEARCH_BASE_URL = "ekstep_content_search_base_url"; + public static final String EKSTEP_CONTENT_SEARCH_URL = "ekstep_content_search_url"; + public static final String EKSTEP_CONTENT_UPDATE_URL = "ekstep.content.update.url"; + public static final String EKSTEP_SERVICE = "EkStep service"; + public static final String EKSTEP_TAG_API_URL = "ekstep.tag.api.url"; + public static final String EMAIL = "email"; + public static final String EMAIL_REQUEST = "emailReq"; + public static final String EMAIL_SERVER_FROM = "sunbird_mail_server_from_email"; + public static final String EMAIL_SERVER_HOST = "sunbird_mail_server_host"; + public static final String EMAIL_SERVER_PASSWORD = "sunbird_mail_server_password"; + public static final String EMAIL_SERVER_PORT = "sunbird_mail_server_port"; + public static final String EMAIL_SERVER_USERNAME = "sunbird_mail_server_username"; + public static final String EMAIL_TEMPLATE_TYPE = "emailTemplateType"; + public static final String EMAIL_UNIQUE = "emailUnique"; + public static final String EMAIL_VERIFIED = "emailVerified"; + public static final String EMAIL_VERIFIED_UPDATED = "emailVerifiedUpdated"; + public static final String EMBEDDED = "embedded"; + public static final String EMBEDDED_MODE = "embedded"; + public static final String ENC_EMAIL = "encEmail"; + public static final String ENC_PHONE = "encPhone"; + public static final String ENCRYPTION_KEY = "sunbird_encryption_key"; + public static final String END_DATE = "endDate"; + public static final String END_TIME = "endTime"; + public static final String ENDORSE_DATE = "endorseDate"; + public static final String ENDORSED_USER_ID = "endorsedUserId"; + public static final String ENDORSEMENT_COUNT = "endorsementCount"; + public static final String ENDORSERS = "endorsers"; + public static final String ENDORSERS_LIST = "endorsersList"; + public static final String ENROLLMENT_END_DATE = "enrollmentEndDate"; + public static final String ENROLLMENT_START_DATE = "enrollementStartDate"; + public static final String ENROLLMENT_TYPE = "enrollmentType"; + public static final String ENROLMENTTYPE = "enrolmentType"; + public static final String ENV = "env"; + public static final String ERR_TYPE = "errtype"; + public static final String ERROR = "err"; + public static final String ERROR_MSG = "err_msg"; + public static final String ERRORMSG = "errmsg"; + public static final String ES_METRICS_PORT = "es_metrics_port"; + public static final String ES_SERVICE = "Elastic search service"; + public static final String ES_URL = "es_search_url"; + public static final String ESTIMATED_COUNT_REQ = "estimatedCountReq"; + public static final String EVENTS = "events"; + public static final String EXISTS = "exists"; + public static final String EXTERNAL_ID = "externalId"; + public static final String EXTERNAL_ID_VALUE = "externalIdValue"; + public static final String FACETS = "facets"; + public static final String FAILED = "FAILED"; + public static final String FAILURE = "failure"; + public static final String FAILURE_RESULT = "failureResult"; + public static final String FCM = "fcm"; + public static final String FCM_URL = "fcm.url"; + public static final String FIELD = "field"; + public static final String FIELDS = "fields"; + public static final String FILE = "file"; + public static final String FILE_NAME = "fileName"; + public static final String FILE_PARAMS = "fileParams"; + public static final String FILE_URL = "fileUrl"; + public static final String FILTER = "filter"; + public static final String FILTERS = "filters"; + public static final String FIRST_NAME = "firstName"; + public static final String FORM_PARAMS = "formParams"; + public static final String FORMAT = "format"; + public static final String FRAMEWORK = "framework"; + public static final String FROM_EMAIL = "fromEmail"; + public static final String GENDER = "gender"; + public static final String GEO_LOCATION_DB = "geoLocationDb"; + public static final String GRADE = "grade"; + public static final String GRADE_LEVEL = "gradeLevel"; + public static final String GROUP = "group"; + public static final String GROUPID = "groupId"; + public static final String GROUP_QUERY = "groupQuery"; + public static final String HASH_TAG_ID = "hashtagid"; + public static final String HASHTAGID = "hashTagId"; + public static final String HEADER = "header"; + public static final String Healthy = "healthy"; + public static final String HOME_URL = "homeUrl"; + public static final String ID = "id"; + public static final String IDENTIFIER = "identifier"; + public static final String IMAGE = "image"; + public static final String INACTIVE = "inactive"; + public static final String INDEX = "index"; + public static final String INFO = "info"; + public static final String INSERT = "insert"; + public static final String INVITE_ONLY = "invite-only"; + public static final String IS_APPROVED = "isApproved"; + public static final String IS_AUTH_REQ = "isAuthReq"; + public static final String IS_DEFAULT = "isDefault"; + public static final String IS_DELETED = "isDeleted"; + public static final String IS_REJECTED = "isRejected"; + public static final String IS_ROOT_ORG = "isRootOrg"; + public static final String IS_SSO_ENABLED = "sso.enabled"; + public static final String IS_VERIFIED = "isVerified"; + public static final String JOB_NAME = "jobName"; + public static final String JOB_PROFILE = "jobProfile"; + public static final String JOB_PROFILE_DB = "user_job_profile"; + public static final String JOINING_DATE = "joiningDate"; + public static final String LANGUAGE = "language"; + public static final String LAST_ACCESS_TIME = "lastAccessTime"; + public static final String LAST_COMPLETED_TIME = "lastCompletedTime"; + public static final String LAST_LOGIN_TIME = "lastLoginTime"; + public static final String LAST_LOGOUT_TIME = "lastLogoutTime"; + public static final String LAST_NAME = "lastName"; + public static final String LAST_READ_CONTENT_STATUS = "lastReadContentStatus"; + public static final String LAST_READ_CONTENT_VERSION = "lastReadContentVersion"; + public static final String LAST_READ_CONTENTID = "lastReadContentId"; + public static final String LAST_UPDATED_TIME = "lastUpdatedTime"; + public static final String LEAF_NODE_COUNT = "leafNodesCount"; + public static final String LEARNER_CONTENT_DB = "learnerContent_db"; + public static final String LEARNER_COURSE_DB = "learnerCourse_db"; + public static final String LEARNER_SERVICE = "Learner service"; + public static final String LEVEL = "level"; + public static final String LIMIT = "limit"; + public static final String LIST = "List"; + public static final String LOC_ID = "locationId"; + public static final String LOCATION = "location"; + public static final String LOCATION_NAME = "locationName"; + public static final String LOCATION_ID = "locationId"; + public static final String LOCATION_IDS = "locationIds"; + public static final String LOCATIONS = "locations"; + public static final String LOG_LEVEL = "logLevel"; + public static final String LOG_RECORD = "logRecord"; + public static final String LOG_TYPE = "logType"; + public static final String LOGIN_GENERAL = "general"; + public static final String LOGIN_ID = "loginId"; + public static final String LOGIN_ID_DELIMETER = "@"; + public static final String LOGIN_TYPE = "type"; + public static final String MAIL_NOTE = "mail_note"; + public static final String MANDATORY_FIELDS = "mandatoryFields"; + public static final String MAP = "map"; + public static final String MAPPED_FORM_PARAMS = "mappedFormParams"; + public static final String MASKED_EMAIL = "maskedEmail"; + public static final String MASKED_PHONE = "maskedPhone"; + public static final String MASTER_ACTION = "master_action"; + public static final String MASTER_KEY = "masterKey"; + public static final String MEDIA_TYPE_DB = "mediaTypeDB"; + public static final String MENTORS = "mentors"; + public static final String MESSAGE = "message"; + public static final String MESSAGE_Id = "message_id"; + public static final String MESSAGE_ID = "X-msgId"; + public static final String METHOD = "method"; + public static final String METHOD_NAME = "methodName"; + public static final String METRICS = "metrics"; + public static final String MISSING_FIELDS = "missingFields"; + public static final String MOBILE = "mobile"; + public static final String NAME = "name"; + public static final String NEW_PASSWORD = "newPassword"; + public static final String NO_OF_LECTURES = "noOfLectures"; + public static final String NO_OF_MEMBERS = "noOfMembers"; + public static final String NOT_AVAILABLE = "NA"; + public static final String NOT_EXISTS = "not_exists"; + public static final String NOTE = "note"; + public static final String NOTE_ID = "noteId"; + public static final String NOTIFICATION = "notification"; + public static final String NULL = "null"; + public static final String OBJECT_ID = "objectId"; + public static final String OBJECT_IDS = "objectIds"; + public static final String OBJECT_TYPE = "objectType"; + public static final String OFFSET = "offset"; + public static final String ON = "ON"; + public static final String ONBOARDING_WELCOME_MAIL_BODY = "onboarding_welcome_mail_body"; + public static final String OPEN = "open"; + public static final String OPERATION = "operation"; + public static final String OPERATION_FOR = "operationFor"; + public static final String OPERATION_TYPE = "operationType"; + public static final String ORDER = "order"; + public static final String ORG_CODE = "orgCode"; + public static final String ORG_CODE_HEADER = "X-Org-code"; + public static final String ORG_EXT_ID_DB = "org_external_identity"; + public static final String ORG_DB = "org_db"; + public static final String ORG_ID = "orgId"; + public static final String ORG_ID_ONE = "orgIdOne"; + public static final String ORG_ID_TWO = "orgIdTwo"; + public static final String ORG_IMAGE_URL = "orgImageUrl"; + public static final String ORG_JOIN_DATE = "orgJoinDate"; + public static final String ORG_LEFT_DATE = "orgLeftDate"; + public static final String ORG_MAP_DB = "org_mapping"; + public static final String ORG_NAME = "orgName"; + public static final String ORG_SERVER_FROM_NAME = "orgServerFromName"; + public static final String ORG_TYPE = "orgType"; + public static final String ORG_TYPE_DB = "org_type"; + public static final String ORG_TYPE_ID = "orgTypeId"; + public static final String ORGANISATION = "organisation"; + public static final String ORGANISATION_ID = "organisationId"; + public static final String ORGANISATION_NAME = "orgName"; + public static final String ORGANISATIONS = "organisations"; + public static final String OrgConsumption = "orgConsumption"; + public static final String OrgCreation = "orgCreation"; + public static final String OTP = "otp"; + public static final String OTP_EMAIL_RESET_PASSWORD_TEMPLATE = "otpEmailResetPasswordTemplate"; + public static final String OTP_PHONE_RESET_PASSWORD_TEMPLATE = "otpPhoneResetPasswordTemplate"; + public static final String VERIFY_PHONE_OTP_TEMPLATE = "verifyPhoneOtpTemplate"; + public static final String PAGE = "page"; + public static final String PAGE_ID = "pageId"; + public static final String PAGE_MGMT_DB = "page_mgmt_db"; + public static final String PAGE_NAME = "name"; + public static final String PAGE_SECTION = "page_section"; + public static final String PAGE_SECTION_DB = "page_section_db"; + public static final String PARAMS = "params"; + public static final String PARENT_OF = "parentOf"; + public static final String PARENT_ORG_ID = "parentOrgId"; + public static final String PARTICIPANT = "participant"; + public static final String PARTICIPANTS = "participants"; + public static final String PASSWORD = "password"; + public static final String PDATA = "pdata"; + + public static final String PERCENTAGE = "percentage"; + public static final String PERIOD = "period"; + public static final String PHONE = "phone"; + public static final String PHONE_NUMBER_VERIFIED = "phoneNumberVerified"; + public static final String PHONE_UNIQUE = "phoneUnique"; + public static final String PHONE_VERIFIED = "phoneVerified"; + public static final String PORTAL_MAP = "portalMap"; + public static final String PORTAL_SECTIONS = "portalSections"; + public static final String POSITION = "position"; + public static final String PREFERRED_LANGUAGE = "preferredLanguage"; + public static final String PREV_STATE = "PREV_STATE"; + public static final String PRIMARY_KEY_DELIMETER = "##"; + public static final String PRIVATE = "private"; + public static final String PROCESS_END_TIME = "processEndTime"; + public static final String PROCESS_ID = "processId"; + public static final String PROCESS_START_TIME = "processStartTime"; + public static final String PROCESSING_STATUS = "processingStatus"; + public static final String PDATA_ID = "telemetry_pdata_id"; + public static final String PDATA_PID = "telemetry_pdata_pid"; + public static final String PDATA_VERSION = "telemetry_pdata_ver"; + public static final String PROFILE_SUMMARY = "profileSummary"; + public static final String PROFILE_VISIBILITY = "profileVisibility"; + public static final String PROGRESS = "progress"; + public static final String PROPERTIES = "properties"; + public static final String PROPS = "props"; + public static final String PROVIDER = "provider"; + public static final String PUBLIC = "public"; + public static final String PUBLISH_COURSE = "publishCourse"; + public static final String QUERY = "query"; + public static final String QUERY_FIELDS = "queryFields"; + public static final String RECEIVER_ID = "receiverId"; + public static final String RECIPIENT_COUNT = "recipientCount"; + public static final String RECIPIENT_EMAILS = "recipientEmails"; + public static final String RECIPIENT_USERIDS = "recipientUserIds"; + public static final String RECOMMEND_TYPE = "recommendType"; + public static final String REGISTERED_ORG = "registeredOrg"; + public static final String REGISTERED_ORG_ID = "regOrgId"; + public static final String RELATION = "relation"; + public static final String RELATIONS = "relations"; + public static final String REMOTE = "remote"; + public static final String REPLACE_WITH_ASTERISK = "*"; + public static final String REPLACE_WITH_X = "X"; + public static final String REPORT_TRACKING_DB = "reportTrackingDb"; + public static final String REQ_ID = "reqId"; + public static final String REQUEST = "request"; + public static final String REQUEST_ID = "requestId"; + public static final String REQUEST_MESSAGE_ID = "msgId"; + public static final String REQUEST_TYPE = "requestType"; + public static final String REQUESTED_BY = "requestedBy"; + public static final String RES_MSG_ID = "resmsgId"; + public static final String RESOURCE_ID = "resourceId"; + public static final String RESPONSE = "response"; + public static final String RESULT = "result"; + public static final String RETIRED = "retired"; + public static final String RETRY_COUNT = "retryCount"; + public static final String ROLE = "role"; + public static final String ROLE_GROUP = "role_group"; + public static final String ROLE_GROUP_ID = "rolegroupid"; + public static final String ROLES = "roles"; + public static final String ROLLUP = "rollup"; + public static final String ROOT_ORG = "rootOrg"; + public static final String ROOT_ORG_ID = "rootOrgId"; + public static final String SCHEDULER_JOB = "scheduler"; + public static final String SEARCH = "search"; + public static final String SEARCH_QUERY = "searchQuery"; + public static final String SEARCH_TOP_N = "searchTopN"; + public static final String SECTION = "section"; + public static final String SECTION_DATA_TYPE = "sectionDataType"; + public static final String SECTION_DISPLAY = "display"; + public static final String SECTION_ID = "sectionId"; + public static final String SECTION_MGMT_DB = "section_mgmt_db"; + public static final String SECTION_NAME = "name"; + public static final String SECTIONS = "sections"; + public static final String SERIES = "series"; + public static final String SIZE = "size"; + public static final String SKILL_ENDORSEMENT_DB = "skillEndorsementDb"; + public static final String SKILL_NAME = "skillName"; + public static final String SKILL_NAME_TO_LOWERCASE = "skillnametolowercase"; + public static final String SKILLS = "skills"; + public static final String SKILLS_LIST_DB = "skillsListDb"; + public static final String SLUG = "slug"; + public static final String SNAPSHOT = "snapshot"; + public static final String SORT = "sort"; + public static final String SORT_BY = "sort_by"; + public static final String SOURCE = "source"; + public static final String SOURCE_HEADER = "X-Source"; + public static final String SPLIT = "split"; + public static final String SSO_CLIENT_ID = "sso.client.id"; + public static final String SSO_CLIENT_SECRET = "sso.client.secret"; + public static final String SSO_PASSWORD = "sso.password"; + public static final String SSO_POOL_SIZE = "sso.connection.pool.size"; + public static final String SSO_PUBLIC_KEY = "sunbird_sso_publickey"; + public static final String SSO_REALM = "sso.realm"; + public static final String SSO_URL = "sso.url"; + public static final String SSO_USERNAME = "sso.username"; + public static final String STACKTRACE = "stacktrace"; + public static final String STANDALONE_MODE = "standalone"; + public static final String START_DATE = "startDate"; + public static final String START_TIME = "startTime"; + public static final String STATE = "state"; + public static final String STATUS = "status"; + public static final String STATUS_CODE = "statusCode"; + public static final String SUB_SECTIONS = "subSections"; + public static final String SUBJECT = "subject"; + public static final String SUBMIT_DATE = "submitDate"; + public static final String SUBTYPE = "subtype"; + public static final String SUCCESS = "SUCCESS"; + public static final String SUCCESS_RESULT = "successResult"; + public static final String SUMMARY = "summary"; + public static final String SUNBIRD = "sunbird"; + public static final String SUNBIRD_ALLOWED_LOGIN = "sunbird_allowed_login"; + public static final String SUNBIRD_API_BASE_URL = "sunbird_api_base_url"; + public static final String SUNBIRD_CASSANDRA_IP = "sunbird_cassandra_host"; + public static final String SUNBIRD_CASSANDRA_KEYSPACE = "sunbird_cassandra_keyspace"; + public static final String SUNBIRD_CASSANDRA_MODE = "sunbird_cassandra_mode"; + public static final String SUNBIRD_CASSANDRA_PASSWORD = "sunbird_cassandra_password"; + public static final String SUNBIRD_CASSANDRA_PORT = "sunbird_cassandra_port"; + public static final String SUNBIRD_CASSANDRA_USER_NAME = "sunbird_cassandra_username"; + public static final String SUNBIRD_ENCRYPTION = "sunbird_encryption"; + public static final String SUNBIRD_ENV_LOGO_URL = "sunbird_env_logo_url"; + public static final String SUNBIRD_ES_CHANNEL = "es.channel.name"; + public static final String SUNBIRD_ES_CLUSTER = "sunbird_es_cluster"; + public static final String SUNBIRD_ES_IP = "sunbird_es_host"; + public static final String SUNBIRD_ES_PORT = "sunbird_es_port"; + public static final String SUNBIRD_FCM_ACCOUNT_KEY = "sunbird_fcm_account_key"; + public static final String SUNBIRD_INSTALLATION = "sunbird_installation"; + public static final String SUNBIRD_NETTY_HOST = "sunbird_netty_host"; + public static final String SUNBIRD_NETTY_PORT = "sunbird_netty_port"; + public static final String SUNBIRD_PG_DB = "sunbird_pg_db"; + public static final String SUNBIRD_PG_HOST = "sunbird_pg_host"; + public static final String SUNBIRD_PG_PASSWORD = "sunbird_pg_password"; + public static final String SUNBIRD_PG_PORT = "sunbird_pg_port"; + public static final String SUNBIRD_PG_USER = "sunbird_pg_user"; + public static final String SUNBIRD_PLUGIN = "sunbirdplugin"; + public static final String SUNBIRD_QUARTZ_MODE = "sunbird_quartz_mode"; + public static final String SUNBIRD_SSO_CLIENT_ID = "sunbird_sso_client_id"; + public static final String SUNBIRD_SSO_CLIENT_SECRET = "sunbird_sso_client_secret"; + public static final String SUNBIRD_SSO_PASSWORD = "sunbird_sso_password"; + public static final String SUNBIRD_SSO_RELAM = "sunbird_sso_realm"; + public static final String SUNBIRD_SSO_URL = "sunbird_sso_url"; + public static final String SUNBIRD_SSO_USERNAME = "sunbird_sso_username"; + public static final String SUNBIRD_WEB_URL = "sunbird_web_url"; + public static final String SUNBIRD_GET_ORGANISATION_API = "sunbird_search_organisation_api"; + public static final String SUNBIRD_GET_SINGLE_USER_API = "sunbird_read_user_api"; + public static final String SUNBIRD_GET_MULTIPLE_USER_API = "sunbird_search_user_api"; + public static final String SUNBIRD_CONTENT_GET_HIERARCHY_API = "sunbird_get_hierarchy_api"; + public static final String SUNBIRD_CONTENT_READ_API = "sunbird_content_read_api"; + public static final String SYSTEM = "system"; + public static final String SYSTEM_SETTINGS_DB = "system_settings"; + public static final String TAG = "tag"; + public static final String TAGS = "tags"; + public static final String TARGET_OBJECT = "targetObject"; + public static final String TC_UPDATED_DATE = "tcUpdatedAt"; + public static final String TELEMETRY_CONTEXT = "TELEMETRY_CONTEXT"; + public static final String TELEMETRY_EVENT_TYPE = "telemetryEventType"; + public static final String TEMPORARY_PASSWORD = "tempPassword"; + public static final String TENANT_PREFERENCE = "tenantPreference"; + public static final String TENANT_PREFERENCE_DB = "tenantPreferenceDb"; + public static final String TERM_AND_CONDITION_STATUS = "tcStatus"; + public static final String TERMS = "terms"; + public static final String THEME = "theme"; + public static final String THUMBNAIL = "thumbnail"; + public static final String TIME_TAKEN = "timeTaken"; + public static final String TIME_UNIT = "time_unit"; + public static final String TITLE = "title"; + public static final String TO = "to"; + public static final String TOC_URL = "tocUrl"; + public static final String TOKEN = "token"; + public static final String TOPIC = "topic"; + public static final String TOPIC_NAME = "topicName"; + public static final String TOPICS = "topics"; + public static final String TOPN = "topn"; + public static final String TRY_COUNT = "tryCount"; + public static final String TYPE = "type"; + public static final String UNDEFINED_IDENTIFIER = "Undefined column name "; + public static final String UNIQUE = "unique"; + public static final String UNKNOWN_IDENTIFIER = "Unknown identifier "; + public static final String UPDATE = "update"; + public static final String UPDATED_BY = "updatedBy"; + public static final String UPDATED_BY_NAME = "updatedByName"; + public static final String UPDATED_DATE = "updatedDate"; + public static final String UPLOADED_BY = "uploadedBy"; + public static final String UPLOADED_DATE = "uploadedDate"; + public static final String URL = "url"; + public static final String URL_ACTION = "url_action"; + public static final String URL_ACTION_ID = "url_action_ids"; + public static final String URLS = "urls"; + public static final String USER = "user"; + public static final String USER_ACTION_ROLE = "user_action_role"; + public static final String USER_AUTH_DB = "userAuth_db"; + public static final String USER_COUNT = "userCount"; + public static final String USER_COUNT_TTL = "userCountTTL"; + public static final String USER_COURSE = "user_course"; + public static final String USER_COURSES = "userCourses"; + public static final String USER_DB = "user_db"; + public static final String USER_FOUND = "user exist with this login Id."; + public static final String USER_ID = "userId"; + public static final String USER_IDs = "userIds"; + public static final String USER_LIST = "userList"; + public static final String USER_LIST_REQ = "userListReq"; + public static final String USER_NAME = "username"; + public static final String USER_NOT_FOUND = "user does not exist with this login Id."; + public static final String USER_NOTES_DB = "userNotes_db"; + public static final String USER_ORG = "user_org"; + public static final String USER_ORG_DB = "user_org_db"; + public static final String USER_SKILL_DB = "userSkillDb"; + public static final String USERIDS = "userIds"; + public static final String USERNAME = "userName"; + public static final String USR_EXT_ID_DB = "user_external_identity"; + public static final String USR_ORG_DB = "user_org"; + public static final String VALUE = "value"; + public static final String VER = "ver"; + public static final String VERSION = "version"; + public static final String VIEW_COUNT = "viewCount"; + public static final String VIEW_POSITION = "viewPosition"; + public static final String WEB_PAGES = "webPages"; + public static final String WEB_URL = "webUrl"; + public static final String WELCOME_MESSAGE = "welcomeMessage"; + public static final String YEAR_OF_PASSING = "yearOfPassing"; + public static final String ZIPCODE = "zipcode"; + public static final String SUNBIRD_CONTENT_SERVICE_BASE_URL = "sunbird_content_service_base_url"; + public static final String SUNBIRD_CONTENT_SERVICE_AUTHORIZATION = + "sunbird_content_service_authorization"; + public static final String SUNBIRD_HEALTH_CHECK_ENABLE = "sunbird_health_check_enable"; + public static final String HEALTH = "health"; + public static final String SERVICE = "service"; + public static final String SOFT_CONSTRAINTS = "softConstraints"; + public static final String SUNBIRD_USER_ORG_API_BASE_URL = "sunbird_user_org_api_base_url"; + public static final String SUNBIRD_API_MGR_BASE_URL = "sunbird_api_mgr_base_url"; + public static final String SUNBIRD_AUTHORIZATION = "sunbird_authorization"; + public static final String SUNBIRD_CS_BASE_URL = "sunbird_cs_base_url"; + public static final String SUNBIRD_CS_SEARCH_PATH = "sunbird_cs_search_path"; + public static final String SUNBIRD_LMS_TELEMETRY = "Sunbird_LMS_Telemetry"; + public static final String SUNBIRD_LMS_AUTHORIZATION = "sunbird_authorization"; + public static final String ETS = "ets"; + public static final String CONTENT_ENCODING = "Content-Encoding"; + public static final String EK_STEP = "EK-STEP"; + public static final String RESOURCE_NAME = "resourceName"; + public static final String DURATION = "duration"; + public static final String OBJECT_STORE = "object-store"; + public static final String IMAGE_URL = "imgUrl"; + public static final String COMMUNITY_ID = "communityId"; + public static final String LOCATION_CODE = "locationCode"; + public static final String LATITUDE = "latitude"; + public static final String LONGITUDE = "longitude"; + public static final String UPLOAD_FILE_MAX_SIZE = "file_upload_max_size"; + public static final String PRIMARY_KEY = "PK"; + public static final String NON_PRIMARY_KEY = "NonPK"; + public static final String PARENT_ID = "parentId"; + public static final String CREATED_ON = "createdOn"; + public static final String UPDATED_ON = "updatedOn"; + public static final String LAST_UPDATED_ON = "lastUpdatedOn"; + public static final String LAST_UPDATED_BY = "lastUpdatedBy"; + public static final String SUNBIRD_DEFAULT_CHANNEL = "sunbird_default_channel"; + public static final String CASSANDRA_WRITE_BATCH_SIZE = "cassandra_write_batch_size"; + public static final String CASSANDRA_UPDATE_BATCH_SIZE = "cassandra_update_batch_size"; + public static final String ORG_EXTERNAL_ID = "orgExternalId"; + public static final String ORG_PROVIDER = "orgProvider"; + public static final String EXTERNAL_IDS = "externalIds"; + public static final String EXTERNAL_ID_TYPE = "externalIdType"; + public static final String ID_TYPE = "idType"; + public static final String ADD = "add"; + public static final String REMOVE = "remove"; + public static final String EDIT = "edit"; + public static final String DEFAULT_FRAMEWORK = "defaultFramework"; + public static final String EXTERNAL_ID_PROVIDER = "externalIdProvider"; + public static final String USR_EXT_IDNT_TABLE = "usr_external_identity"; + public static final String END_TIME_IN_HOUR_MINUTE_SECOND = " 23:59:59"; + public static final String REGISTRY_ID = "registryId"; + public static final String RESPONSE_CODE = "responseCode"; + public static final String OK = "ok"; + public static final String SUNBIRD_DEFAULT_COUNTRY_CODE = "sunbird_default_country_code"; + public static final String ONBOARDING_MAIL_SUBJECT = "onboarding_mail_subject"; + public static final String ONBOARDING_MAIL_MESSAGE = "onboarding_welcome_message"; + public static final String ES_TYPES = "types"; + public static final String RECIPIENT_SEARCH_QUERY = "recipientSearchQuery"; + public static final String ORIGINAL_EXTERNAL_ID = "originalExternalId"; + public static final String ORIGINAL_ID_TYPE = "originalIdType"; + public static final String ORIGINAL_PROVIDER = "originalProvider"; + public static final String SUNBIRD_CASSANDRA_CONSISTENCY_LEVEL = + "sunbird_cassandra_consistency_level"; + public static final String VERSION_2 = "v2"; + public static final String CUSTODIAN_ORG_CHANNEL = "custodianOrgChannel"; + public static final String CUSTODIAN_ORG_ID = "custodianOrgId"; + public static final String APP_ID = "appId"; + public static final String REDIRECT_URI = "redirectUri"; + public static final String SET_PASSWORD_LINK = "set_password_link"; + public static final String VERIFY_EMAIL_LINK = "verify_email_link"; + public static final String LINK = "link"; + public static final String SET_PW_LINK = "setPasswordLink"; + public static final String SUNBIRD_URL_SHORTNER_ENABLE = "sunbird_url_shortner_enable"; + public static final String USER_PROFILE_CONFIG = "userProfileConfig"; + public static final String PUBLIC_FIELDS = "publicFields"; + public static final String PRIVATE_FIELDS = "privateFields"; + public static final String DEFAULT_PROFILE_FIELD_VISIBILITY = "defaultProfileFieldVisibility"; + + public static final String SUNBIRD_COURSE_BATCH_NOTIFICATIONS_ENABLED = + "sunbird_course_batch_notification_enabled"; + + public static final String BATCH_START_DATE = "batchStartDate"; + public static final String BATCH_END_DATE = "batchEndDate"; + public static final String BATCH_NAME = "batchName"; + public static final String BATCH_MENTOR_ENROL = "batchMentorEnrol"; + public static final String BATCH_LEARNER_ENROL = "batchLearnerEnrol"; + public static final String COURSE_INVITATION = "Course Invitation"; + public static final String BATCH_LEARNER_UNENROL = "batchLearnerUnenrol"; + public static final String BATCH_MENTOR_UNENROL = "batchMentorUnenrol"; + public static final String UNENROLL_FROM_COURSE_BATCH = "Unenrolled from Training"; + public static final String OPEN_BATCH_LEARNER_UNENROL = "openBatchLearnerUnenrol"; + + public static final String MENTOR = "mentor"; + public static final String OLD = "old"; + public static final String NEW = "new"; + public static final String COURSE_BATCH = "courseBatch"; + public static final String ADDED_MENTORS = "addedMentors"; + public static final String REMOVED_MENTORS = "removedMentors"; + public static final String ADDED_PARTICIPANTS = "addedParticipants"; + public static final String REMOVED_PARTICIPANTS = "removedParticipants"; + public static final String URL_QUERY_STRING = "urlQueryString"; + public static final String SUNBIRD_API_REQUEST_LOWER_CASE_FIELDS = + "sunbird_api_request_lower_case_fields"; + public static final String ATTRIBUTE = "attribute"; + public static final String ERRORS = "errors"; + public static final String ROLE_LIST = "roleList"; + public static final String SUNBIRD_USER_PROFILE_READ_EXCLUDED_FIELDS = "read.excludedFields"; + public static final String COMPLETED_ON = "completedOn"; + public static final String CALLER_ID = "callerId"; + public static final String USER_TYPE = "userType"; + + public static final String COURSE_BATCH_URL = "courseBatchUrl"; + public static final String SUNBIRD_COURSE_BATCH_NOTIFICATION_SIGNATURE = + "sunbird_course_batch_notification_signature"; + public static final String SIGNATURE = "signature"; + public static final String OPEN_BATCH_LEARNER_ENROL = "openBatchLearnerEnrol"; + public static final String CONTENT_PROPERTY_MEDIUM = "medium"; + public static final String CONTENT_PROPERTY_GRADE_LEVEL = "gradeLevel"; + public static final String CONTENT_PROPERTY_SUBJECT = "subject"; + public static final String CONTENT_PROPERTY_NAME = "name"; + public static final String CONTENT_PROPERTY_VISIBILITY = "visibility"; + public static final String CONTENT_PROPERTY_VISIBILITY_PARENT = "Parent"; + public static final String CONTENT_PROPERTY_MIME_TYPE = "mimeType"; + public static final String CONTENT_MIME_TYPE_COLLECTION = + "application/vnd.ekstep.content-collection"; + public static final String VERSION_KEY = "versionKey"; + public static final String CSV_SEPERATOR = ","; + public static final String CONTENT_CLOUD_STORAGE_TYPE = "sunbird_cloud_service_provider"; + public static final String CONTENT_CLOUD_STORAGE_CONTAINER = + "sunbird_content_cloud_storage_container"; + public static final String AZURE_STR = "azure"; + public static final String AWS_STR = "aws"; + public static final String GCLOUD_STR = "gcloud"; + + public static final String CLOUD_FOLDER_CONTENT = "sunbird_cloud_content_folder"; + public static final String CLOUD_STORE_BASE_PATH = "cloud_storage_base_url"; + public static final String CLOUD_STORAGE_CNAME_URL= "cloud_storage_cname_url"; + public static final String CLOUD_STORAGE_DIAL_BUCKET_NAME = "cloud_storage_dial_bucketname"; + public static final String DIAL_STORAGE_BASE_PATH_PLACEHOLDER="cloud_storage_path_prefix_dial"; + public static final String CLOUD_STORE_BASE_PATH_PLACEHOLDER = "cloud_store_base_path_placeholder"; + public static final String TO_URL = "toUrl"; + public static final String TTL = "ttl"; + public static final String TEXTBOOK_TOC_CSV_TTL = "sunbird_texbook_toc_csv_ttl"; + public static final String FILE_TYPE_CSV = "csv"; + + // Texbook TOC + public static final String TEXTBOOK = "textbook"; + public static final String TEXTBOOK_ID = "textbookId"; + public static final String MODE = "mode"; + public static final String MIME_TYPE = "mimeType"; + public static final String METADATA = "metadata"; + public static final String HIERARCHY = "hierarchy"; + public static final String FILE_DATA = "fileData"; + public static final String FRAMEWORK_METADATA = "frameworkCategories"; + public static final String TEXTBOOK_TOC_ALLOWED_MIMETYPE = + "application/vnd.ekstep.content-collection"; + public static final String TEXTBOOK_TOC_ALLOWED_CONTNET_TYPES = + "textbook_toc_allowed_content_types"; + public static final String TEXTBOOK_TOC_MAX_CSV_ROWS = "textbook_toc_max_csv_rows"; + public static final String TEXTBOOK_TOC_INPUT_MAPPING = "textbook_toc_input_mapping"; + public static final String NODES_MODIFIED = "nodesModified"; + public static final String TEXT_TOC_FILE_SUPPRESS_COLUMN_NAMES = + "textbook_toc_file_suppress_column_names"; + public static final String TEXTBOOK_TOC_MANDATORY_FIELDS = "textbook_toc_mandatory_fields"; + public static final String DOWNLOAD = "download"; + public static final String COLLECTION_MIME_TYPE = "application/vnd.ekstep.content-collection"; + public static final String TB_ROOT = "root"; + public static final String TB_IS_NEW = "isNew"; + public static final String KEYWORDS = "keywords"; + public static final String UNIT = "Unit"; + public static final String UPDATE_HIERARCHY_API = "sunbird_update_hierarchy_api"; + public static final String TB_MESSAGES = "messages"; + public static final String TNC_ACCEPTED_ON = "tncAcceptedOn"; + public static final String TNC_ACCEPTED_VERSION = "tncAcceptedVersion"; + public static final String TNC_LATEST_VERSION_URL = "tncLatestVersionUrl"; + public static final String PROMPT_TNC = "promptTnC"; + public static final String TNC_LATEST_VERSION = "tncLatestVersion"; + public static final String BULK_ORG_UPLOAD = "bulkOrgUpload"; + public static final String FRAMEWORKS = "frameworks"; + public static final String LATEST_VERSION = "latestVersion"; + public static final String TNC_CONFIG = "tncConfig"; + public static final String TNC = "tnc"; + public static final String ACCEPT = "accept"; + public static final String ROOT_ORG_NAME = "rootOrgName"; + public static final String OTP_EXPIRATION_IN_MINUTES = "otpExpiryInMinutes"; + public static final String SUNBIRD_USER_MAX_PHONE_LENGTH = "sunbird_user_max_phone_length"; + public static final String RATE_LIMIT = "rate_limit"; + public static final String RATE_LIMIT_UNIT = "unit"; + public static final String RATE = "rate"; + public static final String INSTALLATION_NAME = "installationName"; + public static final String LOCATION_CODES = "locationCodes"; + public static final String BATCH_DETAILS = "batchDetails"; + public static final String USER_LOCATIONS = "userLocations"; + public static final String DIAL_CODES = "dialcodes"; + public static final String DIAL_CODE_REQUIRED = "dialcodeRequired"; + public static final String NO = "No"; + public static final String YES = "Yes"; + public static final String QR_CODE_REQUIRED = "QR Code Required?"; + public static final String QR_CODE = "QR Code"; + public static final String RESERVED_DIAL_CODES = "reservedDialcodes"; + public static final String FRAMEWORK_READ_API_URL = "framework_read_api_url"; + public static final String DIAL_CODE_IDENTIFIER_MAP = "dialCodeIdentifierMap"; + public static final String LINK_DIAL_CODE_API = "sunbird_link_dial_code_api"; + public static final String LINKED_CONTENT = "linkedContent"; + public static final String MAX_ALLOWED_CONTENT_SIZE = "max_allowed_content_size"; + public static final String LINKED_CONTENT_COLUMN_KEY = "Linked Content"; + + public static final String BATCHES = "batches"; + public static final String ENROLLED_ON = "enrolledOn"; + public static final String LAST_ACCESSED_ON = "lastAccessedOn"; + public static final String OTHER = "OTHER"; + public static final String TEACHER = "TEACHER"; + public static final String USER_EXTERNAL_ID = "userExternalId"; + public static final String USER_ID_TYPE = "userIdType"; + public static final String USER_PROVIDER = "userProvider"; + public static final String SORTBY = "sortBy"; + public static final String SORT_ORDER = "sortOrder"; + public static final String NUMERIC = "NUMERIC"; + public static final String ASC = "asc"; + public static final String TERM = "term"; + public static final String DESC = "desc"; + public static final String SUNBIRD_TOC_LINKED_CONTENT_COLUMN_NAME = + "sunbird_toc_linked_content_column_name"; + public static final String SUNBIRD_TOC_MAX_FIRST_LEVEL_UNITS = + "sunbird_toc_max_first_level_units"; + public static final String TEXTBOOK_TOC_OUTPUT_MAPPING = "textbook_toc_output_mapping"; + public static final String TEXTBOOK_UNIT = "TextBookUnit"; + public static final String USER_NAME_HEADER = "User Name"; + public static final String ORG_NAME_HEADER = "Org Name"; + public static final String SCHOOL_NAME_HEADER = "School Name"; + public static final String COURSE_ENROLL_DATE_HEADER = "Enrollment Date"; + public static final String PROGRESS_HEADER = "Progress"; + public static final String SUNBIRD_CONTENT_SEARCH_URL = "sunbird_content_search_url"; + public static final String DATE_TIME_HEADER = "Date time stamp"; + public static final String PHONE_HEADER = "Mobile Number"; + public static final String EMAIL_HEADER = "Email Id"; + public static final String COURSE_PROGRESS_MAIL_TEMPLATE = "courseProgressMailTemplate"; + public static final String SUNBIRD_TIMEZONE = "sunbird_time_zone"; + public static final String COURSE_STAT_MAIL_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; + public static final String DATA_SOURCE = "dataSource"; + public static final String SUNBIRD_DIALCODE_SEARCH_API = "sunbird_dialcode_search_api"; + public static final String FROM_BEGINING = "fromBegining"; + public static final String SUNBIRD_KEYCLOAK_USER_FEDERATION_PROVIDER_ID = + "sunbird_keycloak_user_federation_provider_id"; + public static final String DEVICE_ID = "did"; + public static final String SUNBIRD_GZIP_FILTER_ENABLED = "sunbird_gzip_filter_enabled"; + public static final String COMPLETED_PERCENT = "completedPercent"; + public static final String PARTICIPANT_COUNT = "participantCount"; + public static final String BOARD = "board"; + public static final String MEDIUM = "medium"; + public static final String SUNBIRD_GZIP_ENABLE = "sunbird_gzip_enable"; + public static final String SHOW_DOWNLOAD_LINK = "showDownloadLink"; + public static final String SUNBIRD_SYNC_READ_WAIT_TIME = "sunbird_sync_read_wait_time"; + public static final String REPORT_UPDATED_ON = "reportUpdatedOn"; + public static final String SUNBIRD_GZIP_SIZE_THRESHOLD = "sunbird_gzip_size_threshold"; + public static final String PAGE_MANAGEMENT = "page_management"; + public static final String MAP_NAME = "mapName"; + public static final String PAGE_ASSEMBLE = "pageAssemble"; + public static final String SIGNUP_TYPE = "signupType"; + public static final String REQUEST_SOURCE = "source"; + + public static final String SUNBIRD_REDIS_CONN_POOL_SIZE = "sunbird_redis_connection_pool_size"; + public static final String RECIPIENT_PHONES = "recipientPhones"; + public static final String TCP = "tcp"; + public static final String REST = "rest"; + public static final String ES_OR_OPERATION = "$or"; + public static final String PREV_USED_EMAIL = "prevUsedEmail"; + public static final String PREV_USED_PHONE = "prevUsedPhone"; + public static final String MERGE_USER = "Mergeuser"; + public static final String FROM_ACCOUNT_ID = "fromAccountId"; + public static final String TO_ACCOUNT_ID = "toAccountId"; + public static final String MERGEE_ID = "mergeeId"; + public static final String USER_MERGEE_ACCOUNT = "userMergeeAccount"; + public static final String SEARCH_FUZZY = "fuzzy"; + public static final String CERT_ID = "certId"; + public static final String ACCESS_CODE = "accessCode"; + public static final String USER_CERT = "user_cert"; + public static final String STORE = "store"; + public static final String JSON = "json"; + public static final String PDF = "pdf"; + public static final String JSON_DATA = "jsonData"; + public static final String PDF_URL = "pdfURL"; + public static final String CREATED_AT = "createdAt"; + public static final String UPDATED_AT = "updatedAt"; + public static final String SIGN_KEYS = "signKeys"; + public static final String ENC_KEYS = "encKeys"; + public static final String SUNBIRD_STATE_IMG_URL = "sunbird_state_img_url"; + public static final String SUNBIRD_DIKSHA_IMG_URL = "sunbird_diksha_img_url"; + public static final String SUNBIRD_CERT_COMPLETION_IMG_URL = "sunbird_cert_completion_img_url"; + public static final String stateImgUrl = "stateImgUrl"; + public static final String dikshaImgUrl = "dikshaImgUrl"; + public static final String certificateImgUrl = "certificateImgUrl"; + public static final String X_AUTHENTICATED_USER_TOKEN = "x-authenticated-user-token"; + public static final String X_SOURCE_USER_TOKEN = "x-source-user-token"; + public static final String SUNBIRD_SUBDOMAIN_KEYCLOAK_BASE_URL = + "sunbird_subdomain_keycloak_base_url"; + public static final String ACTION = "action"; + public static final String ITERATION = "iteration"; + public static final String TELEMETRY_TARGET_USER_MERGE_TYPE = "MergeUserCoursesAndCert"; + public static final String TELEMETRY_PRODUCER_USER_MERGE_ID = "org.sunbird.platform"; + public static final String TELEMETRY_EDATA_USER_MERGE_ACTION = "merge-user-courses-and-cert"; + public static final String BE_JOB_REQUEST = "BE_JOB_REQUEST"; + public static final String TELEMETRY_ACTOR_USER_MERGE_ID = "Merge User Courses and Cert"; + public static final String SUNBIRD_COURSE_DIALCODES_DB = "sunbird_course_dialcodes_db"; + public static final String CERTIFICATE = "Certificate"; + public static final String OLD_CERTIFICATE = "oldCertificate"; + public static final String MERGE_CERT = "Mergecert"; + public static final String RECOVERY_EMAIL = "recoveryEmail"; + public static final String RECOVERY_PHONE = "recoveryPhone"; + public static final String SUPPORTED_COlUMNS = "supportedColumns"; + public static final String INPUT_STATUS = "input status"; + public static final String EXTERNAL_USER_ID = "ext user id"; + public static final String EXTERNAL_ORG_ID = "ext org id"; + public static final String MIGRATION_USER_OBJECT = "MigrationUser"; + public static final String TASK_COUNT = "taskCount";; + public static final String NESTED_KEY_FILTER = "nestedFilters"; + public static final String SHADOW_USER = "shadow_user"; + public static final String USER_EXT_ID = "userExtId"; + public static final String ORG_EXT_ID = "orgExtId"; + public static final String STATE_VALIDATED = "stateValidated"; + public static final String FLAGS_VALUE = "flagsValue"; + public static final String USER_STATUS = "userStatus"; + public static final String CLAIM_STATUS = "claimStatus"; + public static final String CLAIMED_ON = "claimedOn"; + public static final String SMS = "sms"; + public static final String CONTEXT_TELEMETRY = "telemetryContext"; + public static final String OLD_ID = "oldId"; + public static final String MAX_ATTEMPT = "maxAttempt"; + public static final String REMAINING_ATTEMPT = "remainingAttempt"; + public static final String IS_SSO_ROOTORG_ENABLED = "isSSOEnabled"; + public static final String USER_FEED_DB = "user_feed"; + public static final String USER_FEED = "userFeed"; + public static final String FEED_DATA = "data"; + public static final String REJECT = "reject"; + public static final String FEED_ID = "feedId"; + public static final String LICENSE = "license"; + public static final String DEFAULT_LICENSE = "defaultLicense"; + public static final String SUNBIRD_PASS_REGEX = "sunbird_pass_regex"; + public static final String NESTED_EXISTS = "nested_exists"; + public static final String NESTED_NOT_EXISTS = "nested_not_exists"; + public static final String PROSPECT_CHANNELS = "prospectChannels"; + public static final String PROSPECT_CHANNELS_IDS = "prospectChannelsIds"; + public static final String CATEGORY = "category"; + public static final String TEMPLATE_ID = "templateId"; + public static final String TEMPLATE_ID_VALUE = "resetPasswordWithOtp"; + public static final String VERSION_3 = "v3"; + public static final String LEARNING_SERVICE_BASE_URL = "learning_service_base_url"; + public static final String CREATOR_DETAILS_FIELDS = "sunbird_user_search_cretordetails_fields"; + public static final String USER_SEARCH_BASE_URL = "sunbird_user_service_api_base_url"; + public static final String SUNBIRD_QRCODE_COURSES_LIMIT ="sunbird_user_qrcode_courses_limit"; + public static final String ACCESS_TOKEN_PUBLICKEY_BASEPATH = "accesstoken.publickey.basepath"; + public static final String ACCESS_TOKEN_PUBLICKEY_KEYPREFIX = "accesstoken.publickey.keyprefix"; + public static final String ACCESS_TOKEN_PUBLICKEY_KEYCOUNT = "accesstoken.publickey.keycount"; + public static final String SHA_256_WITH_RSA = "SHA256withRSA"; + public static final String SUB = "sub"; + public static final String DOT_SEPARATOR = "."; + public static final String REQUESTED_FOR = "requestedFor"; + public static final String CONTENT_PROPS_TO_ADD ="learning.content.props.to.add"; + public static final String GROUP_ACTIVITY_DB = "groupActivityDB"; + public static final String ACTIVITYID = "activityId"; + public static final String ACTIVITYTYPE = "activityType"; + public static final String ACTIVITY_ID = "activity_id"; + public static final String ACTIVITY_TYPE = "activity_type"; + public static final String GROUP_SERVICE_API_BASE_URL ="sunbird_group_service_api_base_url"; + public static final String GROUP_MEMBERS_METADATA ="group.members.metadata"; + public static final String COLLECTION_ID = "collectionId"; + public static final String TRACKABLE_ENABLED = "trackable.enabled"; + public static final String GROUPBY = "groupBy"; + public static final String X_AUTH_TOKEN = "X_AUTH_TOKEN"; + public static final String TEMPLATE = "template"; + public static final String ASSESSMENT_AGGREGATOR_DB = "assessment_aggregator_db"; + public static final String SERVICE_NAME = "course-service"; + public static final String PRODUCER_NAME = "org.sunbird.course-service"; + public static final String PID = "course-service"; + public static final String P_VERSION = "1.0"; + public static final String X_DEVICE_ID = "x-device-id"; + public static final String X_SESSION_ID = "x-session-id"; + public static final String X_TRACE_ID = "x-trace-id"; + public static final String USER_ENROLMENTS_DB = "user_enrolments"; + public static final List<String> CHANGE_IN_SIMPLE_DATE_FORMAT = Arrays.asList("startDate", "endDate", "enrollmentEndDate"); + public static final List<String> CHANGE_IN_DATE_FORMAT = Arrays.asList("createdDate", "updatedDate"); + public static final List<String> CHANGE_IN_DATE_FORMAT_ALL = Arrays.asList("startDate", "endDate", "enrollmentEndDate", "createdDate", "updatedDate"); + public static final String OLD_START_DATE = "oldStartDate"; + public static final String OLD_END_DATE = "oldEndDate"; + public static final String OLD_ENROLLMENT_END_DATE = "oldEnrollmentEndDate"; + public static final String OLD_LAST_ACCESS_TIME = "oldLastAccessTime"; + public static final String OLD_LAST_COMPLETED_TIME = "oldLastCompletedTime"; + public static final String OLD_LAST_UPDATED_TIME = "oldLastUpdatedTime"; + public static final String COURSE_ID_KEY = "courseid"; + public static final String CONTENT_ID_KEY = "contentid"; + public static final String LAST_ACCESS_TIME_KEY = "last_access_time"; + public static final List<String> SET_END_OF_DAY = Arrays.asList("endDate", "enrollmentEndDate"); + public static final String BATCH_ID_KEY = "batchid"; + public static final String USER_ID_KEY = "userid"; + public static final String OLD_CREATED_DATE = "oldCreatedDate"; + public static final String X_LOGGING_HEADERS = "X_LOGGING_HEADERS"; + public static final String LAST_CONTENT_ACCESS_TIME = "lastcontentaccesstime"; + public static final String GCP="gcloud"; + public static final String TEMPLATE_URL = "templateUrl"; + public static final String SUNBIRD_DIAL_SERVICE_BASE_URL = "sunbird_dial_service_base_url"; + public static final String SUNBIRD_DIAL_SERVICE_SEARCH_URL = "sunbird_dial_service_search_url"; + public static final String AUTH_ENABLED = "AuthenticationEnabled"; + + private JsonKey() {} +} diff --git a/validate-api/validate-service/app/utils/QuestionOperations.scala b/validate-api/validate-service/app/utils/QuestionOperations.scala new file mode 100644 index 000000000..ab3cea870 --- /dev/null +++ b/validate-api/validate-service/app/utils/QuestionOperations.scala @@ -0,0 +1,6 @@ +package utils + +object QuestionOperations extends Enumeration { + val createQuestion, readQuestion, readPrivateQuestion, updateQuestion, + reviewQuestion, publishQuestion, retireQuestion, importQuestion, systemUpdateQuestion, listQuestions, rejectQuestion = Value +} diff --git a/validate-api/validate-service/app/utils/RequestContext.java b/validate-api/validate-service/app/utils/RequestContext.java new file mode 100644 index 000000000..3f51d3084 --- /dev/null +++ b/validate-api/validate-service/app/utils/RequestContext.java @@ -0,0 +1,87 @@ +package utils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class RequestContext { + + private String uid; + private String did; + private String sid; + private String debugEnabled; + private String actorId; + private String actorType; + private String loggerLevel; + private String requestId; + private String env; + private Map<String, Object> contextMap = new HashMap<>(); + private String channel; + private Map<String, Object> pdata = new HashMap<>(); + + public RequestContext(String channel, String pdataId, String env, String did, String sid, String pid, String pver, List<Object> cdata) { + this.did = did; + this.sid = sid; + this.channel = channel; + this.pdata.put("id", pdataId); + this.pdata.put("pid", pid); + this.pdata.put("ver", pver); + this.contextMap.putAll(new HashMap<String, Object>() {{ + put("did", did); + put("sid", sid); + put("channel", channel); + put("env", env); + put("pdata", pdata); + if (cdata != null) + put("cdata", cdata); + }}); + } + + public String getActorId() { + return actorId; + } + + public void setActorId(String actorId) { + this.actorId = actorId; + } + + public String getActorType() { + return actorType; + } + + public void setActorType(String actorType) { + this.actorType = actorType; + } + + public String getLoggerLevel() { + return loggerLevel; + } + + public void setLoggerLevel(String loggerLevel) { + this.loggerLevel = loggerLevel; + } + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public String getDebugEnabled() { + return debugEnabled; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public Map<String, Object> getContextMap() { + return contextMap; + } +} diff --git a/validate-api/validate-service/conf/application.conf b/validate-api/validate-service/conf/application.conf new file mode 100644 index 000000000..a2e0cc367 --- /dev/null +++ b/validate-api/validate-service/conf/application.conf @@ -0,0 +1,407 @@ +# This is the main configuration file for the application. +# https://www.playframework.com/documentation/latest/ConfigFile +# ~~~~~ +# Play uses HOCON as its configuration file format. HOCON has a number +# of advantages over other config formats, but there are two things that +# can be used when modifying settings. +# +# You can include other configuration files in this main application.conf file: +#include "extra-config.conf" +# +# You can declare variables and substitute for them: +#mykey = ${some.value} +# +# And if an environment variable exists when there is no other substitution, then +# HOCON will fall back to substituting environment variable: +#mykey = ${JAVA_HOME} + +## Akka +# https://www.playframework.com/documentation/latest/ScalaAkka#Configuration +# https://www.playframework.com/documentation/latest/JavaAkka#Configuration +# ~~~~~ +# Play uses Akka internally and exposes Akka Streams and actors in Websockets and +# other streaming HTTP responses. +akka { + # "akka.log-config-on-start" is extraordinarly useful because it log the complete + # configuration at INFO level, including defaults and overrides, so it s worth + # putting at the very top. + # + # Put the following in your conf/logback.xml file: + # + # <logger name="akka.actor" level="INFO" /> + # + # And then uncomment this line to debug the configuration. + # + #log-config-on-start = true + default-dispatcher { + # This will be used if you have set "executor = "fork-join-executor"" + fork-join-executor { + # Min number of threads to cap factor-based parallelism number to + parallelism-min = 8 + + # The parallelism factor is used to determine thread pool size using the + # following formula: ceil(available processors * factor). Resulting size + # is then bounded by the parallelism-min and parallelism-max values. + parallelism-factor = 32.0 + + # Max number of threads to cap factor-based parallelism number to + parallelism-max = 64 + + # Setting to "FIFO" to use queue like peeking mode which "poll" or "LIFO" to use stack + # like peeking mode which "pop". + task-peeking-mode = "FIFO" + } + } + actors-dispatcher { + type = "Dispatcher" + executor = "fork-join-executor" + fork-join-executor { + parallelism-min = 8 + parallelism-factor = 32.0 + parallelism-max = 64 + } + # Throughput for default Dispatcher, set to 1 for as fair as possible + throughput = 1 + } + actor { + deployment { + /healthActor + { + router = smallest-mailbox-pool + nr-of-instances = 5 + dispatcher = actors-dispatcher + } + + } + } +} + +## Secret key +# http://www.playframework.com/documentation/latest/ApplicationSecret +# ~~~~~ +# The secret key is used to sign Play's session cookie. +# This must be changed for production, but we don't recommend you change it in this file. +play.http.secret.key= a-long-secret-to-calm-the-rage-of-the-entropy-gods + +## Modules +# https://www.playframework.com/documentation/latest/Modules +# ~~~~~ +# Control which modules are loaded when Play starts. Note that modules are +# the replacement for "GlobalSettings", which are deprecated in 2.5.x. +# Please see https://www.playframework.com/documentation/latest/GlobalSettings +# for more information. +# +# You can also extend Play functionality by using one of the publically available +# Play modules: https://playframework.com/documentation/latest/ModuleDirectory +play.modules { + # By default, Play will load any class called Module that is defined + # in the root package (the "app" directory), or you can define them + # explicitly below. + # If there are any built-in modules that you want to enable, you can list them here. + #enabled += my.application.Module + + # If there are any built-in modules that you want to disable, you can list them here. + #disabled += "" + enabled += modules.AssessmentModule +} + +## IDE +# https://www.playframework.com/documentation/latest/IDE +# ~~~~~ +# Depending on your IDE, you can add a hyperlink for errors that will jump you +# directly to the code location in the IDE in dev mode. The following line makes +# use of the IntelliJ IDEA REST interface: +#play.editor="http://localhost:63342/api/file/?file=%s&line=%s" + +## Internationalisation +# https://www.playframework.com/documentation/latest/JavaI18N +# https://www.playframework.com/documentation/latest/ScalaI18N +# ~~~~~ +# Play comes with its own i18n settings, which allow the user's preferred language +# to map through to internal messages, or allow the language to be stored in a cookie. +play.i18n { + # The application languages + langs = [ "en" ] + + # Whether the language cookie should be secure or not + #langCookieSecure = true + + # Whether the HTTP only attribute of the cookie should be set to true + #langCookieHttpOnly = true +} + +## Play HTTP settings +# ~~~~~ +play.http { + ## Router + # https://www.playframework.com/documentation/latest/JavaRouting + # https://www.playframework.com/documentation/latest/ScalaRouting + # ~~~~~ + # Define the Router object to use for this application. + # This router will be looked up first when the application is starting up, + # so make sure this is the entry point. + # Furthermore, it's assumed your route file is named properly. + # So for an application router like `my.application.Router`, + # you may need to define a router file `conf/my.application.routes`. + # Default to Routes in the root package (aka "apps" folder) (and conf/routes) + #router = my.application.Router + + ## Action Creator + # https://www.playframework.com/documentation/latest/JavaActionCreator + # ~~~~~ + #actionCreator = null + + ## ErrorHandler + # https://www.playframework.com/documentation/latest/JavaRouting + # https://www.playframework.com/documentation/latest/ScalaRouting + # ~~~~~ + # If null, will attempt to load a class called ErrorHandler in the root package, + #errorHandler = null + + ## Session & Flash + # https://www.playframework.com/documentation/latest/JavaSessionFlash + # https://www.playframework.com/documentation/latest/ScalaSessionFlash + # ~~~~~ + session { + # Sets the cookie to be sent only over HTTPS. + #secure = true + + # Sets the cookie to be accessed only by the server. + #httpOnly = true + + # Sets the max-age field of the cookie to 5 minutes. + # NOTE: this only sets when the browser will discard the cookie. Play will consider any + # cookie value with a valid signature to be a valid session forever. To implement a server side session timeout, + # you need to put a timestamp in the session and check it at regular intervals to possibly expire it. + #maxAge = 300 + + # Sets the domain on the session cookie. + #domain = "example.com" + } + + flash { + # Sets the cookie to be sent only over HTTPS. + #secure = true + + # Sets the cookie to be accessed only by the server. + #httpOnly = true + } +} + +play.server.http.idleTimeout = 60s +play.http.parser.maxDiskBuffer = 10MB +parsers.anyContent.maxLength = 10MB + +## Netty Provider +# https://www.playframework.com/documentation/latest/SettingsNetty +# ~~~~~ +play.server.netty { + # Whether the Netty wire should be logged + log.wire = true + + # If you run Play on Linux, you can use Netty's native socket transport + # for higher performance with less garbage. + transport = "native" +} + +## WS (HTTP Client) +# https://www.playframework.com/documentation/latest/ScalaWS#Configuring-WS +# ~~~~~ +# The HTTP client primarily used for REST APIs. The default client can be +# configured directly, but you can also create different client instances +# with customized settings. You must enable this by adding to build.sbt: +# +# libraryDependencies += ws // or javaWs if using java +# +play.ws { + # Sets HTTP requests not to follow 302 requests + #followRedirects = false + + # Sets the maximum number of open HTTP connections for the client. + #ahc.maxConnectionsTotal = 50 + + ## WS SSL + # https://www.playframework.com/documentation/latest/WsSSL + # ~~~~~ + ssl { + # Configuring HTTPS with Play WS does not require programming. You can + # set up both trustManager and keyManager for mutual authentication, and + # turn on JSSE debugging in development with a reload. + #debug.handshake = true + #trustManager = { + # stores = [ + # { type = "JKS", path = "exampletrust.jks" } + # ] + #} + } +} + +## Cache +# https://www.playframework.com/documentation/latest/JavaCache +# https://www.playframework.com/documentation/latest/ScalaCache +# ~~~~~ +# Play comes with an integrated cache API that can reduce the operational +# overhead of repeated requests. You must enable this by adding to build.sbt: +# +# libraryDependencies += cache +# +play.cache { + # If you want to bind several caches, you can bind the individually + #bindCaches = ["db-cache", "user-cache", "session-cache"] +} + +## Filter Configuration +# https://www.playframework.com/documentation/latest/Filters +# ~~~~~ +# There are a number of built-in filters that can be enabled and configured +# to give Play greater security. +# +play.filters { + + # Enabled filters are run automatically against Play. + # CSRFFilter, AllowedHostFilters, and SecurityHeadersFilters are enabled by default. + enabled = [filters.AccessLogFilter] + + # Disabled filters remove elements from the enabled list. + # disabled += filters.CSRFFilter + + + ## CORS filter configuration + # https://www.playframework.com/documentation/latest/CorsFilter + # ~~~~~ + # CORS is a protocol that allows web applications to make requests from the browser + # across different domains. + # NOTE: You MUST apply the CORS configuration before the CSRF filter, as CSRF has + # dependencies on CORS settings. + cors { + # Filter paths by a whitelist of path prefixes + #pathPrefixes = ["/some/path", ...] + + # The allowed origins. If null, all origins are allowed. + #allowedOrigins = ["http://www.example.com"] + + # The allowed HTTP methods. If null, all methods are allowed + #allowedHttpMethods = ["GET", "POST"] + } + + ## Security headers filter configuration + # https://www.playframework.com/documentation/latest/SecurityHeaders + # ~~~~~ + # Defines security headers that prevent XSS attacks. + # If enabled, then all options are set to the below configuration by default: + headers { + # The X-Frame-Options header. If null, the header is not set. + #frameOptions = "DENY" + + # The X-XSS-Protection header. If null, the header is not set. + #xssProtection = "1; mode=block" + + # The X-Content-Type-Options header. If null, the header is not set. + #contentTypeOptions = "nosniff" + + # The X-Permitted-Cross-Domain-Policies header. If null, the header is not set. + #permittedCrossDomainPolicies = "master-only" + + # The Content-Security-Policy header. If null, the header is not set. + #contentSecurityPolicy = "default-src 'self'" + } + + ## Allowed hosts filter configuration + # https://www.playframework.com/documentation/latest/AllowedHostsFilter + # ~~~~~ + # Play provides a filter that lets you configure which hosts can access your application. + # This is useful to prevent cache poisoning attacks. + hosts { + # Allow requests to example.com, its subdomains, and localhost:9000. + #allowed = [".example.com", "localhost:9000"] + } +} + +play.http.parser.maxMemoryBuffer = 50MB +akka.http.parsing.max-content-length = 50MB +schema.base_path="../../schemas/" + +# Cassandra Configuration +cassandra.lp.connection="127.0.0.1:9042" +#content.keyspace = "content_store" +content.keyspace = "dev_content_store" + +# Redis Configuration +redis.host="localhost" +redis.port=6379 +redis.maxConnections=128 + +# Graph Configuration +graph.dir=/data/testingGraphDB +akka.request_timeout=30 +environment.id=10000000 +graph.ids=["domain"] +graph.passport.key.base=31b6fd1c4d64e745c867e61a45edc34a +route.domain="bolt://localhost:7687" +route.bolt.write.domain="bolt://localhost:7687" +route.bolt.read.domain="bolt://localhost:7687" +route.bolt.comment.domain="bolt://localhost:7687" +route.all="bolt://localhost:7687" +route.bolt.write.all="bolt://localhost:7687" +route.bolt.read.all="bolt://localhost:7687" +route.bolt.comment.all="bolt://localhost:7687" + +shard.id=1 +platform.auth.check.enabled=false +platform.cache.ttl=3600000 + +#Top N Config for Search Telemetry +telemetry_env=dev + +installation.id=ekstep + + +languageCode { + assamese : "as" + bengali : "bn" + english : "en" + gujarati : "gu" + hindi : "hi" + kannada : "ka" + marathi : "mr" + odia : "or" + tamil : "ta" + telugu : "te" +} + +kafka { + urls : "localhost:9092" + topic.send.enable : true + topics.instruction : "sunbirddev.assessment.publish.request" +} +objectcategorydefinition.keyspace="dev_category_store" +question { + keyspace = "dev_question_store" + list.limit=20 +} +questionset.keyspace="dev_hierarchy_store" + +cassandra { + lp { + connection: "localhost:9042" + } + lpa { + connection: "localhost:9042" + } +} +neo4j_objecttypes_enabled=["Question"] + +import { + request_size_limit = 200 + output_topic_name = "local.auto.creation.job.request" + required_props { + question = ["name", "code", "mimeType", "framework", "channel"] + questionset = ["name", "code", "mimeType", "framework", "channel"] + } + remove_props { + question = [] + questionset = [] + } +} + +root_node_visibility=["Default","Private"] \ No newline at end of file diff --git a/validate-api/validate-service/conf/logback.xml b/validate-api/validate-service/conf/logback.xml new file mode 100644 index 000000000..73529d622 --- /dev/null +++ b/validate-api/validate-service/conf/logback.xml @@ -0,0 +1,28 @@ +<configuration> + + <conversionRule conversionWord="coloredLevel" converterClass="play.api.libs.logback.ColoredLevel" /> + + <!-- transaction-event-trigger START --> + <timestamp key="timestamp" datePattern="yyyy-MM-dd"/> + <!-- common transactions logs --> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>%d %msg%n</pattern> + </encoder> + </appender> + + <appender name="ASYNCSTDOUT" class="ch.qos.logback.classic.AsyncAppender"> + <appender-ref ref="STDOUT" /> + </appender> + + + <logger name="play" level="INFO" /> + <logger name="DefaultPlatformLogger" level="INFO" /> + <!-- Telemetry Loggers--> + <logger name="TelemetryEventLogger" level="INFO" /> + + <root level="INFO"> + <appender-ref ref="ASYNCSTDOUT" /> + </root> + +</configuration> \ No newline at end of file diff --git a/validate-api/validate-service/conf/routes b/validate-api/validate-service/conf/routes new file mode 100644 index 000000000..9fac2a84a --- /dev/null +++ b/validate-api/validate-service/conf/routes @@ -0,0 +1,8 @@ +# Routes +# This file defines all application routes (Higher priority routes first) +# ~~~~ +GET /health controllers.HealthController.health +GET /service/health controllers.HealthController.serviceHealth + + +PATCH /v1/question/assestment/validate @controllers.QuestionValidateController.assessment(request: play.mvc.Http.Request) diff --git a/validate-api/validate-service/pom.xml b/validate-api/validate-service/pom.xml new file mode 100644 index 000000000..570ad27ed --- /dev/null +++ b/validate-api/validate-service/pom.xml @@ -0,0 +1,188 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>validate-api</artifactId> + <groupId>org.sunbird</groupId> + <version>1.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>validate-service</artifactId> + <packaging>play2</packaging> + + <repositories> + <repository> + <id>scalaz-bintray</id> + <name>Scalaz Bintray - releases</name> + <url>https://dl.bintray.com/scalaz/releases/</url> + <snapshots> + <enabled>false</enabled> + </snapshots> + </repository> + </repositories> + <pluginRepositories> + <pluginRepository> + <id>typesafe-releases-plugins</id> + <url>https://repo.typesafe.com/typesafe/releases/</url> + <snapshots> + <enabled>false</enabled> + </snapshots> + </pluginRepository> + </pluginRepositories> + <properties> + <play2.version>2.7.2</play2.version> + <play2.plugin.version>1.0.0-rc5</play2.plugin.version> + <sbt-compiler.plugin.version>1.0.0</sbt-compiler.plugin.version> + </properties> + + <dependencies> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>18.0</version> + </dependency> + <dependency> + <groupId>com.google.inject</groupId> + <artifactId>guice</artifactId> + <version>3.0</version> + </dependency> + <dependency> + <groupId>com.google.inject.extensions</groupId> + <artifactId>guice-assistedinject</artifactId> + <version>3.0</version> + </dependency> + <dependency> + <groupId>com.typesafe.play</groupId> + <artifactId>play_${scala.major.version}</artifactId> + <version>${play2.version}</version> + <exclusions> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.typesafe.play</groupId> + <artifactId>play-guice_${scala.major.version}</artifactId> + <version>${play2.version}</version> + <exclusions> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>com.typesafe.play</groupId> + <artifactId>filters-helpers_${scala.major.version}</artifactId> + <version>${play2.version}</version> + </dependency> + <dependency> + <groupId>com.typesafe.play</groupId> + <artifactId>play-logback_${scala.major.version}</artifactId> + <version>${play2.version}</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>com.typesafe.play</groupId> + <artifactId>play-netty-server_${scala.major.version}</artifactId> + <version>${play2.version}</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>org.scala-lang</groupId> + <artifactId>scala-library</artifactId> + <version>${scala.version}</version> + </dependency> + <dependency> + <groupId>org.sunbird</groupId> + <artifactId>assessment-actors</artifactId> + <version>1.0-SNAPSHOT</version> + <type>jar</type> + <exclusions> + <exclusion> + <artifactId>slf4j-log4j12</artifactId> + <groupId>org.slf4j</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.scalatest</groupId> + <artifactId>scalatest_${scala.maj.version}</artifactId> + <version>3.1.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.typesafe.play</groupId> + <artifactId>play-specs2_${scala.maj.version}</artifactId> + <version>${play2.version}</version> + <scope>test</scope> + <exclusions> + <exclusion> + <artifactId>guava</artifactId> + <groupId>com.google.guava</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.joda</groupId> + <artifactId>joda-convert</artifactId> + <version>2.2.1</version> + </dependency> + <dependency> + <groupId>com.github.danielwegener</groupId> + <artifactId>logback-kafka-appender</artifactId> + <version>0.2.0-RC2</version> + </dependency> + </dependencies> + <build> + <sourceDirectory>${basedir}/app</sourceDirectory> + <testSourceDirectory>${basedir}/test</testSourceDirectory> + <resources> + <resource> + <directory>${basedir}/conf</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>3.0.0-M4</version> + <configuration> + <includes> + <include>**/*Spec.java</include> + <include>**/*Test.java</include> + </includes> + </configuration> + </plugin> + <plugin> + <groupId>com.google.code.play2-maven-plugin</groupId> + <artifactId>play2-maven-plugin</artifactId> + <version>${play2.plugin.version}</version> + <extensions>true</extensions> + </plugin> + <plugin> + <groupId>com.google.code.sbt-compiler-maven-plugin</groupId> + <artifactId>sbt-compiler-maven-plugin</artifactId> + <version>${sbt-compiler.plugin.version}</version> + <configuration> + <scalacOptions>-feature -deprecation -Xfatal-warnings</scalacOptions> + </configuration> + </plugin> + <plugin> + <groupId>org.scoverage</groupId> + <artifactId>scoverage-maven-plugin</artifactId> + <version>${scoverage.plugin.version}</version> + <configuration> + <scalaVersion>${scala.version}</scalaVersion> + <aggregate>true</aggregate> + <highlighting>true</highlighting> + <excludedFiles>.*RoutesPrefix.*;.*Routes.*;.*javascript.*</excludedFiles> + </configuration> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file diff --git a/validate-api/validate-service/test/controllers/base/BaseSpec.scala b/validate-api/validate-service/test/controllers/base/BaseSpec.scala new file mode 100644 index 000000000..883693c86 --- /dev/null +++ b/validate-api/validate-service/test/controllers/base/BaseSpec.scala @@ -0,0 +1,38 @@ +package controllers.base + +import com.typesafe.config.ConfigFactory +import modules.TestModule +import org.specs2.mutable.Specification +import play.api.inject.guice.GuiceApplicationBuilder +import play.api.libs.json.Json +import play.api.mvc.Result +import play.api.test.Helpers.{POST, contentAsString, contentType, defaultAwaitTimeout, route, status, _} +import play.api.test.{FakeHeaders, FakeRequest} + +import scala.concurrent.Future + +class BaseSpec extends Specification { + implicit val app = new GuiceApplicationBuilder() + .disable(classOf[modules.AssessmentModule]) + .bindings(new TestModule) + .build + implicit val config = ConfigFactory.load() + + def post(apiURL: String, request: String, h: FakeHeaders = FakeHeaders(Seq())) + : Future[Result] = { + val headers = h.add(("content-type", "application/json")) + route(app, FakeRequest(POST, apiURL, headers, Json.toJson(Json.parse(request)))).get + } + + def isOK(response: Future[Result]) { + status(response) must equalTo(OK) + contentType(response) must beSome.which(_ == "application/json") + contentAsString(response) must contain(""""status":"successful"""") + } + + def hasClientError(response: Future[Result]) { + status(response) must equalTo(BAD_REQUEST) + contentType(response) must beSome.which(_ == "application/json") + contentAsString(response) must contain(""""err":"CLIENT_ERROR","status":"failed"""") + } +} diff --git a/validate-api/validate-service/test/controllers/v3/HealthControllerSpec.scala b/validate-api/validate-service/test/controllers/v3/HealthControllerSpec.scala new file mode 100644 index 000000000..49f351a62 --- /dev/null +++ b/validate-api/validate-service/test/controllers/v3/HealthControllerSpec.scala @@ -0,0 +1,18 @@ +package controllers.v3 + +import controllers.base.BaseSpec +import org.junit.runner.RunWith +import org.specs2.runner.JUnitRunner +import play.api.test.{FakeRequest, Helpers} +import play.api.test.Helpers.{OK, status} + +@RunWith(classOf[JUnitRunner]) +class HealthControllerSpec extends BaseSpec { + + "return api health status report - successful response" in { + val controller = app.injector.instanceOf[controllers.HealthController] + val result = controller.health()(FakeRequest()) + isOK(result) + status(result)(Helpers.defaultAwaitTimeout) must equalTo(OK) + } +} diff --git a/validate-api/validate-service/test/modules/TestModule.scala b/validate-api/validate-service/test/modules/TestModule.scala new file mode 100644 index 000000000..3799b17c6 --- /dev/null +++ b/validate-api/validate-service/test/modules/TestModule.scala @@ -0,0 +1,26 @@ +package modules + +import com.google.inject.AbstractModule +import org.sunbird.actor.core.BaseActor +import org.sunbird.common.dto.{Request, Response, ResponseHandler} +import play.libs.akka.AkkaGuiceSupport +import utils.ActorNames + +import scala.concurrent.{ExecutionContext, Future} + +class TestModule extends AbstractModule with AkkaGuiceSupport { + override def configure(): Unit = { + bindActor(classOf[TestActor], ActorNames.HEALTH_ACTOR) + + println("Test Module is initialized...") + } +} + +class TestActor extends BaseActor { + + implicit val ec: ExecutionContext = getContext().dispatcher + + override def onReceive(request: Request): Future[Response] = { + Future(ResponseHandler.OK) + } +} -- GitLab