-
Notifications
You must be signed in to change notification settings - Fork 430
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2318 from constantine2nd/develop
Logout a user after 2 minutes of inactivity
- Loading branch information
Showing
7 changed files
with
248 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1242,6 +1242,98 @@ trait APIMethods510 { | |
} | ||
|
||
|
||
staticResourceDocs += ResourceDoc( | ||
getMetrics, | ||
implementedInApiVersion, | ||
"getMetrics", | ||
"GET", | ||
"/management/metrics", | ||
"Get Metrics", | ||
s"""Get the all metrics | ||
| | ||
|require CanReadMetrics role | ||
| | ||
|Filters Part 1.*filtering* (no wilde cards etc.) parameters to GET /management/metrics | ||
| | ||
|Should be able to filter on the following metrics fields | ||
| | ||
|eg: /management/metrics?from_date=$DateWithMsExampleString&to_date=$DateWithMsExampleString&limit=50&offset=2 | ||
| | ||
|1 from_date (defaults to one week before current date): eg:from_date=$DateWithMsExampleString | ||
| | ||
|2 to_date (defaults to current date) eg:to_date=$DateWithMsExampleString | ||
| | ||
|3 limit (for pagination: defaults to 50) eg:limit=200 | ||
| | ||
|4 offset (for pagination: zero index, defaults to 0) eg: offset=10 | ||
| | ||
|5 sort_by (defaults to date field) eg: sort_by=date | ||
| possible values: | ||
| "url", | ||
| "date", | ||
| "user_name", | ||
| "app_name", | ||
| "developer_email", | ||
| "implemented_by_partial_function", | ||
| "implemented_in_version", | ||
| "consumer_id", | ||
| "verb" | ||
| | ||
|6 direction (defaults to date desc) eg: direction=desc | ||
| | ||
|eg: /management/metrics?from_date=$DateWithMsExampleString&to_date=$DateWithMsExampleString&limit=10000&offset=0&anon=false&app_name=TeatApp&implemented_in_version=v2.1.0&verb=POST&user_id=c7b6cb47-cb96-4441-8801-35b57456753a&[email protected]&consumer_id=78 | ||
| | ||
|Other filters: | ||
| | ||
|7 consumer_id (if null ignore) | ||
| | ||
|8 user_id (if null ignore) | ||
| | ||
|9 anon (if null ignore) only support two value : true (return where user_id is null.) or false (return where user_id is not null.) | ||
| | ||
|10 url (if null ignore), note: can not contain '&'. | ||
| | ||
|11 app_name (if null ignore) | ||
| | ||
|12 implemented_by_partial_function (if null ignore), | ||
| | ||
|13 implemented_in_version (if null ignore) | ||
| | ||
|14 verb (if null ignore) | ||
| | ||
|15 correlation_id (if null ignore) | ||
| | ||
|16 duration (if null ignore) non digit chars will be silently omitted | ||
| | ||
""".stripMargin, | ||
emptyObjectJson, | ||
metricsJsonV510, | ||
List( | ||
UserNotLoggedIn, | ||
UserHasMissingRoles, | ||
UnknownError | ||
), | ||
List(apiTagMetric, apiTagApi), | ||
Some(List(canReadMetrics))) | ||
|
||
lazy val getMetrics: OBPEndpoint = { | ||
case "management" :: "metrics" :: Nil JsonGet _ => { | ||
cc => { | ||
implicit val ec = EndpointContext(Some(cc)) | ||
for { | ||
(Full(u), callContext) <- authenticatedAccess(cc) | ||
_ <- NewStyle.function.hasEntitlement("", u.userId, ApiRole.canReadMetrics, callContext) | ||
httpParams <- NewStyle.function.extractHttpParamsFromUrl(cc.url) | ||
(obpQueryParams, callContext) <- createQueriesByHttpParamsFuture(httpParams, callContext) | ||
metrics <- Future(APIMetrics.apiMetrics.vend.getAllMetrics(obpQueryParams)) | ||
} yield { | ||
(JSONFactory510.createMetricsJson(metrics), HttpCode.`200`(callContext)) | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
|
||
staticResourceDocs += ResourceDoc( | ||
getCustomersForUserIdsOnly, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,9 +39,10 @@ import code.users.UserAttribute | |
import code.views.system.{AccountAccess, ViewDefinition} | ||
import com.openbankproject.commons.model.{Address, AtmId, AtmT, BankId, BankIdAccountId, Customer, Location, Meta} | ||
import com.openbankproject.commons.util.{ApiVersion, ScannedApiVersion} | ||
import java.util.Date | ||
|
||
import java.util.Date | ||
import code.consent.MappedConsent | ||
import code.metrics.APIMetric | ||
import net.liftweb.common.Box | ||
import net.liftweb.json.parse | ||
|
||
|
@@ -229,11 +230,29 @@ case class UserAttributesResponseJsonV510( | |
case class CustomerIdJson(id: String) | ||
case class CustomersIdsJsonV510(customers: List[CustomerIdJson]) | ||
|
||
case class MetricJsonV510( | ||
user_id: String, | ||
url: String, | ||
date: Date, | ||
user_name: String, | ||
app_name: String, | ||
developer_email: String, | ||
implemented_by_partial_function: String, | ||
implemented_in_version: String, | ||
consumer_id: String, | ||
verb: String, | ||
correlation_id: String, | ||
duration: Long, | ||
target_ip: String, | ||
source_ip: String | ||
) | ||
case class MetricsJsonV510(metrics: List[MetricJsonV510]) | ||
|
||
object JSONFactory510 extends CustomJsonFormats { | ||
|
||
def createCustomersIds(customers : List[Customer]): CustomersIdsJsonV510 = | ||
CustomersIdsJsonV510(customers.map(x => CustomerIdJson(x.customerId))) | ||
|
||
def waitingForGodot(sleep: Long): WaitingForGodotJsonV510 = WaitingForGodotJsonV510(sleep) | ||
|
||
def createAtmsJsonV510(atmAndAttributesTupleList: List[(AtmT, List[AtmAttribute])] ): AtmsJsonV510 = { | ||
|
@@ -242,7 +261,7 @@ object JSONFactory510 extends CustomJsonFormats { | |
createAtmJsonV510(atmAndAttributesTuple._1,atmAndAttributesTuple._2) | ||
)) | ||
} | ||
|
||
def createAtmJsonV510(atm: AtmT, atmAttributes:List[AtmAttribute]): AtmJsonV510 = { | ||
AtmJsonV510( | ||
id = Some(atm.atmId.value), | ||
|
@@ -397,31 +416,31 @@ object JSONFactory510 extends CustomJsonFormats { | |
phone = Some(atmJsonV510.phone) | ||
) | ||
} | ||
|
||
def getCustomViewNamesCheck(views: List[ViewDefinition]): CheckSystemIntegrityJsonV510 = { | ||
val success = views.size == 0 | ||
val debugInfo = if(success) None else Some(s"Incorrect custom views: ${views.map(_.viewId.value).mkString(",")}") | ||
CheckSystemIntegrityJsonV510( | ||
success = success, | ||
debug_info = debugInfo | ||
) | ||
} | ||
} | ||
def getSystemViewNamesCheck(views: List[ViewDefinition]): CheckSystemIntegrityJsonV510 = { | ||
val success = views.size == 0 | ||
val debugInfo = if(success) None else Some(s"Incorrect system views: ${views.map(_.viewId.value).mkString(",")}") | ||
CheckSystemIntegrityJsonV510( | ||
success = success, | ||
debug_info = debugInfo | ||
) | ||
} | ||
} | ||
def getAccountAccessUniqueIndexCheck(groupedRows: Map[String, List[AccountAccess]]): CheckSystemIntegrityJsonV510 = { | ||
val success = groupedRows.size == 0 | ||
val debugInfo = if(success) None else Some(s"Incorrect system views: ${groupedRows.map(_._1).mkString(",")}") | ||
CheckSystemIntegrityJsonV510( | ||
success = success, | ||
debug_info = debugInfo | ||
) | ||
} | ||
} | ||
def getSensibleCurrenciesCheck(bankCurrencies: List[String], accountCurrencies: List[String]): CheckSystemIntegrityJsonV510 = { | ||
val incorrectCurrencies: List[String] = bankCurrencies.filterNot(c => accountCurrencies.contains(c)) | ||
val success = incorrectCurrencies.size == 0 | ||
|
@@ -430,7 +449,7 @@ object JSONFactory510 extends CustomJsonFormats { | |
success = success, | ||
debug_info = debugInfo | ||
) | ||
} | ||
} | ||
def getOrphanedAccountsCheck(orphanedAccounts: List[String]): CheckSystemIntegrityJsonV510 = { | ||
val success = orphanedAccounts.size == 0 | ||
val debugInfo = if(success) None else Some(s"Orphaned account's ids: ${orphanedAccounts.mkString(",")}") | ||
|
@@ -439,7 +458,7 @@ object JSONFactory510 extends CustomJsonFormats { | |
debug_info = debugInfo | ||
) | ||
} | ||
|
||
def getConsentInfoJson(consent: MappedConsent): ConsentJsonV510 = { | ||
val jsonWebTokenAsJValue: Box[ConsentJWT] = JwtUtil.getSignedPayloadAsJson(consent.jsonWebToken).map(parse(_).extract[ConsentJWT]) | ||
ConsentJsonV510( | ||
|
@@ -450,7 +469,7 @@ object JSONFactory510 extends CustomJsonFormats { | |
jsonWebTokenAsJValue.map(_.entitlements).toOption | ||
) | ||
} | ||
|
||
def getApiInfoJSON(apiVersion : ApiVersion, apiVersionStatus: String) = { | ||
val organisation = APIUtil.getPropsValue("hosted_by.organisation", "TESOBE") | ||
val email = APIUtil.getPropsValue("hosted_by.email", "[email protected]") | ||
|
@@ -494,7 +513,7 @@ object JSONFactory510 extends CustomJsonFormats { | |
value = atmAttribute.value, | ||
is_active = atmAttribute.isActive | ||
) | ||
|
||
def createAtmAttributesJson(atmAttributes: List[AtmAttribute]): AtmAttributesResponseJsonV510 = | ||
AtmAttributesResponseJsonV510(atmAttributes.map(createAtmAttributeJson)) | ||
|
||
|
@@ -512,5 +531,30 @@ object JSONFactory510 extends CustomJsonFormats { | |
def createUserAttributesJson(userAttribute: List[UserAttribute]): UserAttributesResponseJsonV510 = { | ||
UserAttributesResponseJsonV510(userAttribute.map(createUserAttributeJson)) | ||
} | ||
|
||
def createMetricJson(metric: APIMetric): MetricJsonV510 = { | ||
MetricJsonV510( | ||
user_id = metric.getUserId(), | ||
user_name = metric.getUserName(), | ||
developer_email = metric.getDeveloperEmail(), | ||
app_name = metric.getAppName(), | ||
url = metric.getUrl(), | ||
date = metric.getDate(), | ||
consumer_id = metric.getConsumerId(), | ||
verb = metric.getVerb(), | ||
implemented_in_version = metric.getImplementedInVersion(), | ||
implemented_by_partial_function = metric.getImplementedByPartialFunction(), | ||
correlation_id = metric.getCorrelationId(), | ||
duration = metric.getDuration(), | ||
target_ip = metric.getSourceIp(), | ||
source_ip = metric.getTargetIp() | ||
) | ||
} | ||
|
||
def createMetricsJson(metrics: List[APIMetric]): MetricsJsonV510 = { | ||
MetricsJsonV510(metrics.map(createMetricJson)) | ||
} | ||
|
||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// holds the idle duration in ms (current value = 2 minutes) | ||
var timeoutInterval = 120000; | ||
// holds the timeout variables for easy destruction and reconstruction of the setTimeout hooks | ||
var timeHook = null; | ||
|
||
function initializeTimeHook() { | ||
// this method has the purpose of creating our timehooks and scheduling the call to our logout function when the idle time has been reached | ||
if (timeHook == null) { | ||
timeHook = setTimeout( function () { destroyTimeHook(); logout(); }.bind(this), timeoutInterval); | ||
} | ||
} | ||
|
||
function destroyTimeHook() { | ||
// this method has the sole purpose of destroying any time hooks we might have created | ||
clearTimeout(timeHook); | ||
timeHook = null; | ||
} | ||
|
||
function resetTimeHook() { | ||
// this method replaces the current time hook with a new time hook | ||
destroyTimeHook(); | ||
initializeTimeHook(); | ||
console.log("Reset inactivity of a user"); | ||
} | ||
|
||
function setupListeners() { | ||
// here we setup the event listener for the mouse click operation | ||
document.addEventListener("click", function () { resetTimeHook(); }.bind(this)); | ||
document.addEventListener("mousemove", function () { resetTimeHook(); }.bind(this)); | ||
document.addEventListener("mousedown", function () { resetTimeHook(); }.bind(this)); | ||
document.addEventListener("keypress", function () { resetTimeHook(); }.bind(this)); | ||
document.addEventListener("touchmove", function () { resetTimeHook(); }.bind(this)); | ||
console.log("Listeners for user inactivity activated"); | ||
} | ||
|
||
function destroyListeners() { | ||
// here we destroy event listeners for the mouse click operation | ||
document.removeEventListener("click", function () { resetTimeHook(); }.bind(this)); | ||
document.removeEventListener("mousemove", function () { resetTimeHook(); }.bind(this)); | ||
document.removeEventListener("mousedown", function () { resetTimeHook(); }.bind(this)); | ||
document.removeEventListener("keypress", function () { resetTimeHook(); }.bind(this)); | ||
document.removeEventListener("touchmove", function () { resetTimeHook(); }.bind(this)); | ||
console.log("Listeners for user inactivity deactivated"); | ||
} | ||
|
||
function logout() { | ||
const elem = document.getElementById("loggedIn-username"); | ||
if(elem) { | ||
location.href = '/user_mgt/logout'; | ||
destroyListeners(); | ||
console.log("Logging you out due to inactivity.."); | ||
} | ||
} | ||
|
||
// self executing function to trigger the operation on page load | ||
(function () { | ||
// to prevent any lingering timeout handlers preventing memory leaks | ||
destroyTimeHook(); | ||
// setup a fresh time hook | ||
initializeTimeHook(); | ||
// setup initial event listeners | ||
setupListeners(); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.