Merge remote-tracking branch 'upstream/master'

merge-requests/1/head
susinda 8 years ago
commit 12c12067c7

@ -1,13 +1,7 @@
<api xmlns="http://ws.apache.org/ns/synapse" name="$!apiName" context="$!apiContext" transports="$!transport">
#foreach($resource in $resources)
<resource xmlns="http://ws.apache.org/ns/synapse"
#if($resource.getUriTemplate().contains("{") ||
($resource.getUriTemplate().contains("*") && !$resource.getUriTemplate().endsWith("/*")))
uri-template="$util.escapeXml($resource.getUriTemplate())"
#else
url-mapping="$resource.getUriTemplate()"
#end
methods="$resource.getMethodsAsString()" faultSequence="fault">
<resource methods="POST PATCH GET DELETE HEAD PUT OPTIONS"
url-mapping="/*"
faultSequence="fault">
<inSequence>
<property name="isDefault" expression="$trp:WSO2_AM_API_DEFAULT_VERSION"/>
<filter source="$ctx:isDefault" regex="true">
@ -72,7 +66,6 @@
<send/>
</outSequence>
</resource>
#end ## end of resource iterator
<handlers>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.common.SynapsePropertiesHandler"/>
</handlers>

@ -76,16 +76,32 @@
</markForSuspension>
#end
#macro ( http_endpoint $name $ep )
#macro ( http_endpoint $name $ep )
<endpoint name="$name">
<http uri-template="$util.escapeXml($ep.get("url"))">
#timeout( $ep.get('config') )
</http>
#if($destinationBasedStatsEnabled)
<property name="ENDPOINT_ADDRESS" value="$util.escapeXml($ep.get("url"))"/>
#end
</endpoint>
#end
<http uri-template="$util.escapeXml($ep.get("url"))">
#timeout( $ep.get('config') )
</http>
<property name="ENDPOINT_ADDRESS" value="$util.escapeXml($ep.get("url"))"/>
</endpoint>
#end
#macro ( address_endpoint $name $ep )
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="$name">
#set( $advance_ep = $ep.get("config") )
<address uri="$util.escapeXml($ep.get("url"))"
#if($advance_ep.get("format") && $advance_ep.get("format") != "" && $advance_ep.get("format") != 'leave-as-is')
format="$advance_ep.get("format")"
#end
#if($advance_ep.get("optimize") && $advance_ep.get("optimize") != "" && $advance_ep.get("optimize") != 'leave-as-is')
optimize="$advance_ep.get("optimize")"
#end
>
#timeout( $ep.get('config') )
</address>
<property name="ENDPOINT_ADDRESS" value="$util.escapeXml($ep.get("url"))"/>
</endpoint>
#end
#macro ( draw_endpoint $type $endpoint_config )
@ -157,9 +173,7 @@
>
#timeout( $endpoints.get('config') )
</address>
#if($destinationBasedStatsEnabled)
<property name="ENDPOINT_ADDRESS" value="$util.escapeXml($endpoints.get("url"))"/>
#end
</endpoint>
#elseif ($endpointClass == "wsdl")
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="$ep_name">
@ -172,19 +186,25 @@
#timeout()
</wsdl>
#end
#if($destinationBasedStatsEnabled)
<property name="ENDPOINT_ADDRESS" value="$util.escapeXml($endpoints.get("url"))"/>
#end
</endpoint>
#elseif ($endpointClass == "failover")
#set( $failover_endpoints = $endpoint_config.get("${type}_failovers"))
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="$ep_name">
<failover>
#http_endpoint("${ep_name}_0" $endpoints)
#if($endpoints.get("endpoint_type") == "address")
#address_endpoint("${ep_name}_0" $endpoints)
#else
#http_endpoint("${ep_name}_0" $endpoints)
#end
#set( $i = 1)
#foreach($endpoint in $failover_endpoints)
#http_endpoint("${ep_name}_$i" $endpoint)
#set( $i = $i + 1)
#if($endpoint.get("endpoint_type") == "address")
#address_endpoint("${ep_name}_$i" $endpoint)
#else
#http_endpoint("${ep_name}_$i" $endpoint)
#end
#set( $i = $i + 1)
#end
</failover>
</endpoint>
@ -203,8 +223,12 @@
#end>
#set( $i = 0)
#foreach($endpoint in $endpoints)
#http_endpoint("${ep_name}_$i" $endpoint)
#set( $i = $i + 1)
#if($endpoint.get("endpoint_type") == "address")
#address_endpoint("${ep_name}_$i" $endpoint)
#else
#http_endpoint("${ep_name}_$i" $endpoint)
#end
#set( $i = $i + 1)
#end
</loadbalance>
</endpoint>
@ -215,17 +239,6 @@
</endpoint>
#end
</send>
#if($destinationBasedStatsEnabled)
<filter source="get-property('isStatEnabled')" regex="true">
<then>
<bam>
<serverProfile name="$!profileName">
<streamConfig name="$!streamName" version="$!streamVersion"/>
</serverProfile>
</bam>
</then>
</filter>
#end
#end
######################## End of Macros ######################################
@ -266,17 +279,14 @@
#end
methods="$resource.getMethodsAsString()" faultSequence=#print_string_if_exist($faultSequence "fault")>
<inSequence>
## check and set jwt
#if($jwtIsEnabled && ($apiStatus != 'PROTOTYPED'))
<class name="org.wso2.carbon.apimgt.gateway.mediators.TokenPasser"/>
#end
## check and set response caching
#if($responseCacheEnabled)
<cache scope="per-host" collector="false" hashGenerator="org.wso2.caching.digest.REQUESTHASHGenerator" timeout="$!responseCacheTimeOut">
<implementation type="memory" maxSize="500"/>
</cache>
#end
<property name="api.ut.backendRequestTime" expression="get-property('SYSTEM_TIME')"/>
############## define the filter based on environment type production only, sandbox only , hybrid ############
#if(($environmentType == 'sandbox') || ($environmentType =='hybrid' && !$endpoint_config.get("production_endpoints") ))
@ -288,7 +298,6 @@
<filter source="$ctx:AM_KEY_TYPE" regex="$filterRegex">
<then>
#end
<property name="api.ut.backendRequestTime" expression="get-property('SYSTEM_TIME')"/>
#if(($environmentType == 'sandbox') || ($environmentType =='hybrid' && ! $endpoint_config.get("production_endpoints") ))
#draw_endpoint( "sandbox" $endpoint_config )
#else
@ -329,6 +338,7 @@
#end
</inSequence>
<outSequence>
<class name="org.wso2.carbon.apimgt.usage.publisher.APIMgtResponseHandler"/>
## check and set response caching
#if($responseCacheEnabled)
<cache scope="per-host" collector="true"/>
@ -342,7 +352,6 @@
#if($handlers.size() > 0)
<handlers xmlns="http://ws.apache.org/ns/synapse">
#foreach($handler in $handlers)
#if($handler.className != 'org.wso2.carbon.apimgt.usage.publisher.APIMgtUsageHandler')
<handler xmlns="http://ws.apache.org/ns/synapse" class="$handler.className">
#if($handler.hasProperties())
#set ($map = $handler.getProperties() )
@ -352,7 +361,6 @@
#end
</handler>
#end
#end
</handlers>
#end
#end

@ -218,6 +218,8 @@
<include>**/application-authentication.xml</include>
<include>**/broker.xml</include>
<include>**/log4j.properties</include>
<include>**/nhttp.properties</include>
<include>**/passthru-http.properties</include>
</includes>
</fileSet>
<fileSet>
@ -475,8 +477,6 @@
<exclude>base-page/**</exclude>
<exclude>login/**</exclude>
<exclude>styles-layout.css</exclude>
<exclude>modules/manager/manager.jag</exclude>
<exclude>jagg/jagg.jag</exclude>
</excludes>
</fileSet>
@ -688,19 +688,7 @@
<outputDirectory>${pom.artifactId}-${pom.version}/bin</outputDirectory>
<fileMode>755</fileMode>
</file>
<!-- Copying the "api-store" app specific files that uses the edited "apimstore" jaggery module -->
<file>
<source>src/repository/jaggeryapps/api-store/jagg.jag</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/deployment/server/jaggeryapps/api-store/jagg
</outputDirectory>
<fileMode>755</fileMode>
</file>
<file>
<source>src/repository/jaggeryapps/api-store/manager.jag</source>
<outputDirectory>${pom.artifactId}-${pom.version}/repository/deployment/server/jaggeryapps/api-store/modules/manager
</outputDirectory>
<fileMode>755</fileMode>
</file>
<!-- Copying the "portal" app specific modifications to the distribution pack-->
<file>
<source>src/repository/jaggeryapps/portal/controllers/apis/analytics.jag</source>

@ -1,247 +1,181 @@
<?xml version="1.0"?>
<APIManager>
<!--
JNDI name of the data source to be used by the API publisher, API store and API
key manager. This data source should be defined in the master-datasources.xml file
in conf/datasources directory.
-->
<!-- JNDI name of the data source to be used by the API publisher, API store and API
key manager. This data source should be defined in the master-datasources.xml file
in conf/datasources directory. -->
<DataSourceName>jdbc/WSO2AM_DB</DataSourceName>
<!-- This parameter is used when adding api management capability to other products like GReg, AS, DSS etc.-->
<GatewayType>None</GatewayType>
<GatewayType>Synapse</GatewayType>
<!-- This parameter is used to enable the securevault support when try to publish endpoint secured APIs. Values should be "true" or "false".
By default secure vault is disabled.-->
By default secure vault is disabled.-->
<EnableSecureVault>false</EnableSecureVault>
<!--
Database configuration used by API publisher, API store and API key manager.
When these components are deployed separately, each of them should have
separate database configurations pointing to the same physical database.
-->
<!--Database-->
<!--
JDBC connection string for the database.
-->
<!--<URL>jdbc:h2:repository/database/WSO2AM_DB</URL> -->
<!--
JDBC username for the database.
-->
<!--<Username>wso2carbon</Username>-->
<!-- Authentication manager configuration for API publisher and API store. This is
a required configuration for both web applications as their user authentication
logic relies on this. -->
<AuthManager>
<!-- Server URL of the Authentication service -->
<ServerURL>https://localhost:${mgt.transport.https.port}${carbon.context}services/</ServerURL>
<!-- Admin username for the Authentication manager. -->
<Username>${admin.username}</Username>
<!-- Admin password for the Authentication manager. -->
<Password>${admin.password}</Password>
<!-- Indicates whether the permissions checking of the user (on the Publisher and Store) should be done
via a remote service. The check will be done on the local server when false. -->
<CheckPermissionsRemotely>false</CheckPermissionsRemotely>
</AuthManager>
<!--
JDBC password for the database.
-->
<!--<Password>wso2carbon</Password>
<JWTConfiguration>
<!-- Enable/Disable JWT generation. Default is false. -->
<EnableJWTGeneration>true</EnableJWTGeneration>
<!-- Name of the security context header to be added to the validated requests. -->
<JWTHeader>X-JWT-Assertion</JWTHeader>
JDBC driver for the database.
-->
<!--<Driver>org.h2.Driver</Driver>
</Database>-->
<!-- Fully qualified name of the class that will retrieve additional user claims
to be appended to the JWT. If not specified no claims will be appended.If user wants to add all user claims in the
jwt token, he needs to enable this parameter.
The DefaultClaimsRetriever class adds user claims from the default carbon user store. -->
<!--ClaimsRetrieverImplClass>org.wso2.carbon.apimgt.impl.token.DefaultClaimsRetriever</ClaimsRetrieverImplClass-->
<!--
Authentication manager configuration for API publisher and API store. This is
a required configuration for both web applications as their user authentication
logic relies on this.
-->
<AuthManager>
<!--
Server URL of the Authentication service
-->
<ServerURL>https://${carbon.local.ip}:${mgt.transport.https.port}${carbon.context}/services/</ServerURL>
<!--
Admin username for the Authentication manager.
-->
<Username>admin</Username>
<!--
Admin password for the Authentication manager.
-->
<Password>admin</Password>
</AuthManager>
<!-- The dialectURI under which the claimURIs that need to be appended to the
JWT are defined. Not used with custom ClaimsRetriever implementations. The
same value is used in the keys for appending the default properties to the
JWT. -->
<ConsumerDialectURI>http://wso2.org/claims</ConsumerDialectURI>
<!--
Configuration parameters for the API authentication handler. This is an optional
configuration for the API Gateway component.
-->
<APIConsumerAuthentication>
<!--
Name of the security context header to be added to the validated requests.
-->
<SecurityContextHeader>X-JWT-Assertion</SecurityContextHeader>
<!--
Fully qualified name of the class that will retrieve additional user claims
to be appended to the JWT. If not specified no claims will be appended.If user wants to add all user claims in the
jwt token, he needs to enable this parameter.
The DefaultClaimsRetriever class adds user claims from the default carbon user store.
-->
<!--ClaimsRetrieverImplClass>org.wso2.carbon.apimgt.impl.token.DefaultClaimsRetriever</ClaimsRetrieverImplClass-->
<!-- Signature algorithm. Accepts "SHA256withRSA" or "NONE". To disable signing explicitly specify "NONE". -->
<SignatureAlgorithm>SHA256withRSA</SignatureAlgorithm>
<!--
The dialectURI under which the claimURIs that need to be appended to the
JWT are defined. Not used with custom ClaimsRetriever implementations. The
same value is used in the keys for appending the default properties to the
JWT.
-->
<!--ConsumerDialectURI>http://wso2.org/claims</ConsumerDialectURI-->
<!--
Signature algorithm. Accepts "SHA256withRSA" or "NONE". To disable signing explicitly specify "NONE".
-->
<!--SignatureAlgorithm>SHA256withRSA</SignatureAlgorithm-->
<!--
Enable/Disable JWT generation. Default is false.
-->
<!--EnableTokenGeneration>false</EnableTokenGeneration-->
<!--
Remove OAuth headers from outgoing message or keep with it.
-->
<!--RemoveOAuthHeadersFromOutMessage>true</RemoveOAuthHeadersFromOutMessage-->
</APIConsumerAuthentication>
<!-- This parameter specifies which implementation should be used for generating the Token. JWTGenerator is the
default implementation provided. -->
<!--JWTGeneratorImpl>org.wso2.carbon.apimgt.keymgt.token.JWTGenerator</JWTGeneratorImpl-->
<!-- This parameter specifies which implementation should be used for generating the Token. For URL safe JWT
Token generation the implementation is provided in URLSafeJWTGenerator -->
<!--<JWTGeneratorImpl>org.wso2.carbon.apimgt.keymgt.token.URLSafeJWTGenerator</JWTGeneratorImpl>-->
<!-- Remove UserName from JWT Token -->
<!-- <RemoveUserNameFromJWTForApplicationToken>true</RemoveUserNameFromJWTForApplicationToken>-->
</JWTConfiguration>
<!-- Primary/secondary login configuration for APIstore. If user likes to keep two login attributes in a distributed setup, to login the APIstore,
he should configure this section. Primary login doesn't have a claimUri associated with it. But secondary login, which is a claim attribute,
is associated with a claimuri.-->
<!-- <LoginConfig>
<!--LoginConfig>
<UserIdLogin primary="true">
<ClaimUri></ClaimUri>
</UserIdLogin>
<EmailLogin primary="false">
<ClaimUri>http://wso2.org/claims/emailaddress</ClaimUri>
</EmailLogin>
</LoginConfig>-->
</LoginConfig-->
<!--
Credentials for the API gateway admin server. This configuration
is mainly used by the API publisher and store to connect to the API gateway and
create/update published API configurations.
-->
<!-- Credentials for the API gateway admin server. This configuration
is mainly used by the API publisher and store to connect to the API gateway and
create/update published API configurations. -->
<APIGateway>
<!-- The environments to which an API will be published -->
<Environments>
<!-- Environments can be of different types. Allowed values are 'hybrid', 'production' and 'sandbox'.
An API deployed on a 'production' type gateway will only support production keys
An API deployed on a 'sandbox' type gateway will only support sandbox keys
An API deployed on a 'hybrid' type gateway will support both production and sandbox keys -->
<Environment type="hybrid">
An API deployed on a 'production' type gateway will only support production keys
An API deployed on a 'sandbox' type gateway will only support sandbox keys
An API deployed on a 'hybrid' type gateway will support both production and sandbox keys. -->
<!-- api-console element specifies whether the environment should be listed in API Console or not -->
<Environment type="hybrid" api-console="true">
<Name>Production and Sandbox</Name>
<!--
Server URL of the API gateway.
-->
<ServerURL>https://${carbon.local.ip}:${mgt.transport.https.port}${carbon.context}/services/</ServerURL>
<!--
Admin username for the API gateway.
-->
<Username>admin</Username>
<!--
Admin password for the API gateway.
-->
<Password>admin</Password>
<!--
Endpoint URLs for the APIs hosted in this API gateway.
-->
<Description>This is a hybrid gateway that handles both production and sandbox token traffic.</Description>
<!-- Server URL of the API gateway -->
<ServerURL>https://localhost:${mgt.transport.https.port}${carbon.context}services/</ServerURL>
<!-- Admin username for the API gateway. -->
<Username>${admin.username}</Username>
<!-- Admin password for the API gateway.-->
<Password>${admin.password}</Password>
<!-- Endpoint URLs for the APIs hosted in this API gateway.-->
<GatewayEndpoint>http://${carbon.local.ip}:${http.nio.port},https://${carbon.local.ip}:${https.nio.port}</GatewayEndpoint>
</Environment>
</Environments>
<!--
Enable/Disable token caching at gateway node.
-->
<EnableGatewayKeyCache>true</EnableGatewayKeyCache>
<!--
Enable/Disable API resource caching at gateway node.
-->
<EnableGatewayResourceCache>true</EnableGatewayResourceCache>
<!-- Header name can be configurable, as you preferred. When API invocation is restricted to access only for authorized domains,
client request should send his domain, as the value of this header.
-->
<ClientDomainHeader>referer</ClientDomainHeader>
</APIGateway>
<!--
Enable/Disable Usage metering and billing for api usage
-->
<EnableBillingAndUsage>false</EnableBillingAndUsage>
<CacheConfigurations>
<!-- Enable/Disable token caching at the Gateway-->
<EnableGatewayTokenCache>true</EnableGatewayTokenCache>
<!-- Enable/Disable API resource caching at the Gateway-->
<EnableGatewayResourceCache>true</EnableGatewayResourceCache>
<!-- Enable/Disable API key validation information caching at key-management server -->
<EnableKeyManagerTokenCache>false</EnableKeyManagerTokenCache>
<!-- This parameter specifies whether Recently Added APIs will be loaded from the cache or not.
If there are multiple API modification during a short time period, better to disable cache. -->
<EnableRecentlyAddedAPICache>false</EnableRecentlyAddedAPICache>
<!-- JWT claims Cache expiry in seconds -->
<!--JWTClaimCacheExpiry>900</JWTClaimCacheExpiry-->
<!-- Expiry time for the apim key mgt validation info cache -->
<!--TokenCacheExpiry>900</TokenCacheExpiry-->
<!-- This parameter specifies the expiration time of the TagCache. TagCache will
only be created when this element is uncommented. When the specified
time duration gets elapsed ,tag cache will get re-generated. -->
<!--TagCacheDuration>120000</TagCacheDuration-->
</CacheConfigurations>
<!--
API usage tracker configuration used by the BAM data publisher and
API usage tracker configuration used by the DAS data publisher and
Google Analytics publisher in API gateway.
-->
<APIUsageTracking>
<!--
Enable/Disable the API usage tracker.
-->
<Analytics>
<!-- Enable Analytics for API Manager -->
<Enabled>false</Enabled>
<!--
API Usage Data Publisher.
-->
<!-- Server URL of the remote DAS/CEP server used to collect statistics. Must
be specified in protocol://hostname:port/ format.
An event can also be published to multiple Receiver Groups each having 1 or more receivers. Receiver
Groups are delimited by curly braces whereas receivers are delimited by commas.
Ex - Multiple Receivers within a single group
tcp://localhost:7612/,tcp://localhost:7613/,tcp://localhost:7614/
Ex - Multiple Receiver Groups with two receivers each
{tcp://localhost:7612/,tcp://localhost:7613},{tcp://localhost:7712/,tcp://localhost:7713/} -->
<DASServerURL>{tcp://localhost:7612}</DASServerURL>
<!--DASAuthServerURL>{ssl://localhost:7712}</DASAuthServerURL-->
<!-- Administrator username to login to the remote DAS server. -->
<DASUsername>${admin.username}</DASUsername>
<!-- Administrator password to login to the remote DAS server. -->
<DASPassword>${admin.password}</DASPassword>
<!-- For APIM implemented Statistic client for RDBMS -->
<StatsProviderImpl>org.wso2.carbon.apimgt.usage.client.impl.APIUsageStatisticsRdbmsClientImpl</StatsProviderImpl>
<!-- DAS REST API configuration -->
<DASRestApiURL>https://localhost:9444</DASRestApiURL>
<DASRestApiUsername>${admin.username}</DASRestApiUsername>
<DASRestApiPassword>${admin.password}</DASRestApiPassword>
<!-- Below property is used to skip trying to connect to event receiver nodes when publishing events even if
the stats enabled flag is set to true. -->
<SkipEventReceiverConnection>false</SkipEventReceiverConnection>
<!-- API Usage Data Publisher. -->
<PublisherClass>org.wso2.carbon.apimgt.usage.publisher.APIMgtUsageDataBridgeDataPublisher</PublisherClass>
<!--
Thrift port of the remote BAM server.
-->
<ThriftPort>7612</ThriftPort>
<!--
Server URL of the remote BAM/CEP server used to collect statistics. Must
be specified in protocol://hostname:port/ format.
An event can also be published to multiple Receiver Groups each having 1 or more receivers. Receiver
Groups are delimited by curly braces whereas receivers are delimited by commas.
Ex - Multiple Receivers within a single group
tcp://localhost:7612/,tcp://localhost:7613/,tcp://localhost:7614/
Ex - Multiple Receiver Groups with two receivers each
{tcp://localhost:7612/,tcp://localhost:7613},{tcp://localhost:7712/,tcp://localhost:7713/}
-->
<BAMServerURL>tcp://localhost:7612/</BAMServerURL>
<!--
Administrator username to login to the remote BAM server.
-->
<BAMUsername>admin</BAMUsername>
<!--
Administrator password to login to the remote BAM server.
-->
<BAMPassword>admin</BAMPassword>
<!--
JNDI name of the data source to be used for getting BAM statistics.This data source should
be defined in the master-datasources.xml file in conf/datasources directory.
-->
<!--DataSourceName>jdbc/WSO2AM_STATS_DB</DataSourceName-->
<!--
Data publishing stream names and versions of API requests, responses and faults. If the default values
are changed, the toolbox also needs to be changed accordingly.
-->
<!-- If below property set to true,then the response message size will be calculated and publish
with each successful API invocation event. -->
<PublishResponseMessageSize>false</PublishResponseMessageSize>
<!-- Data publishing stream names and versions of API requests, responses and faults. If the default values
are changed, the toolbox also needs to be changed accordingly. -->
<Streams>
<Request>
<Name>org.wso2.apimgt.statistics.request</Name>
<Version>1.0.0</Version>
<Version>1.1.0</Version>
</Request>
<Response>
<Name>org.wso2.apimgt.statistics.response</Name>
<Version>1.0.0</Version>
<Version>1.1.0</Version>
</Response>
<Fault>
<Name>org.wso2.apimgt.statistics.fault</Name>
<Version>1.0.0</Version>
</Fault>
<Destination>
<Name>org_wso2_apimgt_statistics_destination</Name>
<Version>1.0.0</Version>
<BAMProfileName>bam-profile</BAMProfileName>
</Destination>
<Throttle>
<Name>org.wso2.apimgt.statistics.throttle</Name>
<Version>1.0.0</Version>
@ -250,224 +184,168 @@
<Name>org.wso2.apimgt.statistics.workflow</Name>
<Version>1.0.0</Version>
</Workflow>
<ExecutionTime>
<Name>org.wso2.apimgt.statistics.execution.time</Name>
<Version>1.0.0</Version>
</ExecutionTime>
<AlertTypes>
<Name>org.wso2.analytics.apim.alertStakeholderInfo</Name>
<Version>1.0.0</Version>
</AlertTypes>
</Streams>
</APIUsageTracking>
</Analytics>
<!--
API key validator configuration used by API key manager (IS), API store and API gateway.
API gateway uses it to validate and authenticate users against the provided API keys.
-->
<APIKeyValidator>
<!--
Server URL of the API key manager
-->
<ServerURL>https://${carbon.local.ip}:${mgt.transport.https.port}${carbon.context}/services/</ServerURL>
<!--
Admin username for API key manager.
-->
<Username>admin</Username>
<!--
Admin password for API key manager.
-->
<Password>admin</Password>
<!--
Enable/Disable JWT caching.
-->
<EnableJWTCache>false</EnableJWTCache>
<!--
Enable/Disable API key validation information caching at key-management server
-->
<EnableKeyMgtValidationInfoCache>false</EnableKeyMgtValidationInfoCache>
<!--
Configurations related to enable thrift support for key-management related communication.
If you want to switch back to Web Service Client, change the value of "KeyValidatorClientType" to "WSClient".
In a distributed environment;
-If you are at the Gateway node, you need to point "ThriftClientPort" value to the "ThriftServerPort" value given at KeyManager node.
-If you need to start two API Manager instances in the same machine, you need to give different ports to "ThriftServerPort" value in two nodes.
-ThriftServerHost - Allows to configure a hostname for the thrift server. It uses the carbon hostname by default.
-->
<KeyValidatorClientType>ThriftClient</KeyValidatorClientType>
<ThriftClientPort>10397</ThriftClientPort>
<!-- Server URL of the API key manager -->
<ServerURL>https://localhost:${mgt.transport.https.port}${carbon.context}services/</ServerURL>
<!-- Admin username for API key manager. -->
<Username>${admin.username}</Username>
<!-- Admin password for API key manager. -->
<Password>${admin.password}</Password>
<!-- Configurations related to enable thrift support for key-management related communication.
If you want to switch back to Web Service Client, change the value of "KeyValidatorClientType" to "WSClient".
In a distributed environment;
-If you are at the Gateway node, you need to point "ThriftClientPort" value to the "ThriftServerPort" value given at KeyManager node.
-If you need to start two API Manager instances in the same machine, you need to give different ports to "ThriftServerPort" value in two nodes.
-ThriftServerHost - Allows to configure a hostname for the thrift server. It uses the carbon hostname by default.
-The Gateway uses this parameter to connect to the key validation thrift service. -->
<KeyValidatorClientType>WSClient</KeyValidatorClientType>
<ThriftClientConnectionTimeOut>10000</ThriftClientConnectionTimeOut>
<ThriftServerPort>10397</ThriftServerPort>
<!--ThriftServerHost>localhost</ThriftServerHost-->
<EnableThriftServer>true</EnableThriftServer>
<!--
Scope used for marking Application Tokens. If a token is generated with this scope, they will be treated as Application Access Tokens
-->
<ApplicationTokenScope>am_application_scope</ApplicationTokenScope>
<!--
Specifies the implementation to be used for KeyValidationHandler. Steps for validating a token can be controlled by plugging in a custom KeyValidation Handler
-->
<!--ThriftClientPort>10397</ThriftClientPort-->
<EnableThriftServer>false</EnableThriftServer>
<ThriftServerHost>localhost</ThriftServerHost>
<!--ThriftServerPort>10397</ThriftServerPort-->
<!--ConnectionPool>
<MaxIdle>100</MaxIdle>
<InitIdleCapacity>50</InitIdleCapacity>
</ConnectionPool-->
<!-- Specifies the implementation to be used for KeyValidationHandler. Steps for validating a token can be controlled by plugging in a
custom KeyValidation Handler -->
<KeyValidationHandlerClassName>org.wso2.carbon.apimgt.keymgt.handlers.DefaultKeyValidationHandler</KeyValidationHandlerClassName>
<!--
This parameter is used to specify Thrift server host name. In a distributed deployment we must set this parameter
if keymanager running on separate machine. Gateway use this parameter to connect key validation thrift service
-->
<!--ThriftServerHost>127.0.0.1</ThriftServerHost-->
<!--
Remove UserName from JWT Token
-->
<!-- <RemoveUserNameFromJWTForApplicationToken>true</RemoveUserNameFromJWTForApplicationToken>-->
<!-- Name of the token API -->
<TokenEndPointName>/oauth2/token</TokenEndPointName>
<!-- This the API URL for revoke API. When we revoke tokens revoke requests should go through this
API deployed in API gateway. Then it will do cache invalidations related to revoked tokens.
In distributed deployment we should configure this property in key manager node by pointing
gateway https url. Also please note that we should point gateway revoke service to key manager
-->
<RevokeAPIURL>https://${carbon.local.ip}:${https.nio.port}/revoke</RevokeAPIURL>
<!-- Whether to encrypt tokens when storing in the Database
Note: If changing this value to true, change the value of <TokenPersistenceProcessor> to
org.wso2.carbon.identity.oauth.tokenprocessor.EncryptionDecryptionPersistenceProcessor in the identity.xml -->
<EncryptPersistedTokens>false</EncryptPersistedTokens>
</APIKeyValidator>
<APIKeyManager>
<KeyManagerClientImpl>org.wso2.carbon.apimgt.impl.AMDefaultKeyManagerImpl</KeyManagerClientImpl>
<!-- Uncomment this section only if you are going to have an instance other than KeyValidator as your KeyManager.
Unless a ThirdParty KeyManager is used, you don't need to configure this section. -->
<!--APIKeyManager>
<KeyManagerClientImpl>org.wso2.carbon.apimgt.keymgt.AMDefaultKeyManagerImpl</KeyManagerClientImpl>
<Configuration>
<ServerURL>https://localhost:${mgt.transport.https.port}${carbon.context}services/</ServerURL>
<Username>${admin.username}</Username>
<Password>${admin.password}</Password>
<TokenURL>https://${carbon.local.ip}:${mgt.transport.https.port}/oauth2/token</TokenURL>
<RevokeURL>https://${carbon.local.ip}:${mgt.transport.https.port}/oauth2/revoke</RevokeURL>
<TokenURL>https://${carbon.local.ip}:${https.nio.port}/token</TokenURL>
<RevokeURL>https://${carbon.local.ip}:${https.nio.port}/revoke</RevokeURL>
</Configuration>
</APIKeyManager>
</APIKeyManager-->
<!--
Settings related to managing API access tiers.
-->
<OAuthConfigurations>
<!-- Remove OAuth headers from outgoing message. -->
<!--RemoveOAuthHeadersFromOutMessage>true</RemoveOAuthHeadersFromOutMessage-->
<!-- Scope used for marking Application Tokens. If a token is generated with this scope, they will be treated as Application Access Tokens -->
<ApplicationTokenScope>am_application_scope</ApplicationTokenScope>
<!-- All scopes under the ScopeWhitelist element are not validating against roles that has assigned to it.
By default ^device_.* and openid scopes have been white listed internally. -->
<!--ScopeWhitelist>
<Scope>^device_.*</Scope>
<Scope>openid</Scope>
</ScopeWhitelist-->
<!-- Name of the token API -->
<TokenEndPointName>/oauth2/token</TokenEndPointName>
<!-- This the API URL for revoke API. When we revoke tokens revoke requests should go through this
API deployed in API gateway. Then it will do cache invalidations related to revoked tokens.
In distributed deployment we should configure this property in key manager node by pointing
gateway https( /http, we recommend users to use 'https' endpoints for security purpose) url.
Also please note that we should point gateway revoke service to key manager -->
<RevokeAPIURL>https://localhost:${https.nio.port}/revoke</RevokeAPIURL>
<!-- Whether to encrypt tokens when storing in the Database
Note: If changing this value to true, change the value of <TokenPersistenceProcessor> to
org.wso2.carbon.identity.oauth.tokenprocessor.EncryptionDecryptionPersistenceProcessor in the identity.xml -->
<EncryptPersistedTokens>false</EncryptPersistedTokens>
</OAuthConfigurations>
<!-- Settings related to managing API access tiers. -->
<TierManagement>
<!--
Enable the providers to expose their APIs over the special 'Unlimited' tier which
basically disables tier based throttling for the specified APIs.
-->
<!-- Enable the providers to expose their APIs over the special 'Unlimited' tier which
basically disables tier based throttling for the specified APIs. -->
<EnableUnlimitedTier>true</EnableUnlimitedTier>
</TierManagement>
<!--
Use this configuration to control the self-sign-up capability in API store.
-->
<SelfSignUp>
<!--
Enable or disable the self-sign-up feature.
-->
<Enabled>true</Enabled>
<!--
Self signed up users should be associated with a suitable subscriber
role for them to be able to access the API store portal. This required
parameter specifies which role should be used for that purpose. The role
specified here must have the '/permission/admin/manage/api/subscribe'
permission.
-->
<SubscriberRoleName>subscriber</SubscriberRoleName>
</SelfSignUp>
<!--
Use this configuration to control the number of APIs shown in API store.
-->
<!-- API Store Related Configurations -->
<APIStore>
<!--GroupingExtractor>org.wso2.carbon.apimgt.impl.DefaultGroupIDExtractorImpl</GroupingExtractor-->
<!--This property is used to indicate how we do user name comparision for token generation https://wso2.org/jira/browse/APIMANAGER-2225-->
<CompareCaseInsensitively>true</CompareCaseInsensitively>
<DisplayURL>false</DisplayURL>
<URL>https://${carbon.local.ip}:${mgt.transport.https.port}/store</URL>
<!--
This parameter specifies whether to display multiple versions of same
API or only showing the latest version of an API.
<URL>https://localhost:${mgt.transport.https.port}/store</URL>
-->
<DisplayMultipleVersions>false</DisplayMultipleVersions>
<!--
This parameter specifies whether to display all the APIs
[which are having DEPRECATED/PUBLISHED status] or only display the APIs
with having their status is as 'PUBLISHED'
<!-- Server URL of the API Store. -->
<ServerURL>https://localhost:${mgt.transport.https.port}${carbon.context}services/</ServerURL>
<!-- Admin username for API Store. -->
<Username>${admin.username}</Username>
-->
<!-- Admin password for API Store. -->
<Password>${admin.password}</Password>
<!-- This parameter specifies whether to display multiple versions of same
API or only showing the latest version of an API. -->
<DisplayMultipleVersions>false</DisplayMultipleVersions>
<!-- This parameter specifies whether to display all the APIs
[which are having DEPRECATED/PUBLISHED status] or only display the APIs
with having their status is as 'PUBLISHED' -->
<DisplayAllAPIs>false</DisplayAllAPIs>
<!-- Uncomment this to limit the number of APIs in api the API Store -->
<!--APIsPerPage>5</APIsPerPage-->
<!--
This parameter specifies whether to display the comment editing facility or not.
Default is "true". If user wants to disable, he must set this param as "false"
-->
<!-- This parameter specifies whether to display the comment editing facility or not.
Default is "true". If user wants to disable, he must set this param as "false" -->
<DisplayComments>true</DisplayComments>
<!--
This parameter specifies whether to display the ratings or not.
Default is "true". If user wants to disable, he must set this param as "false"
-->
<!-- This parameter specifies whether to display the ratings or not.
Default is "true". If user wants to disable, he must set this param as "false" -->
<DisplayRatings>true</DisplayRatings>
<!--
This parameter specifies the expiration time of the TagCache. TagCache will
only be created when this element is uncommented. When the specified
time duration gets elapsed ,tag cache will get re-generated.
-->
<!--TagCacheDuration>120000</TagCacheDuration-->
<!--
This parameter specifies whether Recently Added APIs will be loaded from the cache or not.
If there are multiple API modification during a short time period, better to disable cache.
-->
<EnableRecentlyAddedAPICache>false</EnableRecentlyAddedAPICache>
<!--set isStoreForumEnabled to false for disable forum in store-->
<!--isStoreForumEnabled>false</isStoreForumEnabled-->
</APIStore>
<APIPublisher>
<DisplayURL>false</DisplayURL>
<URL>https://${carbon.local.ip}:${mgt.transport.https.port}/publisher</URL>
<!--
This parameter specifies enabling the capability of setting API documentation level granular visibility levels.
By default any document associate with an API will have the same permissions set as the API.With enabling below
property,it will show two additional permission levels as visible only to all registered users in a particular
domain or only visible to API doc creator
-->
<URL>https://localhost:${mgt.transport.https.port}/publisher</URL>
<!-- This parameter specifies enabling the capability of setting API documentation level granular visibility levels.
By default any document associate with an API will have the same permissions set as the API.With enabling below
property,it will show two additional permission levels as visible only to all registered users in a particular
domain or only visible to API doc creator -->
<!--EnableAPIDocVisibilityLevels>true</EnableAPIDocVisibilityLevels-->
<!-- Uncomment this to limit the number of APIs in api the API Publisher -->
<!--APIsPerPage>30</APIsPerPage-->
</APIPublisher>
<!--
Status observers can be registered against the API Publisher to listen for
API status update events. Each observer must implement the APIStatusObserver
interface. Multiple observers can be engaged if necessary and in such situations
they will be notified in the order they are defined here.
-->
<!-- Status observers can be registered against the API Publisher to listen for
API status update events. Each observer must implement the APIStatusObserver
interface. Multiple observers can be engaged if necessary and in such situations
they will be notified in the order they are defined here.
This configuration is unused from API Manager version 1.10.0 -->
<!--StatusObservers>
<Observer>org.wso2.carbon.apimgt.impl.observers.SimpleLoggingObserver</Observer>
</StatusObservers-->
<!--
Use this configuration Create APIs at the Server startup
-->
<!-- Use this configuration Create APIs at the Server startup -->
<StartupAPIPublisher>
<!--
Enable/Disable the API Startup Publisher
-->
<!-- Enable/Disable the API Startup Publisher -->
<Enabled>false</Enabled>
<!--
Configuration to create APIs for local endpoints.
Endpoint will be computed as http://${carbon.local.ip}:${mgt.transport.http.port}/Context.
Define many LocalAPI elements as below to create many APIs
for local Endpoints.
IconPath should be relative to CARBON_HOME.
-->
<!-- Configuration to create APIs for local endpoints.
Endpoint will be computed as http://${carbon.local.ip}:${mgt.transport.http.port}/Context.
Define many LocalAPI elements as below to create many APIs
for local Endpoints.
IconPath should be relative to CARBON_HOME. -->
<LocalAPIs>
<LocalAPI>
<Context>/resource</Context>
@ -478,56 +356,188 @@
<AuthType>Any</AuthType>
</LocalAPI>
</LocalAPIs>
<!--
Configuration to create APIs for remote endpoints.
When Endpoint need to be defined use this configuration.
Define many API elements as below to create many APIs
for external Endpoints.
If you do not need to add Icon or Documentation set
'none' as the value for IconPath & DocumentURL.
-->
<!--APIs>
<API>
<Context>/resource</Context>
<Endpoint>http://localhost:9764/resource</Endpoint>
<Provider>admin</Provider>
<Version>1.0.0</Version>
<IconPath>none</IconPath>
<DocumentURL>none</DocumentURL>
<AuthType>Any</AuthType>
</API>
</APIs-->
<!-- Configuration to create APIs for remote endpoints.
When Endpoint need to be defined use this configuration.
Define many API elements as below to create many APIs
for external Endpoints.
If you do not need to add Icon or Documentation set
'none' as the value for IconPath & DocumentURL. -->
<!--APIs>
<API>
<Context>/resource</Context>
<Endpoint>http://localhost:9764/resource</Endpoint>
<Provider>admin</Provider>
<Version>1.0.0</Version>
<IconPath>none</IconPath>
<DocumentURL>none</DocumentURL>
<AuthType>Any</AuthType>
</API>
</APIs-->
</StartupAPIPublisher>
<!--
When an API is invoked, a list of handlers get engaged to its execution flow. This
property defines the position of the Extension Handler.
Supported values: top, bottom
Defaults to: bottom
-->
<!--ExtensionHandlerPosition>top|bottom</ExtensionHandlerPosition-->
<!--Configuration to enable/disable sending CORS headers in the Gateway response
and define the Access-Control-Allow-Origin header value.-->
<!-- Configuration to enable/disable sending CORS headers in the Gateway response
and define the Access-Control-Allow-Origin header value.-->
<CORSConfiguration>
<!--Configuration to enable/disable sending CORS headers from the Gateway-->
<!-- Configuration to enable/disable sending CORS headers from the Gateway-->
<Enabled>true</Enabled>
<!--The value of the Access-Control-Allow-Origin header. Default values are
API Store addresses, which is needed for swagger to function.-->
<Access-Control-Allow-Origin>https://localhost:9443,http://localhost:9763</Access-Control-Allow-Origin>
<!-- The value of the Access-Control-Allow-Origin header. Default values are
API Store addresses, which is needed for swagger to function. -->
<Access-Control-Allow-Origin>*</Access-Control-Allow-Origin>
<!--Configure Access-Control-Allow-Headers-->
<Access-Control-Allow-Headers>authorization,Access-Control-Allow-Origin,Content-Type</Access-Control-Allow-Headers>
<!-- Configure Access-Control-Allow-Methods -->
<Access-Control-Allow-Methods>GET,PUT,POST,DELETE,PATCH,OPTIONS</Access-Control-Allow-Methods>
<!-- Configure Access-Control-Allow-Headers -->
<Access-Control-Allow-Headers>authorization,Access-Control-Allow-Origin,Content-Type,SOAPAction</Access-Control-Allow-Headers>
<!-- Configure Access-Control-Allow-Credentials -->
<!-- Specifying this header to true means that the server allows cookies (or other user credentials) to be included on cross-origin requests.
It is false by default and if you set it to true then make sure that the Access-Control-Allow-Origin header does not contain the wildcard (*) -->
<Access-Control-Allow-Credentials>false</Access-Control-Allow-Credentials>
</CORSConfiguration>
<!-- This property is there to configure velocity log output into existing Log4j carbon Logger.
You can enable this and set preferable Logger name.
-->
<!--VelocityLogger>VELOCITY</VelocityLogger-->
</APIManager>
You can enable this and set preferable Logger name. -->
<!-- VelocityLogger>VELOCITY</VelocityLogger -->
<RESTAPI>
<!--Configure white-listed URIs of REST API. Accessing white-listed URIs does not require credentials (does not require Authorization header). -->
<WhiteListedURIs>
<WhiteListedURI>
<URI>/api/am/publisher/{version}/swagger.json</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
<WhiteListedURI>
<URI>/api/am/store/{version}/swagger.json</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
<WhiteListedURI>
<URI>/api/am/admin/{version}/swagger.json</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
<WhiteListedURI>
<URI>/api/am/store/{version}/apis</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
<WhiteListedURI>
<URI>/api/am/store/{version}/apis/{apiId}</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
<WhiteListedURI>
<URI>/api/am/store/{version}/apis/{apiId}/swagger</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
<WhiteListedURI>
<URI>/api/am/store/{version}/apis/{apiId}/documents</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
<WhiteListedURI>
<URI>/api/am/store/{version}/apis/{apiId}/documents/{documentId}</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
<WhiteListedURI>
<URI>/api/am/store/{version}/apis/{apiId}/documents/{documentId}/content</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
<WhiteListedURI>
<URI>/api/am/store/{version}/apis/{apiId}/thumbnail</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
<WhiteListedURI>
<URI>/api/am/store/{version}/tags</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
<WhiteListedURI>
<URI>/api/am/store/{version}/tiers/{tierLevel}</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
<WhiteListedURI>
<URI>/api/am/store/{version}/tiers/{tierLevel}/{tierName}</URI>
<HTTPMethods>GET,HEAD</HTTPMethods>
</WhiteListedURI>
</WhiteListedURIs>
</RESTAPI>
<ThrottlingConfigurations>
<EnableAdvanceThrottling>false</EnableAdvanceThrottling>
<DataPublisher>
<Enabled>false</Enabled>
<Type>Binary</Type>
<ReceiverUrlGroup>tcp://${carbon.local.ip}:${receiver.url.port}</ReceiverUrlGroup>
<AuthUrlGroup>ssl://${carbon.local.ip}:${auth.url.port}</AuthUrlGroup>
<Username>${admin.username}</Username>
<Password>${admin.password}</Password>
<DataPublisherPool>
<MaxIdle>1000</MaxIdle>
<InitIdleCapacity>200</InitIdleCapacity>
</DataPublisherPool>
<DataPublisherThreadPool>
<CorePoolSize>200</CorePoolSize>
<MaxmimumPoolSize>1000</MaxmimumPoolSize>
<KeepAliveTime>200</KeepAliveTime>
</DataPublisherThreadPool>
</DataPublisher>
<PolicyDeployer>
<ServiceURL>https://localhost:${mgt.transport.https.port}${carbon.context}services/</ServiceURL>
<Username>${admin.username}</Username>
<Password>${admin.password}</Password>
</PolicyDeployer>
<BlockCondition>
<Enabled>false</Enabled>
<!--InitDelay>300000</InitDelay>
<Period>3600000</Period-->
</BlockCondition>
<JMSConnectionDetails>
<Enabled>false</Enabled>
<ServiceURL>tcp://${carbon.local.ip}:${jms.port}</ServiceURL>
<Username>${admin.username}</Username>
<Password>${admin.password}</Password>
<Destination>throttleData</Destination>
<!--InitDelay>300000</InitDelay-->
<JMSConnectionParameters>
<transport.jms.ConnectionFactoryJNDIName>TopicConnectionFactory</transport.jms.ConnectionFactoryJNDIName>
<transport.jms.DestinationType>topic</transport.jms.DestinationType>
<java.naming.factory.initial>org.wso2.andes.jndi.PropertiesFileInitialContextFactory</java.naming.factory.initial>
<connectionfactory.TopicConnectionFactory>amqp://${jms.username}:${jms.password}@clientid/carbon?brokerlist='${jms.url}'</connectionfactory.TopicConnectionFactory>
</JMSConnectionParameters>
<JMSTaskManager>
<MinThreadPoolSize>20</MinThreadPoolSize>
<MaxThreadPoolSize>100</MaxThreadPoolSize>
<KeepAliveTimeInMillis>1000</KeepAliveTimeInMillis>
<JobQueueSize>10</JobQueueSize>
</JMSTaskManager>
</JMSConnectionDetails>
<JMSEventPublisherParameters>
<java.naming.factory.initial>org.wso2.andes.jndi.PropertiesFileInitialContextFactory</java.naming.factory.initial>
<java.naming.provider.url>repository/conf/jndi.properties</java.naming.provider.url>
<transport.jms.DestinationType>topic</transport.jms.DestinationType>
<transport.jms.Destination>throttleData</transport.jms.Destination>
<transport.jms.ConcurrentPublishers>allow</transport.jms.ConcurrentPublishers>
<transport.jms.ConnectionFactoryJNDIName>TopicConnectionFactory</transport.jms.ConnectionFactoryJNDIName>
</JMSEventPublisherParameters>
<!--DefaultLimits>
<SubscriptionTierLimits>
<Gold>5000</Gold>
<Silver>2000</Silver>
<Bronze>1000</Bronze>
<Unauthenticated>60</Unauthenticated>
</SubscriptionTierLimits>
<ApplicationTierLimits>
<50PerMin>50</50PerMin>
<20PerMin>20</20PerMin>
<10PerMin>10</10PerMin>
</ApplicationTierLimits>
<ResourceLevelTierLimits>
<50KPerMin>50000</50KPerMin>
<20KPerMin>20000</20KPerMin>
<10KPerMin>10000</10KPerMin>
</ResourceLevelTierLimits>
</DefaultLimits-->
<EnableUnlimitedTier>true</EnableUnlimitedTier>
<EnableHeaderConditions>false</EnableHeaderConditions>
<EnableJWTClaimConditions>false</EnableJWTClaimConditions>
<EnableQueryParamConditions>false</EnableQueryParamConditions>
</ThrottlingConfigurations>
</APIManager>

@ -36,14 +36,14 @@
</IdentityConfiguration>
<PolicyConfiguration>
<MonitoringClass>org.wso2.carbon.policy.mgt</MonitoringClass>
<MonitoringEnable>true</MonitoringEnable>
<MonitoringEnable>false</MonitoringEnable>
<MonitoringFrequency>60000</MonitoringFrequency>
<MaxRetries>5</MaxRetries>
<MinRetriesToMarkUnreachable>8</MinRetriesToMarkUnreachable>
<MinRetriesToMarkInactive>20</MinRetriesToMarkInactive>
</PolicyConfiguration>
<TaskConfiguration>
<Enable>true</Enable>
<Enable>false</Enable>
<Frequency>600000</Frequency>
<TaskClass>org.wso2.carbon.device.mgt.core.task.impl.DeviceDetailsRetrieverTask</TaskClass>
<Operations>

@ -24,10 +24,14 @@
<WebappPublisherConfigs>
<!-- This host is used to define the host address which is used to publish APIs -->
<Host>https://localhost:9443</Host>
<Host>https://localhost:${carbon.https.port}</Host>
<!-- If it is true, the APIs of this instance will be published to the defined host -->
<PublishAPI>true</PublishAPI>
<!-- If it is true, the APIs of this instance will be updated when the webapps are redeployed -->
<EnabledUpdateApi>false</EnabledUpdateApi>
<!--Webapp will be published only when running below profiles-->
<Profiles>
<Profile>default</Profile>

@ -128,9 +128,10 @@
<GrantTypeName>authorization_code</GrantTypeName>
<GrantTypeHandlerImplClass>org.wso2.carbon.identity.oauth2.token.handlers.grant.AuthorizationCodeGrantHandler</GrantTypeHandlerImplClass>
</SupportedGrantType>
<SupportedGrantType>
<GrantTypeName>password</GrantTypeName>
<GrantTypeHandlerImplClass>org.wso2.carbon.apimgt.keymgt.handlers.ExtendedPasswordGrantHandler</GrantTypeHandlerImplClass>
<GrantTypeHandlerImplClass>org.wso2.carbon.device.mgt.oauth.extensions.handlers.grant.ExtendedPasswordGrantHandler</GrantTypeHandlerImplClass>
</SupportedGrantType>
<SupportedGrantType>
<GrantTypeName>refresh_token</GrantTypeName>

@ -0,0 +1,46 @@
#
# Copyright (c) 2005-2010, WSO2 Inc. (http://wso2.com) All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This file contains the configuration parameters used by the Non-blocking HTTP transport
#http.socket.timeout=60000
#http.socket.buffer-size=8192
#http.tcp.nodelay=1
#http.connection.stalecheck=0
# Uncomment the following property for an AIX based deployment
#http.nio.interest-ops-queueing=true
# HTTP Sender thread pool parameters
#snd_t_core=20
#snd_t_max=100
#snd_alive_sec=5
#snd_qlen=-1
#snd_io_threads=2
# HTTP Listener thread pool parameters
#lst_t_core=20
#lst_t_max=100
#lst_alive_sec=5
#lst_qlen=-1
#lst_io_threads=2
nhttp.rest.dispatcher.service=__MultitenantDispatcherService
rest_uri_api_regex=\\w+://.+:\\d+/t/.*|\\w+://.+\\w+/t/.*|^(/t/).*
rest_uri_proxy_regex=\\w+://.+:\\d+/services/t/.*|\\w+://.+\\w+/services/t/.*|^(/services/t/)
# This property is crucial for automated tests
http.socket.reuseaddr=true

@ -0,0 +1,51 @@
#
# Copyright (c) 2005-2010, WSO2 Inc. (http://wso2.com) All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
## This file contains the configuration parameters used by the Pass-through HTTP transport
## Nhttp tuning parameters
#http.socket.timeout=60000
#http.connection.timeout=0
#http.socket.buffer-size=8192
#http.socket.linger=-1
#http.nio.select-interval=1000
#http.tcp.nodelay=true
#http.connection.stalecheck=false
#http.socket.reuseaddr=false
## Uncomment the following for AIX based deployments
#http.nio.interest-ops-queueing=true
## Pass-through HTTP transport specific tuning parameters
worker_pool_size_core=400
worker_pool_size_max=500
#worker_thread_keepalive_sec=60
#worker_pool_queue_length=-1
#io_threads_per_reactor=2
io_buffer_size=16384
#http.max.connection.per.host.port=32767
## Other parameters
#http.user.agent.preserve=false
#http.server.preserve=true
#http.connection.disable.keepalive=false
# URI configurations that determine if it requires custom rest dispatcher
rest_uri_api_regex=\\w+://.+:\\d+/t/.*|\\w+://.+\\w+/t/.*|^(/t/).*
rest_uri_proxy_regex=\\w+://.+:\\d+/services/t/.*|\\w+://.+\\w+/services/t/.*|^(/services/t/)
# This property is crucial for automated tests
http.socket.reuseaddr=true

@ -1,897 +0,0 @@
<%
var site = require("/site/conf/site.json");
//TODO : remove this when log configs are implemented
//Log.prototype.isDebugEnabled = function () {
// return false;
//};
//TODO : remove this when Context HO is implemented.
var context = context || {
put:function (key, value) {
session.put(key, value);
},
get:function (key) {
return session.get(key);
},
remove:function (key) {
session.remove(key);
}
};
var jagg = jagg || (function () {
var ctx = context;
var modules = {};
var requirs = {};
var templates = {};
var initializers = {};
var bloks = {};
var data;
var reverse_proxy;
var setData = function (d) {
data = d;
};
var getData = function () {
return data;
};
var getUser = function () {
var user = session.get("logged.user");
// If user is null then check for mutual auth
if (!user) {
user = mutualAuthVerifier(user);
}
return user;
};
var setUser = function (user) {
//if jaggery allow session reset
if (typeof request.getSession == "function") {
if (session && !session.isNew()) {
session.invalidate();
}
session = request.getSession(true);
}
session.put("logged.user", user);
};
var mutualAuthVerifier = function(user){
var log = new Log();
var site = require("/site/conf/site.json");
if(site.mutualAuthConfiguration){
if (site.mutualAuthConfiguration.enabled == "true") {
// cert will be available only if trust store holds client certificate. Otherwise it is null
var cert = request.getAttribute("javax.servlet.request.X509Certificate");
var userName = request.getHeader("MutualAuthUserName");
// proceed mutul ssl validation if cert and user name set properly
if (cert != null) {
if (userName) {
var security = require("apimstore");
var mutualAuthHostObject = new security.MutualAuthHostObject();
var isValidUser = mutualAuthHostObject.validateUserNameHeader(userName);
// Group ID feature not supported here
var groupId="";
session.put("groupId", groupId);
if (isValidUser) {
log.info("Mutual Auth authentication success for user : " + userName);
user = {username: userName, cookie: null, hasPublisherAccess: false};
return user;
} else {
log.debug("Mutual authentication failed for invalid user : " + userName);
}
} else {
log.debug("Mutual authentication failed for invalid user : MutualAuthUserName header is empty");
}
} else {
log.debug("Mutual Authentication failed due to no trusted certificate");
}
}
}
};
var getThemeFile = function (path) {
var p, index, theme = getUserTheme();
if (theme.tenant_theme) {
p = getTenantThemePath() + path;
index = p.indexOf("?");
if (new File(p.substring(0, index == -1 ? p.length : index)).isExists()) {
return p;
}
}
if (theme.subtheme) {
p = getThemePath() + "subthemes/" + theme.subtheme + "/" + path;
index = p.indexOf("?");
if(new File(p.substring(0, index == -1 ? p.length : index)).isExists()) {
return p;
}
}
return getThemePath() + path;
};
var getThemesPath = function () {
return "/site/themes/";
};
var getTenantThemesPath = function(){
return "/site/tenant_themes/";
};
var getThemePath = function () {
return getThemesPath() + getUserTheme().base + "/";
};
var getTenantThemePath = function (){
return getTenantThemesPath() + getTheme().tenant_theme + "/";
}
var getBlockFile = function (name) {
return getBlocksDir() + name + "/block.jag";
};
var getInitializerFile = function (name) {
return getThemeFile("templates/" + name + "/initializer.jag");
};
var getTemplateFile = function (name) {
return getThemeFile("templates/" + name + "/template.jag");
};
var getTemplatePath = function(themeDir, name) {
return themeDir + "templates/" + name + "/template.jag";
};
var getModuleFile = function (name) {
return getModulesDir() + name + "/module.jag";
};
var getBlocksDir = function () {
return "/site/blocks/";
};
var getThemesDir = function () {
return "/site/themes/";
};
var getModulesDir = function () {
return "/modules/";
};
var getTheme = function () {
//TODO : remove following lines if theme switching need to be avoided
var site = require("/site/conf/site.json"),
theme = request.getParameter("theme"),
subtheme = request.getParameter("subtheme");
var r = {
base : theme ? theme : site.theme.base,
subtheme : subtheme ? subtheme : site.theme.subtheme,
};
//load the tenant theme if exists
var tenant = getTenantDomain();
if(tenant){
tenant = tenant.replace("/",".");
r.tenant_theme = getTenantDomain();
}
return r;
};
var getUserTheme = function () {
return session.get("theme") ? session.get("theme") : getTheme();
};
var mergeParams = function (extInputs, defInputs) {
var key, obj;
extInputs = extInputs || {};
for (key in defInputs) {
if (defInputs.hasOwnProperty(key)) {
obj = extInputs[key];
if (!obj) {
extInputs[key] = defInputs[key];
}
}
}
return extInputs;
};
var renderBlock = function (name, inputs, outputs, populate) {
//initializeTemplate({name:name, params:null}, jagg);
var init, fn, blok, log = new Log();
fn = template(name);
if (!fn) {
log.error("Template header and footer includes are missing for : " + name);
}
if (populate) {
blok = block(name);
if (!inputs) {
inputs = blok.getInputs ? blok.getInputs() : {};
} else {
mergeParams(inputs, blok.getInputs ? blok.getInputs() : null);
}
if (blok.getOutputs) {
outputs = blok.getOutputs(inputs);
} else if (blok.getInputs) {
outputs = inputs;
} else {
outputs = {};
}
}
init = initializer(name);
if (init.postInitialize) {
init.postInitialize(inputs, outputs);
}
fn(inputs, outputs, jagg);
};
var inheritParent = function (blok, name) {
var parent = require(getBlockFile(name));
for (var prop in parent) {
if (parent.hasOwnProperty(prop)) {
if (!blok[prop]) {
blok[prop] = parent[prop];
}
}
}
};
var initializeBlock = function (obj) {
if (!obj) {
return;
}
var extInputs, defInputs, parent, tmpl, inputBlocks, outputBlocks, outputs, tmplInitializer, bloks, i, length,
name = obj.name, blok = block(name), log = new Log();
template(name);
extInputs = obj.inputs || (obj.inputs = {});
defInputs = blok.getInputs ? blok.getInputs() : {};
mergeParams(extInputs, defInputs);
if (blok.getInputBlocks) {
inputBlocks = blok.getInputBlocks();
length = inputBlocks.length;
for (i = 0; i < length; i++) {
initializeBlocks(inputBlocks[i], extInputs);
}
}
if (blok.getOutputs) {
outputs = blok.getOutputs(extInputs);
} else if (blok.getInputs) {
outputs = extInputs;
} else {
outputs = {};
}
obj.outputs = outputs;
if (blok.getOutputBlocks) {
outputBlocks = blok.getOutputBlocks();
length = outputBlocks.length;
for (i = 0; i < length; i++) {
initializeBlocks(outputBlocks[i], outputs);
}
}
if (blok.getStaticBlocks) {
bloks = blok.getStaticBlocks();
length = bloks.length;
for (i = 0; i < length; i++) {
initializeBlock({name:bloks[i], inputs:null});
}
}
};
// [ "foo", "bar", "mar"]
// [{ "name" : "foo/bar", params : {}}]
var initializeBlocks = function (keys, inputs) {
if (!inputs) {
return;
}
var i, length, values, last;
if (typeof keys !== "string") {
length = keys.length;
values = inputs[keys[0]];
last = (length == 1);
if (values instanceof Array) {
length = values.length;
for (i = 0; i < length; i++) {
if (last) {
initializeBlock(values[i]);
} else {
initializeBlocks(keys.slice(1), values[i]);
}
}
} else {
if (last) {
initializeBlock(values);
} else {
initializeBlocks(keys.slice(1), values);
}
}
return;
} else {
values = inputs[keys];
}
if (values instanceof Array) {
length = values.length;
for (i = 0; i < length; i++) {
initializeBlock(values[i]);
}
} else {
initializeBlock(values);
}
};
var insertData = function (jagg, template, parent, name, key, value) {
var keys, values, data = getData();
data = data[parent] || (data[parent] = {});
data = data[name] || (data[name] = {});
data = data[template] || (data[template] = {});
keys = data.keys || (data.keys = []);
values = data.values || (data.values = {});
keys.push(key);
values[key] = value;
};
var printData = function (tmpls) {
var key, tmpl, keys, values, i, length;
for (key in tmpls) {
if (tmpls.hasOwnProperty(key)) {
tmpl = tmpls[key];
keys = tmpl.keys;
values = tmpl.values;
length = keys.length;
for (i = 0; i < length; i++) {
print(values[keys[i]]);
}
}
}
};
var getUrlMapping = function (path) {
var urlMap = ctx.get("url.map"), url, configs, i, length, mapping, mappings, file;
if (urlMap) {
url = urlMap[path];
return url ? url : path;
}
file = new File("/jaggery.conf");
file.open("r");
configs = parse(file.readAll());
file.close();
urlMap = {};
mappings = configs.urlMappings;
length = mappings.length;
for (i = 0; i < length; i++) {
mapping = mappings[i];
urlMap[mapping.path] = mapping.url;
}
ctx.put("url.map", urlMap);
url = urlMap[path];
return url ? url : path;
};
var getRequestSegments = function(){
var href = request.getRequestURL()
var match = href.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)(\/[^?#]*)(\?[^#]*|)(#.*|)$/);
return match && {
protocol: match[1],
host: match[2],
hostname: match[3],
port: match[4],
pathname: match[5],
search: match[6],
hash: match[7]
}
};
var getMappedUrl = function (path) {
return getAbsoluteUrl(getUrlMapping(path));
};
var getAbsoluteUrl = function (path) {
var host = ""
if(isReverseProxyEnabled()){
host = "https://" + site.reverseProxy.host ;
}else{
var match = getRequestSegments();
var host = match.protocol + "//" + match.host;
}
return host + url(path);
};
var getSiteDomainFromRequest = function(){
var match = href.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)(\/[^?#]*)(\?[^#]*|)(#.*|)$/);
}
var getHttpsUrl = function(path, parameters){
var hostname = "";
var requestSegments = getRequestSegments();
mod = jagg.module("manager");
hostname = mod.getHTTPsURL();
hostname = hostname.replace("https://","");
// if the site is fronted by a proxy server
if(isReverseProxyEnabled()){
hostname = site.reverseProxy.host ;
//if a custom https port is used
if(site.reverseProxy.hosts_port){
hostname = hostname + ":" + site.reverseProxy.hosts_port;
}
}
return "https://" + hostname + url(path, parameters);
}
var url = function(path,parameters){
var tail = "";
if(parameters){
var params = [];
for (var key in parameters) {
params.push(key+"="+parameters[key]) ;
}
if(/\?/.test(path)){
tail = "&";
}
else{
tail = "?";
}
tail = tail + params.join("&");
}
return getSiteContext()+ path + tail;
};
var getTenantURLPrefix = function(tail) {
if (!tail) {
tail = "";
}
if( site.reverseProxy.tenantHeader == null ||
request.getHeader(site.reverseProxy.tenantHeader) == null){
if(getTenantDomain() != null){
return tail + "tenant=" + getTenantDomain();
}
}
return "";
}
// following function will generate a url with the currently activated tenant
var urlTenanted = function(path, parameters){
//if tenented add tenant url
if(getTenantDomain() != null && !(/(\?tenant\=|\&tenant\=)/i.test(path))){
if(!parameters){
parameters = {};
}
parameters.tenant = getTenantDomain();
}
if(isReverseProxyEnabled()){
return getHttpsUrl(path, parameters)
}
return url(path,parameters)
};
var getCarbonProxyContextPath = function(){
var CarbonUtils = Packages.org.wso2.carbon.utils.CarbonUtils;
var carbonUtils = new CarbonUtils();
var context = carbonUtils.getServerConfiguration().getFirstProperty("ProxyContextPath");
if(context != null)
return context;
else
return '';
};
var isReverseProxyEnabled = function(){
if(reverse_proxy != undefined){
return reverse_proxy;
}
if(site.reverseProxy.enabled){
if(site.reverseProxy.enabled == "auto"){
var xfwd = request.getHeader("X-Forwarded-Host");
if(xfwd != null){
var xfwd = xfwd.split(",")[0];
//if(xfwd.trim() == site.reverseProxy.host){
reverse_proxy = true;
site.reverseProxy.host = xfwd.trim();
//}
}else{
reverse_proxy = false;
}
}
else{
reverse_proxy = true;
}
}
else{
reverse_proxy = false;
}
return reverse_proxy;
};
var getSiteContext = function(){
if(isReverseProxyEnabled()){
//If we use a custom domain mapping we will not use the context.
if( site.reverseProxy.tenantHeader != null &&
request.getHeader(site.reverseProxy.tenantHeader) != null){
return "";
}
else{
return site.reverseProxy.context
}
}
var proxyContext = getCarbonProxyContextPath();
return proxyContext + site.context;
};
var getRegistryPath = function(path){
if(isReverseProxyEnabled()){
if(site.reverseProxy.regContext != undefined){
return site.reverseProxy.regContext + path;
}
return site.reverseProxy.context + path;
}
var ProxyContextPath = getCarbonProxyContextPath();
return ProxyContextPath + path;
}
var module = function (name, module) {
if (module) {
return modules[name] = module;
}
module = modules[name];
if (module) {
return module;
}
include(getModuleFile(name));
return modules[name];
};
var requir = function (path) {
var obj = requirs[path];
return obj ? obj : requirs[path] = require(path);
};
var block = function (name, blok) {
var parent;
if (blok) {
return bloks[name] = blok;
}
blok = bloks[name];
if (blok) {
return blok;
}
//we need to include and initialize
include(getBlockFile(name));
blok = bloks[name];
parent = blok.getParent;
if (parent) {
parent = parent();
inheritParent(blok, parent);
}
if (blok.initialize) {
//TODO which to pass into initialize method
blok.initialize(getData());
}
return bloks[name];
};
var template = function (name, tmpl) {
var blok, parent, init;
if (tmpl) {
return templates[name] = tmpl;
}
tmpl = templates[name];
if (tmpl) {
return tmpl;
}
blok = block(name);
parent = blok.getParent;
if (parent) {
name = parent();
}
tmpl = templates[name];
if (tmpl) {
return tmpl;
}
include(getTemplateFile(name));
init = initializer(name);
if (init.preInitialize) {
init.preInitialize();
}
return templates[name];
};
var initializer = function (name, init) {
var blok, parent;
if (init) {
return initializers[name] = init;
}
init = initializers[name];
if (init) {
return init;
}
blok = block(name);
parent = blok.getParent;
if (parent) {
name = parent();
}
init = initializers[name];
if (init) {
return init;
}
include(getInitializerFile(name));
return initializers[name];
};
var render = function (obj) {
var init, fn, inputs, outputs, name = obj.name, log = new Log(), blok;
setData(obj);
initializeBlock(obj);
include(getTemplateFile(name));
fn = template(name);
if (!fn) {
log.error("Template header and footer includes are missing for : " + name);
}
inputs = obj.inputs;
blok = block(name);
if (blok.getOutputs) {
outputs = blok.getOutputs(inputs);
} else if (blok.getInputs) {
outputs = inputs;
} else {
outputs = {};
}
init = initializer(name);
if (init.postInitialize) {
init.postInitialize(inputs, outputs);
}
fn(inputs, outputs, jagg);
};
var includeBlock = function (name, inputs) {
renderBlock(name, inputs, null, true);
};
var includeBlocks = function (bloks) {
if (!bloks) {
return;
}
var i, d, length;
if (bloks instanceof Array) {
length = bloks.length;
for (i = 0; i < length; i++) {
d = bloks[i];
renderBlock(d.name, d.inputs, d.outputs, false);
}
} else {
renderBlock(bloks.name, bloks.inputs, bloks.outputs, false);
}
};
var addHeaderCSS = function (template, key, css) {
css = '<link type="text/css" rel="stylesheet" href="' + url(getThemeFile(css)) + '"/>';
insertData(this, template, "header", "css", key, css);
};
var addHeaderCSSCode = function (template, key, css) {
css = '<style type="text/css">' + css + '</style>';
insertData(this, template, "header", "css", key, css);
};
var addHeaderJS = function (template, key, js) {
js = '<script type="text/javascript" src="' + url(getThemeFile(js)) + '"></script>\n';
insertData(this, template, "header", "js", key, js);
};
var addHeaderJSCode = function (template, key, js) {
js = '<script type="text/javascript">' + js + '</script>';
insertData(this, template, "header", "js", key, js);
};
var addHeaderCode = function (template, key, code) {
insertData(this, template, "header", "code", key, code);
};
var addFooterCSS = function (template, key, css) {
css = '<link type="text/css" rel="stylesheet" href="' + url(getThemeFile(css)) + '"/>';
insertData(this, template, "footer", "css", key, css);
};
var addFooterCSSCode = function (template, key, css) {
css = '<style type="text/css">' + css + '</style>';
insertData(this, template, "footer", "css", key, css);
};
var addFooterJS = function (template, key, js) {
js = '\t<script type="text/javascript" src="' + url(getThemeFile(js)) + '"></script>\n';
insertData(this, template, "footer", "js", key, js);
};
var addFooterJSCode = function (template, key, js) {
js = '<script type="text/javascript">' + js + '</script>';
insertData(this, template, "footer", "js", key, js);
};
var addFooterCode = function (template, key, code) {
insertData(this, template, "footer", "code", key, code);
};
var includeJag = function (path) {
include(getThemeFile(path));
};
var getTenantDomain = function(){
if(isReverseProxyEnabled()){
// check if tenant header exists
if(site.reverseProxy.tenantHeader != undefined && site.reverseProxy.tenantHeader != null
&& request.getHeader(site.reverseProxy.tenantHeader) != null){
return request.getHeader(site.reverseProxy.tenantHeader);
}
}
return request.getParameter("tenant");
}
var setCSRFToken = function(){
var cookie = request.getCookie("csrftoken");
var user = jagg.getUser();
var csrfuser = session.get('csrfuser');
//set CSRF if it is not set + you need to refresh the token if the user has changed.
if( !cookie || user != csrfuser){
//Use a secure random as the CSRF token.
var SecureRandom = Packages.java.security.SecureRandom;
var random = new SecureRandom();
var BigInteger = Packages.java.math.BigInteger;
var token = new BigInteger(130, random).toString(32);
var cookie= {'name':'csrftoken','value': token , 'maxAge': 86400, 'path':"/"};
session.put('csrfuser',user);
response.addCookie(cookie);
}
}
var isCSRFTokenValid = function(){
var log = new Log();
var cookie = request.getCookie("csrftoken");
var token = request.getHeader("X-CSRFToken");
var user = jagg.getUser();
if(cookie == null || cookie.value == token){
return true;
}
else{
log.info("CSRF Token error at "+request.getRequestURI());
return false;
}
}
var validateInputs = function(config){
var errors = [];
//set most used parapeters
config.name = { type:"name"};
config.provider = { type:"provider"};
config.version = { type:"name"};
for(var key in config){
var value = request.getParameter(key);
if(value == null){
if(config[key].required)
errors.push(key);
continue;
}
switch (config[key].type) {
case "url":
break;
case "input":
var regex = /([<>\"\'])/;
if(regex.test(value)) errors.push(key);
break;
case "number":
var regex = /^[0-9]*$/;
if(!regex.test(value)) errors.push(key);
break;
case "safetext":
var regex = /^[a-zA-Z0-9]*$/;
if(!regex.test(value)) errors.push(key);
break;
case "uuid":
var regex = /^[a-zA-Z0-9\-]*$/;
if(!regex.test(value)) errors.push(key);
break;
case "name":
var regex = /([~!#$;%^*+={}\|\\<>\"\'\/,])/;
if(regex.test(value)) errors.push(key);
break;
case "password":
var regex = /^[\S]{5,30}$/;
if(!regex.test(value)) errors.push(key);
break;
case "email":
var regex = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
if(!regex.test(value)) errors.push(key);
break;
case "provider":
var regex = /([~!#$;%^*+={}\|\\<>\"\'\,])/;
if(regex.test(value)) errors.push(key);
break;
default:
}
}
if(errors.length > 0){
return errors;
}
else{
return true;
}
}
return {
setUser:setUser,
getUser:getUser,
block:block,
module:module,
initializer:initializer,
includeBlock:includeBlock,
includeBlocks:includeBlocks,
render:render,
template:template,
require:requir,
getAbsoluteUrl:getAbsoluteUrl,
getMappedUrl:getMappedUrl,
printData:printData,
getUserTheme:getUserTheme,
getThemeFile:getThemeFile,
getModulesDir:getModulesDir,
data:getData,
addHeaderCSS:addHeaderCSS,
addHeaderCSSCode:addHeaderCSSCode,
addHeaderJS:addHeaderJS,
addHeaderJSCode:addHeaderJSCode,
addHeaderCode:addHeaderCode,
addFooterCSS:addFooterCSS,
addFooterCSSCode:addFooterCSSCode,
addFooterJS:addFooterJS,
addFooterJSCode:addFooterJSCode,
addFooterCode:addFooterCode,
includeJag:includeJag,
url:url,
urlTenanted:urlTenanted,
getRegistryPath:getRegistryPath,
getSiteContext:getSiteContext,
getHttpsUrl:getHttpsUrl,
getTenantDomain:getTenantDomain,
setCSRFToken:setCSRFToken,
isCSRFTokenValid:isCSRFTokenValid,
validateInputs:validateInputs,
getTenantURLPrefix:getTenantURLPrefix
};
}());
%>

@ -1,168 +0,0 @@
<%
var getAuthServerURL = function() {
return getAPIStoreObj().getAuthServerURL();
};
var getHTTPsURL = function() {
return getAPIStoreObj().getHTTPsURL(request.getRequestURL());
};
var getHTTPURL = function() {
return getAPIStoreObj().getHTTPURL();
};
var getHostname = function() {
return getAPIStoreObj().getHostName();
};
var getAPIPublisherURL = function() {
var result,log=new Log();
var store = getAPIStoreObj();
try {
result = store.getAPIPublisherURL();
if (log.isDebugEnabled()) {
log.debug("getAPIPublisherURL : ");
}
return {
error:false,
url:result
};
} catch (e) {
return {
error:true,
message:e.message.split(":")[1]
};
}
};
var getServer = function() {
return {
server : "localhost",
port : "9443"
};
};
var isSelfSignupEnabled = function(){
return getAPIStoreObj().isSelfSignupEnabled();
};
var isSelfSignupEnabledForTenantUser = function(tenantDomain){
var log = new Log();
try {
if (tenantDomain == null) {
return getAPIStoreObj().isSelfSignupEnabledForTenant("carbon.super");
} else {
return getAPIStoreObj().isSelfSignupEnabledForTenant(tenantDomain);
}
} catch (e) {
log.error(e.message);
return false;
}
};
var getAdminCookie = function() {
//TODO : this should be set in the Context during the deployment
};
var getAPIStoreObj = function() {
var tenantDomain = jagg.getTenantDomain();
var user = jagg.getUser();
var store;
if (user == null) {
store = require('apimstore');
var storeHostObj = new store.APIStore();
if(tenantDomain != null && tenantDomain != ""){
storeHostObj.loadRegistryOfTenant(tenantDomain);
}
return storeHostObj;
} else {
store = require('apimstore');
return new store.APIStore(user.username);
}
};
var getAPIConsumerObj = function() {
var user = jagg.getUser();
var APIManagerFactory = Packages.org.wso2.carbon.apimgt.impl.APIManagerFactory;
return APIManagerFactory.getInstance().getAPIConsumer(user);
};
var loadTenantRegistry = function (tenantDomain) {
try {
if (tenantDomain != null && tenantDomain != "") {
getAPIStoreObj().loadRegistryOfTenant(tenantDomain);
return
{
error:false
}
;
}
} catch (e) {
return {
error:true,
message:e.message
};
}
};
var loadTenantAxisConfiguration = function (tenantDomain) {
try {
if (tenantDomain != null && tenantDomain != "") {
getAPIStoreObj().loadAxisConfigOfTenant(String(tenantDomain));
return
{
error:false
}
;
}
} catch (e) {
return {
error:true,
message:e.message
};
}
};
var getActiveTenantDomains=function(){
var tenantDomains,
log = new Log(),
store = jagg.module("manager").getAPIStoreObj();
try {
tenantDomains = store.getActiveTenantDomains();
tenantDomains = parse(stringify(tenantDomains));
if (log.isDebugEnabled()) {
log.debug("isTenantMode : " + stringify(api));
}
return {
error:false,
tenantDomains:tenantDomains
};
} catch (e) {
//log.error(e.message);
return {
error:true,
tenantDomains:null,
message:e.message
};
}
};
var getUsageClient = function(){
var user = jagg.getUser();
return org.wso2.carbon.apimgt.usage.client.UsageClient.getClient(user);
}
%>

@ -0,0 +1,10 @@
<module name="lifecycle" xmlns="http://wso2.org/projects/jaggery/module.xml">
<script>
<name>core</name>
<path>scripts/core/core.js</path>
</script>
<script>
<name>api</name>
<path>scripts/api/api.js</path>
</script>
</module>

@ -0,0 +1,89 @@
/*
* Copyright (c) WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* The api namespace exposes methods to retrieve information individual states of the lifecycles
* deployed to the Governance Registry
* @namespace
* @example
* var api = require('lifecycle').api;
* var superTenantId=-1234;
*
* api.getLifecycleList(superTenantId);
* @requires store
* @requires event
* @requires utils
* @requires Packages.org.wso2.carbon.governance.lcm.util.CommonUtil
*/
var api = {};
(function (api, core) {
var log = new Log('lifecycle');
/**
* Represents a class which models a lifecycle
* @constructor
* @param {Object} definiton The JSON definition of a lifecycle
* @memberOf api
*/
function Lifecycle(definiton) {
this.definition = definiton;
}
/**
* Returns the JSON definition for the lifecycle managed by the instance
* @return {Object} Lifecycle definition
*/
Lifecycle.prototype.getDefinition = function () {
return this.definition;
};
/**
* Returns the name of the lifecycle
* @return {String} The name of the lifecycle
*/
Lifecycle.prototype.getName = function () {
if (!this.definition.name) {
throw 'Unable to locate name attribute in the lifecycle definition ';
}
return this.definition.name;
};
/**
* Returns an instance of the Lifecycle class
* @example
* var lc = api.getLifecycle('SimpleLifeCycle',-1234);
* lc.nextStates('initial');
* @param {String} lifecycleName The name of the lifecycle
* @param {Number} tenantDomain The tenant ID
* @return {Object} An instance of the Lifecycle class
* @throws Unable to locate lifecycle without a tenant ID
*/
api.getLifecycle = function (tenantDomain, APIProvider) {
if (!tenantDomain) {
throw 'Unable to locate lifecycle without a tenantDomain';
}
var lcJSON = core.getJSONDef(tenantDomain,APIProvider);
if (!lcJSON) {
log.warn('Unable to locate lifecycle for the tenant: ' + tenantDomain);
return null; //TODO: This should throw an exception
}
return new Lifecycle(lcJSON);
};
}(api, core));

@ -0,0 +1,158 @@
/*
* Copyright (c) WSO2 Inc. (http://wso2.com) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* The core namespace contains methods that load the lifecycle definitions from the registry
* @namespace
* @example
* var core = require('lifecycle').core;
* core.init(); //Should only be called once in the lifecycle of an app.Ideally in an init script
* @requires store
* @requires event
* @requires utils
* @requires Packages.org.wso2.carbon.governance.lcm.util.CommonUtil
*/
var core = {};
(function(core) {
var CommonUtil = Packages.org.wso2.carbon.governance.lcm.util.CommonUtil;
var LC_MAP = 'lc.map';
var EMPTY = '';
var log = new Log('lifecycle');
var addRawLifecycle = function(lifecycleName, content, tenantId) {
var lcMap = core.configs(tenantId);
if (!lcMap.raw) {
lcMap.raw = {};
}
lcMap.raw[lifecycleName] = new String(content);
};
var addJsonLifecycle = function(lifecycleName, definition, tenantId) {
var lcMap = core.configs(tenantId);
if (!lcMap.json) {
lcMap.json = {};
}
lcMap.json[lifecycleName] = definition;
};
/**
* Converts array references to properties.The JSON conversion produces some properties which need to be accessed
* using array indexes.
* @param {Object} obj Unaltered JSON object
* @return {Object} JSON object with resolved array references
*/
var transformJSONLifecycle = function(obj) {
obj.configuration = obj.configuration[0];
obj.configuration.lifecycle = obj.configuration.lifecycle[0];
obj.configuration.lifecycle.scxml = obj.configuration.lifecycle.scxml[0];
var states = obj.configuration.lifecycle.scxml.state;
var stateObj = {};
var state;
for (var index = 0; index < states.length; index++) {
state = states[index];
stateObj[state.id.toLowerCase()] = state;
if (stateObj[state.id.toLowerCase()].datamodel) {
stateObj[state.id.toLowerCase()].datamodel = stateObj[state.id.toLowerCase()].datamodel[0];
}
}
obj.configuration.lifecycle.scxml.state = stateObj;
return obj;
};
/*
Creates an xml file from the contents of an Rxt file
@rxtFile: An rxt file
@return: An xml file
*/
var createXml = function(content) {
var fixedContent = content.replace('<xml version="1.0"?>', EMPTY).replace('</xml>', EMPTY);
return new XML(fixedContent);
};
var parseLifeycle = function(content) {
var ref = require('utils').xml;
var obj = ref.convertE4XtoJSON(createXml(content));
return obj;
};
var loadLifecycles = function(tenantDomain,APIProvider) {
//Obtain the definition
content = APIProvider.getLifecycleConfiguration(tenantDomain);
//Store the raw lifecycle
addRawLifecycle("APILifeCycle", content, tenantDomain);
//Parse the raw lifecycle definition into a json
var jsonLifecycle = parseLifeycle(new String(content));
//Correct any array references
jsonLifecycle = transformJSONLifecycle(jsonLifecycle);
//Store the json lifecycle definition
addJsonLifecycle("APILifeCycle", jsonLifecycle, tenantDomain);
if(log.isDebugEnabled()){
log.debug('Found lifecycle: ' + jsonLifecycle.name + ' tenant: ' + tenantDomain);
}
};
var init = function(tenantDomain,APIProvider) {
loadLifecycles(tenantDomain,APIProvider);
};
core.force = function(tenantDomain,APIProvider) {
init(tenantDomain,APIProvider);
};
/**
* Returns the lifecycle map which is stored in the application context
* The map is maintained on a per user basis
* @param {Number} tenantId The tenant ID
* @return {Object} The lifecycle map
*/
core.configs = function(tenantDomain) {
var lcMap = application.get(LC_MAP);
if (!lcMap) {
log.debug('Creating lcMap in the application context');
lcMap = {};
application.put(LC_MAP, lcMap);
}
if (!lcMap[tenantDomain]) {
log.debug('Creating lcMap for the tenant: ' + tenantDomain + ' in application context');
lcMap[tenantDomain] = {};
}
return lcMap[tenantDomain];
};
/**
* Returns the JSON definition of the provided lifecycle for the given tenant
* @param {Number} tenantDomain The tenant Domain
* @return {Object} The JSON definitin of the lifecycle
* @throws There is no lifcycle information for the tenant
* @throws There is no json lifecycle information for the lifecycle of the tenant
*/
core.getJSONDef = function(tenantDomain,APIProvider) {
var lifecycleName='APILifeCycle';
var lcMap = core.configs(tenantDomain);
if (!lcMap) {
throw 'There is no lifecycle information for the tenant: ' + tenantDomain;
}
//if (!lcMap.json) {
// throw 'There is no json lifecycle information for the lifecycle of tenant: ' + tenantDomain;
//}
if (!lcMap.json) {
core.force(tenantDomain,APIProvider);
lcMap = core.configs(tenantDomain);
if (!lcMap.json[lifecycleName]){
throw 'There is no lifecycle information for ';
}
}
return lcMap.json[lifecycleName];
};
}(core));

@ -26,123 +26,123 @@ var client = {};
(function (client) {
var Util = Packages.org.jaggeryjs.modules.sso.common.util.Util,
carbon = require('carbon'),
log = new Log();
/**
* obtains an encoded saml response and return a decoded/unmarshalled saml obj
* @param samlResp
* @return {*}
*/
client.getSamlObject = function (samlResp) {
var decodedResp = Util.decode(samlResp);
return Util.unmarshall(decodedResp);
};
/**
* validating the signature of the response saml object
*/
client.validateSignature = function (samlObj, config) {
var tDomain = Util.getDomainName(samlObj);
var tId = carbon.server.tenantId({domain: tDomain});
return Util.validateSignature(samlObj,
config.KEY_STORE_NAME, config.KEY_STORE_PASSWORD, config.IDP_ALIAS, tId, tDomain);
};
/**
* Checking if the request is a logout call
*/
client.isLogoutRequest = function (samlObj) {
return samlObj instanceof Packages.org.opensaml.saml2.core.LogoutRequest;
};
/**
* Checking if the request is a logout call
*/
client.isLogoutResponse = function (samlObj) {
return samlObj instanceof Packages.org.opensaml.saml2.core.LogoutResponse;
};
/**
* getting url encoded saml authentication request
* @param issuerId
*/
client.getEncodedSAMLAuthRequest = function (issuerId) {
return Util.encode(
Util.marshall(
new Packages.org.jaggeryjs.modules.sso.common.builders.AuthReqBuilder().buildAuthenticationRequest(issuerId)
));
};
/**
* get url encoded saml logout request
*/
client.getEncodedSAMLLogoutRequest = function (user, sessionIndex, issuerId) {
return Util.encode(
Util.marshall(
new Packages.org.jaggeryjs.modules.sso.common.builders.LogoutRequestBuilder().buildLogoutRequest(user, sessionIndex,
Packages.org.jaggeryjs.modules.sso.common.constants.SSOConstants.LOGOUT_USER,
issuerId)));
};
/**
* Reads the returning SAML login response and populates a session info object
*/
client.decodeSAMLLoginResponse = function (samlObj, samlResp, sessionId) {
var samlSessionObj = {
// sessionId, loggedInUser, sessionIndex, samlToken
};
if (samlObj instanceof Packages.org.opensaml.saml2.core.Response) {
var assertions = samlObj.getAssertions();
// extract the session index
if (assertions != null && assertions.size() > 0) {
var authenticationStatements = assertions.get(0).getAuthnStatements();
var authnStatement = authenticationStatements.get(0);
if (authnStatement != null) {
if (authnStatement.getSessionIndex() != null) {
samlSessionObj.sessionIndex = authnStatement.getSessionIndex();
}
}
}
// extract the username
if (assertions != null && assertions.size() > 0) {
var subject = assertions.get(0).getSubject();
if (subject != null) {
if (subject.getNameID() != null) {
samlSessionObj.loggedInUser = subject.getNameID().getValue();
}
}
}
samlSessionObj.sessionId = sessionId;
samlSessionObj.samlToken = samlResp;
}
return samlSessionObj;
};
/**
* This method is to get the session index when a single logout happens
* The IDP sends a logout request to the ACS with the session index, so that
* the app can invalidate the associated HTTP Session
*/
client.decodeSAMLLogoutRequest = function (samlObj) {
var sessionIndex = null;
if (samlObj instanceof org.opensaml.saml2.core.LogoutRequest) {
var sessionIndexes = samlObj.getSessionIndexes();
if (sessionIndexes != null && sessionIndexes.size() > 0) {
sessionIndex = sessionIndexes.get(0).getSessionIndex();
}
}
return sessionIndex;
};
var Util = Packages.org.jaggeryjs.modules.sso.common.util.Util,
carbon = require('carbon'),
log = new Log();
/**
* obtains an encoded saml response and return a decoded/unmarshalled saml obj
* @param samlResp
* @return {*}
*/
client.getSamlObject = function (samlResp) {
var decodedResp = Util.decode(samlResp);
return Util.unmarshall(decodedResp);
};
/**
* validating the signature of the response saml object
*/
client.validateSignature = function (samlObj, config) {
var tDomain = Util.getDomainName(samlObj);
var tId = carbon.server.tenantId({domain: tDomain});
return Util.validateSignature(samlObj,
config.KEY_STORE_NAME, config.KEY_STORE_PASSWORD, config.IDP_ALIAS, tId, tDomain);
};
/**
* Checking if the request is a logout call
*/
client.isLogoutRequest = function (samlObj) {
return samlObj instanceof Packages.org.opensaml.saml2.core.LogoutRequest;
};
/**
* Checking if the request is a logout call
*/
client.isLogoutResponse = function (samlObj) {
return samlObj instanceof Packages.org.opensaml.saml2.core.LogoutResponse;
};
/**
* getting url encoded saml authentication request
* @param issuerId
*/
client.getEncodedSAMLAuthRequest = function (issuerId) {
return Util.encode(
Util.marshall(
new Packages.org.jaggeryjs.modules.sso.common.builders.AuthReqBuilder().buildAuthenticationRequest(issuerId)
));
};
/**
* get url encoded saml logout request
*/
client.getEncodedSAMLLogoutRequest = function (user, sessionIndex, issuerId) {
return Util.encode(
Util.marshall(
new Packages.org.jaggeryjs.modules.sso.common.builders.LogoutRequestBuilder().buildLogoutRequest(user, sessionIndex,
Packages.org.jaggeryjs.modules.sso.common.constants.SSOConstants.LOGOUT_USER,
issuerId)));
};
/**
* Reads the returning SAML login response and populates a session info object
*/
client.decodeSAMLLoginResponse = function (samlObj, samlResp, sessionId) {
var samlSessionObj = {
// sessionId, loggedInUser, sessionIndex, samlToken
};
if (samlObj instanceof Packages.org.opensaml.saml2.core.Response) {
var assertions = samlObj.getAssertions();
// extract the session index
if (assertions != null && assertions.size() > 0) {
var authenticationStatements = assertions.get(0).getAuthnStatements();
var authnStatement = authenticationStatements.get(0);
if (authnStatement != null) {
if (authnStatement.getSessionIndex() != null) {
samlSessionObj.sessionIndex = authnStatement.getSessionIndex();
}
}
}
// extract the username
if (assertions != null && assertions.size() > 0) {
var subject = assertions.get(0).getSubject();
if (subject != null) {
if (subject.getNameID() != null) {
samlSessionObj.loggedInUser = subject.getNameID().getValue();
}
}
}
samlSessionObj.sessionId = sessionId;
samlSessionObj.samlToken = samlResp;
}
return samlSessionObj;
};
/**
* This method is to get the session index when a single logout happens
* The IDP sends a logout request to the ACS with the session index, so that
* the app can invalidate the associated HTTP Session
*/
client.decodeSAMLLogoutRequest = function (samlObj) {
var sessionIndex = null;
if (samlObj instanceof org.opensaml.saml2.core.LogoutRequest) {
var sessionIndexes = samlObj.getSessionIndexes();
if (sessionIndexes != null && sessionIndexes.size() > 0) {
sessionIndex = sessionIndexes.get(0).getSessionIndex();
}
}
return sessionIndex;
};
}(client));

@ -0,0 +1,6 @@
<module name="utils" xmlns="http://wso2.org/projects/jaggery/module.xml">
<script>
<name>xml</name>
<path>scripts/xml/xml.js</path>
</script>
</module>

@ -0,0 +1,138 @@
/*
* Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
var xml = {};
(function () {
var log=new Log('util.xml')
/*
The method is used to create a JSON object using
an xml object.
@xmlElement: An xml element object to be processed
@return: A pseudo object containing the properties of the
xml element.
*/
var createJSONObject = function (xmlElement) {
var pseudo = {};
//Extract all attributes
var attributes = xmlElement.@*;
//Fill the pseudo object with the attributes of the element
for (var attributeKey in attributes) {
var attribute = attributes[attributeKey];
pseudo[attribute.localName()] = attribute.toString();
}
return pseudo;
};
/*
The function converts an E4X Xml object to a JSON object
This function has been adapted from the work of Oleg Podsechin available at
https://gist.github.com/olegp/642667
It uses a slightly modified version of his algorithm , therefore
all credit should be attributed to Oleg Podsechin.
IMPORTANT:
1. It does not create a 1..1 mapping due to the differences
between Xml and JSON.It is IMPORTANT that you verify the structure
of the object generated before using it.
2. The input xml object must not contain the xml header information
This is a known bug 336551 (Mozilla Developer Network)
Source: https://developer.mozilla.org/en/docs/E4X
Please remove the header prior to sending the xml object for processing.
@root: A starting element in an E4X Xml object
@return: A JSON object mirroring the provided Xml object
*/
var recursiveConvertE4XtoJSON = function (root) {
log.debug('Root: ' + root.localName());
//Obtain child nodes
var children = root.*;
//The number of children
var numChildren = children.length();
//No children
if (numChildren == 0) {
//Extract contents
return createJSONObject(root);
}
else {
//Create an empty object
var rootObject = createJSONObject(root);
//Could be multiple children
for (var childElementKey in children) {
var child = children[childElementKey];
log.debug('Examining child: ' + child.localName());
//If the child just contains a single value then stop
if (child.localName() == undefined) {
log.debug('Child is undefined: ' + child.toString());
//Change the object to just a key value pair
rootObject[root.localName()] = child.toString();
return rootObject;
}
//Make a recursive call to construct the child element
var createdObject = recursiveConvertE4XtoJSON(child);
log.debug('Converted object: ' + stringify(createdObject));
//Check if the root object has the property
if (rootObject.hasOwnProperty(child.localName())) {
log.debug('key: ' + child.localName() + ' already present.');
rootObject[child.localName()].push(createdObject);
}
else {
log.debug('key: ' + child.localName() + ' not present.');
rootObject[child.localName()] = [];
rootObject[child.localName()].push(createdObject);
}
}
log.debug('root: ' + root.localName());
return rootObject;
}
};
/**
* The function is used to convert an E4X xml to JSON
* @param root
*/
xml.convertE4XtoJSON = function (root) {
return recursiveConvertE4XtoJSON(root);
};
}());

@ -1093,7 +1093,7 @@
<carbon.governance.version>4.6.4</carbon.governance.version>
<!-- Carbon Device Management -->
<carbon.device.mgt.version>1.2.3-SNAPSHOT</carbon.device.mgt.version>
<carbon.device.mgt.version>1.2.6-SNAPSHOT</carbon.device.mgt.version>
<carbon.device.mgt.version.range>[1.1.1, 2.0.0)</carbon.device.mgt.version.range>
<!-- IOT Device Management -->
@ -1110,7 +1110,7 @@
<carbon.mediation.version>4.6.6</carbon.mediation.version>
<!-- Carbon Analytics Common (DAS) -->
<carbon.analytics.common.version>5.1.3</carbon.analytics.common.version>
<carbon.analytics.common.version>5.1.4</carbon.analytics.common.version>
<!-- Tomcat -->
<orbit.tomcat.version>7.0.59.wso2v1</orbit.tomcat.version>

Loading…
Cancel
Save