{"action":"created","comment":{"url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls/comments/28773178","id":28773178,"diff_hunk":"@@ -0,0 +1,261 @@\n+/**\n+ * Copyright 2015 DuraSpace, Inc.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *     http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+package org.fcrepo.audit;\n+\n+import static org.fcrepo.audit.AuditNamespaces.AUDIT;\n+import static org.fcrepo.audit.AuditNamespaces.EVENT_TYPE;\n+import static org.fcrepo.audit.AuditNamespaces.PROV;\n+import static org.fcrepo.audit.AuditNamespaces.REPOSITORY;\n+import static org.fcrepo.kernel.RdfLexicon.REPOSITORY_NAMESPACE;\n+import static org.slf4j.LoggerFactory.getLogger;\n+\n+import java.io.IOException;\n+import java.text.DateFormat;\n+import java.text.SimpleDateFormat;\n+import java.util.Date;\n+import java.util.Set;\n+import java.util.TimeZone;\n+\n+import javax.annotation.PostConstruct;\n+import javax.annotation.PreDestroy;\n+import javax.inject.Inject;\n+import javax.jcr.Node;\n+import javax.jcr.RepositoryException;\n+\n+import org.fcrepo.kernel.identifiers.PidMinter;\n+import org.fcrepo.kernel.observer.FedoraEvent;\n+import org.fcrepo.kernel.services.ContainerService;\n+import org.fcrepo.kernel.utils.EventType;\n+import org.fcrepo.mint.UUIDPathMinter;\n+\n+import org.modeshape.jcr.api.Repository;\n+import org.modeshape.jcr.api.Session;\n+import org.slf4j.Logger;\n+\n+import com.fasterxml.jackson.databind.JsonNode;\n+import com.fasterxml.jackson.databind.ObjectMapper;\n+import com.google.common.base.Function;\n+import com.google.common.base.Joiner;\n+import com.google.common.collect.Iterables;\n+import com.google.common.eventbus.EventBus;\n+import com.google.common.eventbus.Subscribe;\n+\n+/**\n+ * @author mohideen\n+ * @date 4/15/15.\n+ */\n+public class InternalAuditor implements Auditor {\n+\n+    /**\n+     * Logger for this class.\n+     */\n+    private static final Logger LOGGER = getLogger(InternalAuditor.class);\n+\n+    private static final String AUDIT_CONTAINER = \"fcrepo.audit.container\";\n+\n+    private static String AUDIT_CONTAINER_LOCATION;\n+\n+    @Inject\n+    private EventBus eventBus;\n+\n+    @Inject\n+    private Repository repository;\n+\n+    @Inject\n+    private ContainerService containerService;\n+\n+    private Session session;\n+\n+    private static final PidMinter pidMinter =  new UUIDPathMinter();\n+\n+    /**\n+     * Register with the EventBus to receive events.\n+     */\n+    @PostConstruct\n+    public void register() throws RepositoryException {\n+        AUDIT_CONTAINER_LOCATION = System.getProperty(AUDIT_CONTAINER);\n+        if (AUDIT_CONTAINER_LOCATION != null) {\n+            LOGGER.info(\"Initializing: {}\", this.getClass().getCanonicalName());\n+            eventBus.register(this);\n+            if (!AUDIT_CONTAINER_LOCATION.startsWith(\"/\")) {\n+                AUDIT_CONTAINER_LOCATION = \"/\" + AUDIT_CONTAINER_LOCATION;\n+            }\n+            session = repository.login();\n+            containerService.findOrCreate(session, AUDIT_CONTAINER_LOCATION);\n+            session.save();\n+        } else {\n+            LOGGER.warn(\"Cannot Initialize: {}\", this.getClass().getCanonicalName());\n+            LOGGER.warn(\"System property not found: \" + AUDIT_CONTAINER);\n+        }\n+    }\n+\n+    /**\n+     * Fedora internal events are received and processed by this method.\n+     *\n+     * @param event\n+     *        The {@link FedoraEvent} to record.\n+     * @throws RepositoryException\n+     */\n+    @Subscribe\n+    public void recordEvent(final FedoraEvent event) throws RepositoryException, IOException {\n+        LOGGER.debug(\"Event detected: {} {}\", event.getUserID(), event.getPath());\n+        boolean isParentNodeLastModifiedEvent = false;\n+        final String eventType = getEventURIs(event.getTypes());\n+        final String properties = Joiner.on(',').join(event.getProperties());\n+        if (eventType.contains(PROPERTY_CHANGED)) {\n+            if (properties != null) {\n+                if (properties.equals(LAST_MODIFIED)\n+                        || properties.equals(LAST_MODIFIED_BY)\n+                        || properties.equals(LAST_MODIFIED + \",\" + LAST_MODIFIED_BY)\n+                        || properties.equals(LAST_MODIFIED_BY + \",\" + LAST_MODIFIED)) {\n+\n+                /* adding/removing a file updates the lastModified property of the parent container,\n+                so ignore updates when only lastModified is changed */\n+                    isParentNodeLastModifiedEvent = true;\n+                }\n+            }\n+        }\n+        if (!event.getPath().startsWith(AUDIT_CONTAINER_LOCATION)\n+                && !isParentNodeLastModifiedEvent) {\n+            createAuditNode(event);\n+        }\n+    }\n+\n+    /**\n+     * Close external connections\n+     */\n+    @PreDestroy\n+    public void releaseConnections() {\n+        LOGGER.debug(\"Tearing down: {}\", this.getClass().getCanonicalName());\n+        eventBus.unregister(this);\n+    }\n+\n+    // namespaces and properties\n+    private static final String INTERNAL_EVENT = AUDIT + \"InternalEvent\";\n+    private static final String PREMIS_EVENT = \"premis:Event\";\n+    private static final String PROV_EVENT = PROV + \"InstantaneousEvent\";\n+\n+    private static final String CONTENT_MOD = AUDIT + \"contentModification\";\n+    private static final String CONTENT_REM = AUDIT + \"contentRemoval\";\n+    private static final String METADATA_MOD = AUDIT + \"metadataModification\";\n+\n+    private static final String CONTENT_ADD = EVENT_TYPE + \"ing\";\n+    private static final String OBJECT_ADD = EVENT_TYPE + \"cre\";\n+    private static final String OBJECT_REM = EVENT_TYPE + \"del\";\n+\n+    private static final String PREMIS_TIME = \"premis:hasEventDateTime\";\n+    private static final String PREMIS_OBJ = \"premis:hasEventRelatedObject\";\n+    private static final String PREMIS_AGENT = \"premis:hasEventRelatedAgent\";\n+    private static final String PREMIS_TYPE = \"premis:hasEventType\";\n+\n+    private static final String RDF_TYPE = \"rdf:type\";\n+\n+    private static final String HAS_CONTENT = REPOSITORY + \"hasContent\";\n+    private static final String LAST_MODIFIED = REPOSITORY + \"lastModified\";\n+    private static final String LAST_MODIFIED_BY = REPOSITORY + \"lastModifiedBy\";\n+    private static final String NODE_ADDED = REPOSITORY + \"NODE_ADDED\";\n+    private static final String NODE_REMOVED = REPOSITORY + \"NODE_REMOVED\";\n+    private static final String PROPERTY_CHANGED = REPOSITORY + \"PROPERTY_CHANGED\";\n+\n+    /**\n+     * Creates a node for the audit event under the configured container.\n+     *\n+     * @param event\n+     * @throws RepositoryException\n+     */\n+    public void createAuditNode(final FedoraEvent event) throws RepositoryException, IOException {\n+        final String uuid = pidMinter.mintPid();\n+        final String userData = event.getUserData();\n+        final ObjectMapper mapper = new ObjectMapper();\n+        final JsonNode json = mapper.readTree(userData);\n+        final String userAgent = json.get(\"userAgent\").asText();\n+        final String baseURL = json.get(\"baseURL\").asText();\n+        final String path = event.getPath();\n+        final Long timestamp =  event.getDate();\n+        final DateFormat df = new SimpleDateFormat(\"yyyy-MM-dd'T'HH:mm:ss'Z'\");\n+        df.setTimeZone(TimeZone.getTimeZone(\"UTC\"));\n+        final String eventDate = df.format(new Date(timestamp));\n+        final String userID = event.getUserID();\n+        final String eventType = getEventURIs(event.getTypes());\n+        final String properties = Joiner.on(',').join(event.getProperties());\n+        final String auditEventType = getAuditEventType(eventType, properties);\n+        final Node auditNode = containerService.findOrCreate(session, \"/audit/\" + uuid).getNode();\n+\n+        LOGGER.debug(\"Audit node {} created for event.\", uuid);\n+\n+        auditNode.addMixin(\"fedora:Resource\");\n+        auditNode.setProperty(RDF_TYPE, INTERNAL_EVENT);\n+        auditNode.setProperty(RDF_TYPE, PREMIS_EVENT);\n+        auditNode.setProperty(RDF_TYPE, PROV_EVENT);\n+        auditNode.setProperty(PREMIS_TIME, eventDate);\n+        auditNode.setProperty(PREMIS_OBJ, baseURL + path);\n+        auditNode.setProperty(PREMIS_AGENT, userID);\n+        auditNode.setProperty(PREMIS_AGENT, userAgent);\n+        if (auditEventType != null) {\n+            auditNode.setProperty(PREMIS_TYPE, auditEventType);","path":"src/main/java/org/fcrepo/audit/InternalAuditor.java","position":208,"original_position":208,"commit_id":"22885d38b3f14bc9c60c640dbd7659485c76b654","original_commit_id":"22885d38b3f14bc9c60c640dbd7659485c76b654","user":{"login":"escowles","id":856924,"avatar_url":"https://avatars.githubusercontent.com/u/856924?v=3","gravatar_id":"","url":"https://api.github.com/users/escowles","html_url":"https://github.com/escowles","followers_url":"https://api.github.com/users/escowles/followers","following_url":"https://api.github.com/users/escowles/following{/other_user}","gists_url":"https://api.github.com/users/escowles/gists{/gist_id}","starred_url":"https://api.github.com/users/escowles/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/escowles/subscriptions","organizations_url":"https://api.github.com/users/escowles/orgs","repos_url":"https://api.github.com/users/escowles/repos","events_url":"https://api.github.com/users/escowles/events{/privacy}","received_events_url":"https://api.github.com/users/escowles/received_events","type":"User","site_admin":false},"body":"This should also use setProperty(PREMIS_TYPE, auditEventType, javax.jcr.PropertyType.URI);","created_at":"2015-04-21T12:35:42Z","updated_at":"2015-04-21T12:35:42Z","html_url":"https://github.com/fcrepo4-labs/fcrepo-audit/pull/1#discussion_r28773178","pull_request_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls/comments/28773178"},"html":{"href":"https://github.com/fcrepo4-labs/fcrepo-audit/pull/1#discussion_r28773178"},"pull_request":{"href":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls/1","id":33459704,"html_url":"https://github.com/fcrepo4-labs/fcrepo-audit/pull/1","diff_url":"https://github.com/fcrepo4-labs/fcrepo-audit/pull/1.diff","patch_url":"https://github.com/fcrepo4-labs/fcrepo-audit/pull/1.patch","issue_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/issues/1","number":1,"state":"open","locked":false,"title":"Internal audit","user":{"login":"mohideen","id":1703851,"avatar_url":"https://avatars.githubusercontent.com/u/1703851?v=3","gravatar_id":"","url":"https://api.github.com/users/mohideen","html_url":"https://github.com/mohideen","followers_url":"https://api.github.com/users/mohideen/followers","following_url":"https://api.github.com/users/mohideen/following{/other_user}","gists_url":"https://api.github.com/users/mohideen/gists{/gist_id}","starred_url":"https://api.github.com/users/mohideen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mohideen/subscriptions","organizations_url":"https://api.github.com/users/mohideen/orgs","repos_url":"https://api.github.com/users/mohideen/repos","events_url":"https://api.github.com/users/mohideen/events{/privacy}","received_events_url":"https://api.github.com/users/mohideen/received_events","type":"User","site_admin":false},"body":"https://jira.duraspace.org/browse/FCREPO-1426","created_at":"2015-04-16T15:01:17Z","updated_at":"2015-04-21T12:35:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a9436153607a13b297b59b3d35c1e4e8504b27f8","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls/1/commits","review_comments_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls/1/comments","review_comment_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls/comments{/number}","comments_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/issues/1/comments","statuses_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/statuses/22885d38b3f14bc9c60c640dbd7659485c76b654","head":{"label":"mohideen:internal-audit","ref":"internal-audit","sha":"22885d38b3f14bc9c60c640dbd7659485c76b654","user":{"login":"mohideen","id":1703851,"avatar_url":"https://avatars.githubusercontent.com/u/1703851?v=3","gravatar_id":"","url":"https://api.github.com/users/mohideen","html_url":"https://github.com/mohideen","followers_url":"https://api.github.com/users/mohideen/followers","following_url":"https://api.github.com/users/mohideen/following{/other_user}","gists_url":"https://api.github.com/users/mohideen/gists{/gist_id}","starred_url":"https://api.github.com/users/mohideen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mohideen/subscriptions","organizations_url":"https://api.github.com/users/mohideen/orgs","repos_url":"https://api.github.com/users/mohideen/repos","events_url":"https://api.github.com/users/mohideen/events{/privacy}","received_events_url":"https://api.github.com/users/mohideen/received_events","type":"User","site_admin":false},"repo":{"id":34005181,"name":"fcrepo-audit","full_name":"mohideen/fcrepo-audit","owner":{"login":"mohideen","id":1703851,"avatar_url":"https://avatars.githubusercontent.com/u/1703851?v=3","gravatar_id":"","url":"https://api.github.com/users/mohideen","html_url":"https://github.com/mohideen","followers_url":"https://api.github.com/users/mohideen/followers","following_url":"https://api.github.com/users/mohideen/following{/other_user}","gists_url":"https://api.github.com/users/mohideen/gists{/gist_id}","starred_url":"https://api.github.com/users/mohideen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mohideen/subscriptions","organizations_url":"https://api.github.com/users/mohideen/orgs","repos_url":"https://api.github.com/users/mohideen/repos","events_url":"https://api.github.com/users/mohideen/events{/privacy}","received_events_url":"https://api.github.com/users/mohideen/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mohideen/fcrepo-audit","description":"","fork":true,"url":"https://api.github.com/repos/mohideen/fcrepo-audit","forks_url":"https://api.github.com/repos/mohideen/fcrepo-audit/forks","keys_url":"https://api.github.com/repos/mohideen/fcrepo-audit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mohideen/fcrepo-audit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mohideen/fcrepo-audit/teams","hooks_url":"https://api.github.com/repos/mohideen/fcrepo-audit/hooks","issue_events_url":"https://api.github.com/repos/mohideen/fcrepo-audit/issues/events{/number}","events_url":"https://api.github.com/repos/mohideen/fcrepo-audit/events","assignees_url":"https://api.github.com/repos/mohideen/fcrepo-audit/assignees{/user}","branches_url":"https://api.github.com/repos/mohideen/fcrepo-audit/branches{/branch}","tags_url":"https://api.github.com/repos/mohideen/fcrepo-audit/tags","blobs_url":"https://api.github.com/repos/mohideen/fcrepo-audit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mohideen/fcrepo-audit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mohideen/fcrepo-audit/git/refs{/sha}","trees_url":"https://api.github.com/repos/mohideen/fcrepo-audit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mohideen/fcrepo-audit/statuses/{sha}","languages_url":"https://api.github.com/repos/mohideen/fcrepo-audit/languages","stargazers_url":"https://api.github.com/repos/mohideen/fcrepo-audit/stargazers","contributors_url":"https://api.github.com/repos/mohideen/fcrepo-audit/contributors","subscribers_url":"https://api.github.com/repos/mohideen/fcrepo-audit/subscribers","subscription_url":"https://api.github.com/repos/mohideen/fcrepo-audit/subscription","commits_url":"https://api.github.com/repos/mohideen/fcrepo-audit/commits{/sha}","git_commits_url":"https://api.github.com/repos/mohideen/fcrepo-audit/git/commits{/sha}","comments_url":"https://api.github.com/repos/mohideen/fcrepo-audit/comments{/number}","issue_comment_url":"https://api.github.com/repos/mohideen/fcrepo-audit/issues/comments{/number}","contents_url":"https://api.github.com/repos/mohideen/fcrepo-audit/contents/{+path}","compare_url":"https://api.github.com/repos/mohideen/fcrepo-audit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mohideen/fcrepo-audit/merges","archive_url":"https://api.github.com/repos/mohideen/fcrepo-audit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mohideen/fcrepo-audit/downloads","issues_url":"https://api.github.com/repos/mohideen/fcrepo-audit/issues{/number}","pulls_url":"https://api.github.com/repos/mohideen/fcrepo-audit/pulls{/number}","milestones_url":"https://api.github.com/repos/mohideen/fcrepo-audit/milestones{/number}","notifications_url":"https://api.github.com/repos/mohideen/fcrepo-audit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mohideen/fcrepo-audit/labels{/name}","releases_url":"https://api.github.com/repos/mohideen/fcrepo-audit/releases{/id}","created_at":"2015-04-15T16:19:52Z","updated_at":"2015-04-15T16:19:52Z","pushed_at":"2015-04-21T01:21:56Z","git_url":"git://github.com/mohideen/fcrepo-audit.git","ssh_url":"git@github.com:mohideen/fcrepo-audit.git","clone_url":"https://github.com/mohideen/fcrepo-audit.git","svn_url":"https://github.com/mohideen/fcrepo-audit","homepage":null,"size":113,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"fcrepo4-labs:master","ref":"master","sha":"6284aeb35e89dba6b4dcf81272d728966bd93401","user":{"login":"fcrepo4-labs","id":7586101,"avatar_url":"https://avatars.githubusercontent.com/u/7586101?v=3","gravatar_id":"","url":"https://api.github.com/users/fcrepo4-labs","html_url":"https://github.com/fcrepo4-labs","followers_url":"https://api.github.com/users/fcrepo4-labs/followers","following_url":"https://api.github.com/users/fcrepo4-labs/following{/other_user}","gists_url":"https://api.github.com/users/fcrepo4-labs/gists{/gist_id}","starred_url":"https://api.github.com/users/fcrepo4-labs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fcrepo4-labs/subscriptions","organizations_url":"https://api.github.com/users/fcrepo4-labs/orgs","repos_url":"https://api.github.com/users/fcrepo4-labs/repos","events_url":"https://api.github.com/users/fcrepo4-labs/events{/privacy}","received_events_url":"https://api.github.com/users/fcrepo4-labs/received_events","type":"Organization","site_admin":false},"repo":{"id":25169261,"name":"fcrepo-audit","full_name":"fcrepo4-labs/fcrepo-audit","owner":{"login":"fcrepo4-labs","id":7586101,"avatar_url":"https://avatars.githubusercontent.com/u/7586101?v=3","gravatar_id":"","url":"https://api.github.com/users/fcrepo4-labs","html_url":"https://github.com/fcrepo4-labs","followers_url":"https://api.github.com/users/fcrepo4-labs/followers","following_url":"https://api.github.com/users/fcrepo4-labs/following{/other_user}","gists_url":"https://api.github.com/users/fcrepo4-labs/gists{/gist_id}","starred_url":"https://api.github.com/users/fcrepo4-labs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fcrepo4-labs/subscriptions","organizations_url":"https://api.github.com/users/fcrepo4-labs/orgs","repos_url":"https://api.github.com/users/fcrepo4-labs/repos","events_url":"https://api.github.com/users/fcrepo4-labs/events{/privacy}","received_events_url":"https://api.github.com/users/fcrepo4-labs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/fcrepo4-labs/fcrepo-audit","description":"","fork":false,"url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit","forks_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/forks","keys_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/teams","hooks_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/hooks","issue_events_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/issues/events{/number}","events_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/events","assignees_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/assignees{/user}","branches_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/branches{/branch}","tags_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/tags","blobs_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/git/refs{/sha}","trees_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/statuses/{sha}","languages_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/languages","stargazers_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/stargazers","contributors_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/contributors","subscribers_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/subscribers","subscription_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/subscription","commits_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/commits{/sha}","git_commits_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/git/commits{/sha}","comments_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/comments{/number}","issue_comment_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/issues/comments{/number}","contents_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/contents/{+path}","compare_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/merges","archive_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/downloads","issues_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/issues{/number}","pulls_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls{/number}","milestones_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/milestones{/number}","notifications_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/labels{/name}","releases_url":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/releases{/id}","created_at":"2014-10-13T17:21:32Z","updated_at":"2014-10-13T17:23:13Z","pushed_at":"2015-04-21T01:21:57Z","git_url":"git://github.com/fcrepo4-labs/fcrepo-audit.git","ssh_url":"git@github.com:fcrepo4-labs/fcrepo-audit.git","clone_url":"https://github.com/fcrepo4-labs/fcrepo-audit.git","svn_url":"https://github.com/fcrepo4-labs/fcrepo-audit","homepage":null,"size":148,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls/1"},"html":{"href":"https://github.com/fcrepo4-labs/fcrepo-audit/pull/1"},"issue":{"href":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/issues/1"},"comments":{"href":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/fcrepo4-labs/fcrepo-audit/statuses/22885d38b3f14bc9c60c640dbd7659485c76b654"}}}}