import { getCachedJWT } from '@/api/api-cache.js'
import api from '@/api'
import appService from '@/services/app-service.js'
import envService from '@/services/env-service.js'
import { errorLogger } from '@/plugins/error-logger.js'
import * as Sentry from '@sentry/browser'
import APIUrls from '@/config/simpliciti-apis.js'
const md5 = require('md5')
function isUserAuditEnabled() {
return envService.getEnvValue('VUE_APP_DISABLE_USER_AUDIT', '0') !== '1'
}
/**
* @namespace Services
* @category Services
* @module logging-service
* */
//Hit third party provider once (to avoid API limits)
let browserIP = null
async function getBrowserIP() {
if (browserIP) {
return browserIP
}
try {
let r = await fetch('https://api.ipify.org?format=json')
r = await r.json()
browserIP = r.ip
return r.ip || ''
} catch (err) {
console.warn('Warning: Retrieving client IP', err.stack || err)
}
}
/**
* Will log a session event (auth required)
* @function createGeoredClientUserSession
*/
export async function createGeoredClientUserSession(apiWrapperOptions = {}) {
if (!isUserAuditEnabled()) {
return false
}
//Try catch any errors until API fix (to be able to detect UniqueConstraintViolationException)
try {
let jwt = await getCachedJWT('createGeoredClientUserSession')
if (jwt) {
await api.v3.post(
APIUrls.APIV3_USER_SESSIONS,
{
application: appService.getAppIdentifier(),
sessionNumber: md5(jwt),
userAgent: window.navigator.userAgent,
ip: await getBrowserIP(),
version: appService.getAppVersion(),
},
apiWrapperOptions
)
}
} catch (err) {
console.warn('createGeoredClientUserSession::catch', err.stack)
//if (!err.stack.includes("409")) {
// throw err;
//}
}
return true
}
/**
* Will log an audit event (auth required)
* @function createGeoredClientUserAudit
*/
export async function createEditGeoredClientUserAudit(
functionId,
payload = {},
auditId = null
) {
if (!isUserAuditEnabled()) {
return false
}
let jwt = await getCachedJWT('createEditGeoredClientUserAudit')
if (jwt) {
let sessionNumber = md5(jwt)
if (auditId) {
return await api.v3.patch(`${APIUrls.APIV3_USER_AUDITS}/${auditId}`, {
sessionNumber,
functionId,
...payload,
})
} else {
return await api.v3.post(
`${APIUrls.APIV3_USER_AUDITS}?sessionNumber=${sessionNumber}`,
{
functionId,
...payload,
}
)
}
}
return true
}
/**
* @var {Object} scope default export object (internal)
*/
const scope = {
isUserAuditEnabled,
/**
*
* @param {String} payload.id User internal id
* @returns
*/
identifyUser(payload) {
try {
if (payload === null) {
Sentry.configureScope((scope) => scope.setUser(null))
return
}
Sentry.configureScope((scope) => scope.setUser(payload))
} catch (err) {
console.warn('logging: Fail to identify user')
errorLogger.logError(err)
}
},
setContext(contextName, payload = {}) {
try {
Sentry.setContext(contextName, payload)
} catch (err) {
console.warn('logging: Fail to set a context')
errorLogger.logError(err)
}
},
createSession: createGeoredClientUserSession,
createAudit: createEditGeoredClientUserAudit,
updateAudit: (auditId, functionId, payload) =>
createEditGeoredClientUserAudit(functionId, payload, auditId),
/**
* Will createAudit/updateAudit for a functionId while computing duration (elapsed time)
*/
activityAuditManager: {
//Internal: Will save the activity start timestamp
_startedActivities: {},
hasActivityStarted(functionId) {
return !!this._startedActivities[functionId]
},
/**
* Will create audit given a functionId (will also stop any audit in progress for the same functionId)
* @param {Number} functionId Module identifier
*/
async startActivityAudit(functionId) {
if (!isUserAuditEnabled()) {
return false
}
this.stopAnyOtherActivityAudit(functionId)
let response = await scope.createAudit(functionId, {
duration: 0,
})
this._startedActivities[functionId] = {
startDate: Date.now(),
auditId: response.data.id,
}
return true
},
/**
* Will update audit given a functionId (only if startActivityAudit has been called before)
* @param {Number} functionId
*/
stopActivityAudit(functionId) {
if (!isUserAuditEnabled()) {
return false
}
if (this.hasActivityStarted(functionId)) {
//Hide error until API implemented (404)
try {
let { auditId, startDate } = this._startedActivities[functionId]
scope.updateAudit(auditId, functionId, {
duration: Math.round((Date.now() - startDate) / 1000),
})
} catch (err) {
console.warn('Warning: Logging update audit', err.stack || err)
}
delete this._startedActivities[functionId]
return true
}
},
stopAnyOtherActivityAudit() {
if (!isUserAuditEnabled()) {
return false
}
Object.keys(this._startedActivities).forEach((functionId) => {
this.stopActivityAudit(functionId)
})
return true
},
},
}
export default scope
Source