{"id":38962085,"url":"https://github.com/coodoo-io/coodoo-audit","last_synced_at":"2026-01-17T16:25:39.526Z","repository":{"id":56378182,"uuid":"87422224","full_name":"coodoo-io/coodoo-audit","owner":"coodoo-io","description":"Audit framework to store data changes by observing JPA events","archived":false,"fork":false,"pushed_at":"2020-11-11T17:12:29.000Z","size":55,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2023-12-14T13:20:45.279Z","etag":null,"topics":["audit","framework","javaee","jpa","revisions"],"latest_commit_sha":null,"homepage":"http://coodoo.io/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coodoo-io.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-04-06T11:34:39.000Z","updated_at":"2020-11-11T10:07:56.000Z","dependencies_parsed_at":"2022-08-15T17:40:23.996Z","dependency_job_id":null,"html_url":"https://github.com/coodoo-io/coodoo-audit","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"purl":"pkg:github/coodoo-io/coodoo-audit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coodoo-io%2Fcoodoo-audit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coodoo-io%2Fcoodoo-audit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coodoo-io%2Fcoodoo-audit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coodoo-io%2Fcoodoo-audit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coodoo-io","download_url":"https://codeload.github.com/coodoo-io/coodoo-audit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coodoo-io%2Fcoodoo-audit/sbom","scorecard":{"id":303892,"data":{"date":"2025-08-11","repo":{"name":"github.com/coodoo-io/coodoo-audit","commit":"3f3fb3be06846cf8422978ec94d7d4785fad50a0"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.8,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 1/17 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'master'","Info: 'force pushes' disabled on branch 'master'","Info: 'branch protection settings apply to administrators' is required to merge on branch 'master'","Warn: 'stale review dismissal' is disabled on branch 'master'","Warn: branch 'master' does not require approvers","Warn: codeowners review is not required on branch 'master'","Warn: 'last push approval' is disabled on branch 'master'","Warn: no status checks found to merge onto branch 'master'","Info: PRs are required in order to make changes on branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 4 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":5,"reason":"5 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-2qrg-x229-3v8q","Warn: Project is vulnerable to: GHSA-65fg-84f6-3jq3","Warn: Project is vulnerable to: GHSA-f7vh-qwp3-x37m","Warn: Project is vulnerable to: GHSA-fp5r-v3w9-4333","Warn: Project is vulnerable to: GHSA-w9p3-5cr8-m3jj"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-17T21:29:58.229Z","repository_id":56378182,"created_at":"2025-08-17T21:29:58.229Z","updated_at":"2025-08-17T21:29:58.229Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28511861,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T13:38:16.342Z","status":"ssl_error","status_checked_at":"2026-01-17T13:37:44.060Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audit","framework","javaee","jpa","revisions"],"created_at":"2026-01-17T16:25:39.446Z","updated_at":"2026-01-17T16:25:39.517Z","avatar_url":"https://github.com/coodoo-io.png","language":"Java","readme":"# Audit #\n\n*Audit framework to store data changes by observing JPA events*\n\n## Getting started\n\n1. Add the [maven dependency](http://search.maven.org/#artifactdetails%7Cio.coodoo%7Ccoodoo-audit%7C1.0.4%7Cjar):\n\n   ```xml\n    \u003cdependency\u003e\n        \u003cgroupId\u003eio.coodoo\u003c/groupId\u003e\n        \u003cartifactId\u003ecoodoo-audit\u003c/artifactId\u003e\n        \u003cversion\u003e1.0.4\u003c/version\u003e\n    \u003c/dependency\u003e\n   ```\n\n2. Create the audit tables `audit_event` and `audit_change` in your database.\n         \n   ```sql\n   CREATE TABLE audit_event (\n     id BIGINT(20) NOT NULL AUTO_INCREMENT,\n     created_at DATETIME NOT NULL,\n     entity VARCHAR(128) NOT NULL,\n     entity_id BIGINT(20) NOT NULL,\n     action VARCHAR(8) NOT NULL,\n     user_id BIGINT(20) DEFAULT NULL,\n     user_name VARCHAR(128) DEFAULT NULL,\n     PRIMARY KEY (id)\n   );\n\n   CREATE TABLE audit_change (\n     id BIGINT(20) NOT NULL AUTO_INCREMENT,\n     event_id BIGINT(20) NOT NULL,\n     field VARCHAR(128) NOT NULL,\n     old_value VARCHAR(4096) DEFAULT NULL,\n     new_value VARCHAR(4096) DEFAULT NULL,\n     sub_event_id BIGINT(20) DEFAULT NULL,\n     sub_event_name VARCHAR(4096) DEFAULT NULL,\n     PRIMARY KEY (id),\n     KEY fk_audit_change__audit_event_idx (event_id),\n     CONSTRAINT fk_audit_change__audit_event FOREIGN KEY (event_id) \n\t  REFERENCES audit_event (id) \n\t  ON DELETE NO ACTION ON UPDATE NO ACTION\n   );\n\n   ```\n   *This is a MySQL example, see [here](https://github.com/coodoo-io/coodoo-audit/tree/master/src/main/resources/sql) for more.*\n                 \n3. Add the audit entities to your persistence.xml:\n\n   ```xml\n    \u003cclass\u003eio.coodoo.framework.audit.entity.AuditEvent\u003c/class\u003e\n    \u003cclass\u003eio.coodoo.framework.audit.entity.AuditChange\u003c/class\u003e\n   ```\n4. To provide the EntityManager you have to implement a `@AuditEntityManager` CDI producer.\n\n   ```java\n\n    @Stateless\n    public class AuditEntityManagerProducer {\n         \n        @PersistenceContext  \n        private EntityManager entityManager;\n         \n        @Produces\n        @AuditEntityManager\n        public EntityManager getEntityManager() {\n            return entityManager;\n        }\n    }\n    ```\n    *This is necessary to avoid trouble when it comes to different persistence contexts.*\n\n5. Prepare your entities to get audited.\n   Every desired entity needs to add the `AuditEntityListener` and implement the `AuditInitialValues` interface. The easiest way to do so is to extend the given class `AbstractAuditValuesEntity`.\n\n   ```java\n   @Entity\n   public class Person extends AbstractAuditValuesEntity {\n\n       @Id\n       @GeneratedValue\n       private Long id;\n         \n       private String name;\n         \n       private Date birthday;\n         \n       private Gender gender;\n         \n       @Override\n       public Long getEntiyId() {\n           return id;\n       }\n         \n       // getters, setters, hashCode, equals, ...\n   }\n   ```\n From now on, every create, update and delete will be audited and stored in in the database. You can access the audit data using the `AuditService` by giving the simple class name of the audited entity. This will get you all the data concerning the entity. To see the audit of one entry you have to give the ID as well.\n\n   ```java\n   @Stateless\npublic class PersonService {\n\n    Logger logger = LoggerFactory.getLogger(PersonService.class);\n\n    @Inject\n    AuditService auditService;\n\n    public void logAuditForPerson(Long personId) {\n\n        logger.info(\"Audit for Person with the ID {}\", personId);\n\n        for (AuditEvent auditEvent : auditService.getEvents(Person.class.getSimpleName(), personId)) {\n\n            logger.info(\"{}: {} ({})\", auditEvent.getCreatedAt(),\n                                       auditEvent.getAction(),\n                                       auditEvent.getUserName());\n\n            for (AuditChange auditChange : auditEvent.getChanges()) {\n\n                logger.info(\"* Field '{}' changed from '{}' to '{}'\", \n                        auditChange.getField(), \n                        auditChange.getOldValue(), \n                        auditChange.getNewValue());\n            }\n        }\n    }\n}\n   ```\n\n## Make it pretty\n\nFirst of all you will need a name on an audit event, so you know who is to blame. Therefore you\n\n\n\n## Import / Export events\n\n`@AuditImport` and `@AuditExport` interceptor annotations.\n  \n```xml\n\u003cinterceptors\u003e\n    \u003cclass\u003eio.coodoo.framework.audit.boundary.interceptor.AuditImportInterceptor\u003c/class\u003e\n    \u003cclass\u003eio.coodoo.framework.audit.boundary.interceptor.AuditExportInterceptor\u003c/class\u003e\n\u003c/interceptors\u003e \n```\n\n## Custom settings\n\nTo provide own settings you need to add a property file named `coodoo.audit.properties` to your project. This file gets read on JavaEE server startup if available or manually by calling `AuditSettings.loadProperties()`;\n\nThese are the properties to be defined on the file:\n```properties\n## Default user name if no user is present while the audit is taken\ncoodoo.audit.default.user = Unknown\n\n## Maximal possible characters to use as a value in a change\ncoodoo.audit.max.character = 4000\n\n## Default pattern for Date or LocalDateTime values in a change\ncoodoo.audit.timestamp.pattern = dd.MM.yyyy HH:mm:ss\n\n## Time zone\ncoodoo.audit.timezone = UTC  \n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoodoo-io%2Fcoodoo-audit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoodoo-io%2Fcoodoo-audit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoodoo-io%2Fcoodoo-audit/lists"}