Skip to content

Commit

Permalink
AuditEvent Resource (#53)
Browse files Browse the repository at this point in the history
* Add auditEvent

* add repository for auditEvent

* spotless
  • Loading branch information
evance-mose authored Apr 9, 2024
1 parent 6337f55 commit 439beff
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright 2021 Ona Systems, Inc
*
* 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.
*/

package org.smartregister.fhircore.engine.auditEvent

import java.util.Date
import java.util.UUID
import javax.inject.Inject
import javax.inject.Singleton
import org.hl7.fhir.r4.model.AuditEvent
import org.hl7.fhir.r4.model.Coding
import org.hl7.fhir.r4.model.Practitioner
import org.smartregister.fhircore.engine.R
import org.smartregister.fhircore.engine.data.local.DefaultRepository
import org.smartregister.fhircore.engine.util.SharedPreferenceKey
import org.smartregister.fhircore.engine.util.SharedPreferencesHelper
import org.smartregister.fhircore.engine.util.extension.asReference

@Singleton
class AuditEventRepository
@Inject
constructor(
val defaultRepository: DefaultRepository,
val sharedPreferences: SharedPreferencesHelper,
) : IAuditEventRepository {
override suspend fun createAuditEvent() {
// Get Practitioner Resource
val practitionerID =
sharedPreferences.read(key = SharedPreferenceKey.PRACTITIONER_ID.name, defaultValue = null)
?: return

val practitioner = defaultRepository.loadResource<Practitioner>(practitionerID!!)

val context = sharedPreferences.context

// Create AuditEvent Resource
val auditEvent =
AuditEvent().apply {
id = UUID.randomUUID().toString()
type =
Coding().apply {
system = context.getString(R.string.audit_event_system)
code = "110114"
display = "User Authentication"
}
subtype =
listOf(
Coding().apply {
system = context.getString(R.string.audit_event_system)
code = "110122"
display = "Login"
},
)
outcome = AuditEvent.AuditEventOutcome._0
action = AuditEvent.AuditEventAction.C
recorded = Date()
agent =
listOf(
AuditEvent.AuditEventAgentComponent().apply {
who = practitioner?.asReference()
requestor = true
},
)
source =
AuditEvent.AuditEventSourceComponent().apply { observer = practitioner?.asReference() }
}

// Save AuditEvent Resource
defaultRepository.addOrUpdate(true, auditEvent)
}
}

interface IAuditEventRepository {
suspend fun createAuditEvent()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2021 Ona Systems, Inc
*
* 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.
*/

package org.smartregister.fhircore.engine.auditEvent

import android.content.Context
import androidx.hilt.work.HiltWorker
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import timber.log.Timber

@HiltWorker
class AuditEventWorker
@AssistedInject
constructor(
@Assisted val appContext: Context,
@Assisted workerParameters: WorkerParameters,
private val auditEventRepository: AuditEventRepository,
) : CoroutineWorker(appContext, workerParameters) {

override suspend fun doWork(): Result {
Timber.e("AuditEventWorker is running")
auditEventRepository.createAuditEvent()
return Result.success()
}

companion object {
const val NAME = "AuditEventWorker"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ package org.smartregister.fhircore.engine.configuration.app

import android.content.Context
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import java.util.concurrent.TimeUnit
import org.hl7.fhir.r4.model.Coding
import org.smartregister.fhircore.engine.appointment.MissedFHIRAppointmentsWorker
import org.smartregister.fhircore.engine.appointment.ProposedWelcomeServiceAppointmentsWorker
import org.smartregister.fhircore.engine.auditEvent.AuditEventWorker
import org.smartregister.fhircore.engine.sync.ResourceTag
import org.smartregister.fhircore.engine.task.FhirTaskPlanWorker
import org.smartregister.fhircore.engine.task.WelcomeServiceBackToCarePlanWorker
Expand Down Expand Up @@ -119,4 +121,10 @@ interface ConfigService {
workRequest,
)
}

fun scheduleAuditEvent(context: Context) {
val workRequest = OneTimeWorkRequestBuilder<AuditEventWorker>().build()

WorkManager.getInstance(context).enqueue(workRequest)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
import org.hl7.fhir.r4.context.SimpleWorkerContext
import org.hl7.fhir.r4.model.Parameters
import org.smartregister.fhircore.engine.auditEvent.AuditEventRepository
import org.smartregister.fhircore.engine.configuration.ConfigurationRegistry
import org.smartregister.fhircore.engine.configuration.app.ConfigService
import org.smartregister.fhircore.engine.data.local.DefaultRepository
Expand Down Expand Up @@ -91,4 +92,11 @@ class CoreModule {
defaultRepository: DefaultRepository,
configurationRegistry: ConfigurationRegistry,
): PatientDao = HivRegisterDao(fhirEngine, defaultRepository, configurationRegistry)

@Singleton
@Provides
fun provideAudiEventRepository(
defaultRepository: DefaultRepository,
sharedPreferencesHelper: SharedPreferencesHelper,
): AuditEventRepository = AuditEventRepository(defaultRepository, sharedPreferencesHelper)
}
1 change: 1 addition & 0 deletions android/engine/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,5 @@
<string name="error_loading_config_general">Error connecting to the server. Please contact the system administrator</string>
<string name="re_fetch_practitioner">Re-fetch Practitioner</string>
<string name="dev_menu">Dev Menu</string>
<string name="audit_event_system">http://dicom.nema.org/resources/ontology/DCM</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import org.hl7.fhir.r4.model.Encounter
import org.hl7.fhir.r4.model.ResourceType
import org.smartregister.fhircore.engine.R
import org.smartregister.fhircore.engine.configuration.app.ConfigService
import org.smartregister.fhircore.engine.data.remote.shared.TokenAuthenticator
import org.smartregister.fhircore.engine.sync.OnSyncListener
import org.smartregister.fhircore.engine.sync.SyncBroadcaster
import org.smartregister.fhircore.engine.task.FhirCarePlanGenerator
Expand Down Expand Up @@ -61,9 +62,11 @@ open class AppMainActivity : BaseMultiLanguageActivity(), OnSyncListener {

@Inject lateinit var configService: ConfigService

@Inject lateinit var tokenAuthenticator: TokenAuthenticator

val appMainViewModel by viewModels<AppMainViewModel>()

val authActivityLauncherForResult =
private val authActivityLauncherForResult =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { res ->
if (res.resultCode == Activity.RESULT_OK) {
appMainViewModel.onEvent(AppMainEvent.ResumeSync)
Expand All @@ -75,6 +78,7 @@ open class AppMainActivity : BaseMultiLanguageActivity(), OnSyncListener {
setupTimeOutListener()
setContent { AppTheme { MainScreen(appMainViewModel = appMainViewModel) } }
syncBroadcaster.registerSyncListener(this, lifecycleScope)
scheduleAuthWorkers()
}

override fun onResume() {
Expand Down Expand Up @@ -171,6 +175,13 @@ open class AppMainActivity : BaseMultiLanguageActivity(), OnSyncListener {
}
}

private fun scheduleAuthWorkers() {
val isAuthenticated = tokenAuthenticator.sessionActive()
if (isAuthenticated) {
with(configService) { scheduleAuditEvent(applicationContext) }
}
}

private fun setupTimeOutListener() {
if (application is QuestApplication) {
(application as QuestApplication).onInActivityListener =
Expand Down

0 comments on commit 439beff

Please sign in to comment.