{"action":"created","comment":{"url":"https://api.github.com/repos/codice/ddf/pulls/comments/155572634","pull_request_review_id":81914110,"id":155572634,"diff_hunk":"@@ -161,9 +178,45 @@ private EntityDescriptor getEntityDescriptor() {\n       boolean updated = entryDescriptions.compareAndSet(null, edMap);\n       if (!updated) {\n         LOGGER.debug(\"Safe but concurrent update to serviceProviders map; using processed value\");\n+      } else {\n+        setCacheInformation(extractRootEntityFromMap(edMap));\n+      }\n+    }\n+\n+    return extractRootEntityFromMap(edMap);\n+  }\n+\n+  private void setCacheInformation(EntityDescriptor entityDescriptor) {\n+    if (entityDescriptor != null) {\n+      created = Instant.now();\n+      if (entityDescriptor.getCacheDuration() != null) {\n+        cacheDuration = Duration.ofMillis(entityDescriptor.getCacheDuration());\n+      }\n+      if (entityDescriptor.getValidUntil() != null) {\n+        validUntil = entityDescriptor.getValidUntil().toDate().toInstant();\n       }\n     }\n+  }\n+\n+  /**\n+   * Return true if this the metadata is expired. It if ambiguous is both the cache duration and\n+   * valid-until are specified. Assume that only one will be specified. Return true only if neither\n+   * are currently valid. If neither is present, assume the metadata is good.\n+   *\n+   * @return true if metadata should be reacquired from the IDP\n+   */\n+  public boolean isMetadataExpired() {\n+    boolean missingCacheDuration = cacheDuration == null;\n+    boolean missingValidUntil = validUntil == null;\n+    boolean missingAllTimeConstraints = missingCacheDuration && missingValidUntil;\n+    Instant now = Instant.now();\n+    boolean cacheDurationGood = !missingCacheDuration && now.isBefore(created.plus(cacheDuration));\n+    boolean stillValidUntil = !missingValidUntil && now.isBefore(validUntil);\n+    boolean isMetadataGood = missingAllTimeConstraints || cacheDurationGood || stillValidUntil;\n+    return !isMetadataGood;","path":"platform/security/idp/security-idp-client/src/main/java/org/codice/ddf/security/idp/client/IdpMetadata.java","position":86,"original_position":86,"commit_id":"e3c4a86e8fbd044bcd4654351ef99263f4d96f8f","original_commit_id":"e3c4a86e8fbd044bcd4654351ef99263f4d96f8f","user":{"login":"rzwiefel","id":9013416,"avatar_url":"https://avatars0.githubusercontent.com/u/9013416?v=4","gravatar_id":"","url":"https://api.github.com/users/rzwiefel","html_url":"https://github.com/rzwiefel","followers_url":"https://api.github.com/users/rzwiefel/followers","following_url":"https://api.github.com/users/rzwiefel/following{/other_user}","gists_url":"https://api.github.com/users/rzwiefel/gists{/gist_id}","starred_url":"https://api.github.com/users/rzwiefel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rzwiefel/subscriptions","organizations_url":"https://api.github.com/users/rzwiefel/orgs","repos_url":"https://api.github.com/users/rzwiefel/repos","events_url":"https://api.github.com/users/rzwiefel/events{/privacy}","received_events_url":"https://api.github.com/users/rzwiefel/received_events","type":"User","site_admin":false},"body":"I'm not sure the logic in here is necessarily correct. According to the spec:\r\n>Note that cache expiration does not imply a lack of validity in the absence of a `validUntil` attribute or \r\nother information; failure to update a cached instance (e.g., due to network failure) need not render \r\nmetadata invalid, although implementations may offer such controls to deployers.\r\n[Section 4.3.1](https://www.oasis-open.org/committees/download.php/56786/sstc-saml-metadata-errata-2.0-wd-05-diff.pdf)\r\n\r\n>Metadata MUST be considered invalid upon reaching the time specified in a `validUntil` attribute of the \r\nsubject element(s). The effective expiration may be adjusted downward by parent element(s) with earlier \r\nexpirations. Invalid metadata MUST NOT be used. This contrasts with \"stale\" metadata that may be beyond its optimum cache duration but is not explicitly invalid. Such metadata remains valid and MAY be \r\nused at the discretion of the implementation.\r\n[Section 4.3.2](https://www.oasis-open.org/committees/download.php/56786/sstc-saml-metadata-errata-2.0-wd-05-diff.pdf)\r\n\r\nI think this is stating if it valid until is there and it is invalid, we MUST expire the metadata regardless of if caching is good. I would say we should also add defensive logic if both are set to ensure that the `validUntil` is respected even if both happen to be set. \r\n\r\nAnd according to the first sentence in section 4.3.1 \r\n>Document caching MUST be based on the duration indicated by the `cacheDuration` attribute\r\n\r\nThis implies that we **cannot** cache if the cacheDuration is not set and must  fetch new metadata every time. \r\n\r\nWe could try to get @stustison or maybe @coyotesqrl to double check as well if we wanted.","created_at":"2017-12-07T16:32:47Z","updated_at":"2017-12-07T16:32:47Z","html_url":"https://github.com/codice/ddf/pull/2711#discussion_r155572634","pull_request_url":"https://api.github.com/repos/codice/ddf/pulls/2711","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/codice/ddf/pulls/comments/155572634"},"html":{"href":"https://github.com/codice/ddf/pull/2711#discussion_r155572634"},"pull_request":{"href":"https://api.github.com/repos/codice/ddf/pulls/2711"}}},"pull_request":{"url":"https://api.github.com/repos/codice/ddf/pulls/2711","id":155117638,"html_url":"https://github.com/codice/ddf/pull/2711","diff_url":"https://github.com/codice/ddf/pull/2711.diff","patch_url":"https://github.com/codice/ddf/pull/2711.patch","issue_url":"https://api.github.com/repos/codice/ddf/issues/2711","number":2711,"state":"open","locked":false,"title":"[2.11.x] DDF-3473 The MetadataConfigurationParser does not respect the validUntil or cacheDuration attributes that might be present on SAML metadata","user":{"login":"ahoffer","id":133284,"avatar_url":"https://avatars3.githubusercontent.com/u/133284?v=4","gravatar_id":"","url":"https://api.github.com/users/ahoffer","html_url":"https://github.com/ahoffer","followers_url":"https://api.github.com/users/ahoffer/followers","following_url":"https://api.github.com/users/ahoffer/following{/other_user}","gists_url":"https://api.github.com/users/ahoffer/gists{/gist_id}","starred_url":"https://api.github.com/users/ahoffer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ahoffer/subscriptions","organizations_url":"https://api.github.com/users/ahoffer/orgs","repos_url":"https://api.github.com/users/ahoffer/repos","events_url":"https://api.github.com/users/ahoffer/events{/privacy}","received_events_url":"https://api.github.com/users/ahoffer/received_events","type":"User","site_admin":false},"body":"#### What does this PR do?\r\n1. Adds a cache duration to the IDP metadata XML file (duration = 1 day)\r\n2. Adds a check, `MetadataConfigurationParser.validateMetadata` to ensure metadata has either a cache duration or a (future) valid-until date. \r\n3. More unit tests\r\n\r\n**This is the first of what is expected to be 2 PRs. The next PR will update the consumers of the metadata to retrieve cache metadata using the duration/validUntil properties.**\r\n#### Who is reviewing it? \r\n@vinamartin @mcalcote @rzwiefel @garrettfreibott \r\n#### Select relevant component teams: \r\nSecurity\r\nhttps://github.com/orgs/codice/teams/security\r\n#### Choose 2 committers to review/merge the PR. \r\n\r\n@clockard\r\n@rzwiefel\r\n@stustison\r\n\r\n#### How should this be tested? (List steps with links to updated documentation)\r\nFull build/tests. \r\nBuild and start DDF. Make sure login/logout works.\r\n\r\n#### Any background context you want to provide?\r\nAddress tech debt and improves SAML compliance.\r\n\r\n#### What are the relevant tickets?\r\nhttps://codice.atlassian.net/browse/DDF-3473\r\n\r\n#### Screenshots (if appropriate)\r\n\r\n#### Checklist:\r\n- [NA] Documentation Updated\r\n- [X] Update / Add Unit Tests\r\n- [NA] Update / Add Integration Tests\r\n\r\n#### Notes on Review Process\r\nFor the general case, merging is gated on the following:\r\n\r\n* Review by at least two contributors\r\n* Review by at least two committers\r\n* Successful CI\r\n* Successful static analysis (SonarQube/Coverity/etc.)\r\n* Heroing of change (details vary by ticket)\r\n\r\nCertain exceptions may occur. For example, if there is a problem with the CI environment then a manually performed full build and static analysis check may be substituted _at the discretion of the repository maintainers_. Additionally, repository metadata such as this `PULL_REQUEST_TEMPLATE`, the repository `README`, and other non-functional items may be merged without requiring CI and static analysis.\r\n\r\nFinally, an abbreviated review process may be in place for forward-port tickets immediately following branching and prior to branch divergence. In that case, approvals, CI, static analysis, and heroing that occur against the PR against the _release branch_ can be considered sufficient for reviewing the PR against the _master branch_.\r\n\r\nOnce the branches diverge, the process will return to normal.\r\n\r\nInsofar as divergence is not a function of time but of change to the parent branch, the repository maintainers will determine when abbreviated review ends.\r\n\r\nWhen abbreviated review is in effect, a note to that effect will be at the top of this template. Following is an example note:\r\n```\r\n##### ABBREVIATED REVIEW BETWEEN 2.12.X AND MASTER IS IN EFFECT\r\n____\r\n\r\n```\r\n\r\n#### Review Comment Legend:\r\n- ✏️ (Pencil) This comment is a nitpick or style suggestion, no action required for approval. This comment should provide a suggestion either as an in line code snippet or a gist. \r\n- ❓ (Question Mark) This comment is to gain a clearer understanding of design or code choices, clarification is required but action may not be necessary for approval.\r\n- ❗ (Exclamation Mark) This comment is critical and requires clarification or action before approval.\r\n","created_at":"2017-11-28T16:21:31Z","updated_at":"2017-12-07T16:32:47Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d5238c31bb637412878ebc70741eb78b881d3608","assignee":{"login":"stustison","id":4391679,"avatar_url":"https://avatars0.githubusercontent.com/u/4391679?v=4","gravatar_id":"","url":"https://api.github.com/users/stustison","html_url":"https://github.com/stustison","followers_url":"https://api.github.com/users/stustison/followers","following_url":"https://api.github.com/users/stustison/following{/other_user}","gists_url":"https://api.github.com/users/stustison/gists{/gist_id}","starred_url":"https://api.github.com/users/stustison/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stustison/subscriptions","organizations_url":"https://api.github.com/users/stustison/orgs","repos_url":"https://api.github.com/users/stustison/repos","events_url":"https://api.github.com/users/stustison/events{/privacy}","received_events_url":"https://api.github.com/users/stustison/received_events","type":"User","site_admin":false},"assignees":[{"login":"stustison","id":4391679,"avatar_url":"https://avatars0.githubusercontent.com/u/4391679?v=4","gravatar_id":"","url":"https://api.github.com/users/stustison","html_url":"https://github.com/stustison","followers_url":"https://api.github.com/users/stustison/followers","following_url":"https://api.github.com/users/stustison/following{/other_user}","gists_url":"https://api.github.com/users/stustison/gists{/gist_id}","starred_url":"https://api.github.com/users/stustison/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stustison/subscriptions","organizations_url":"https://api.github.com/users/stustison/orgs","repos_url":"https://api.github.com/users/stustison/repos","events_url":"https://api.github.com/users/stustison/events{/privacy}","received_events_url":"https://api.github.com/users/stustison/received_events","type":"User","site_admin":false},{"login":"clockard","id":5248090,"avatar_url":"https://avatars1.githubusercontent.com/u/5248090?v=4","gravatar_id":"","url":"https://api.github.com/users/clockard","html_url":"https://github.com/clockard","followers_url":"https://api.github.com/users/clockard/followers","following_url":"https://api.github.com/users/clockard/following{/other_user}","gists_url":"https://api.github.com/users/clockard/gists{/gist_id}","starred_url":"https://api.github.com/users/clockard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/clockard/subscriptions","organizations_url":"https://api.github.com/users/clockard/orgs","repos_url":"https://api.github.com/users/clockard/repos","events_url":"https://api.github.com/users/clockard/events{/privacy}","received_events_url":"https://api.github.com/users/clockard/received_events","type":"User","site_admin":false},{"login":"rzwiefel","id":9013416,"avatar_url":"https://avatars0.githubusercontent.com/u/9013416?v=4","gravatar_id":"","url":"https://api.github.com/users/rzwiefel","html_url":"https://github.com/rzwiefel","followers_url":"https://api.github.com/users/rzwiefel/followers","following_url":"https://api.github.com/users/rzwiefel/following{/other_user}","gists_url":"https://api.github.com/users/rzwiefel/gists{/gist_id}","starred_url":"https://api.github.com/users/rzwiefel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rzwiefel/subscriptions","organizations_url":"https://api.github.com/users/rzwiefel/orgs","repos_url":"https://api.github.com/users/rzwiefel/repos","events_url":"https://api.github.com/users/rzwiefel/events{/privacy}","received_events_url":"https://api.github.com/users/rzwiefel/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"stustison","id":4391679,"avatar_url":"https://avatars0.githubusercontent.com/u/4391679?v=4","gravatar_id":"","url":"https://api.github.com/users/stustison","html_url":"https://github.com/stustison","followers_url":"https://api.github.com/users/stustison/followers","following_url":"https://api.github.com/users/stustison/following{/other_user}","gists_url":"https://api.github.com/users/stustison/gists{/gist_id}","starred_url":"https://api.github.com/users/stustison/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stustison/subscriptions","organizations_url":"https://api.github.com/users/stustison/orgs","repos_url":"https://api.github.com/users/stustison/repos","events_url":"https://api.github.com/users/stustison/events{/privacy}","received_events_url":"https://api.github.com/users/stustison/received_events","type":"User","site_admin":false}],"milestone":{"url":"https://api.github.com/repos/codice/ddf/milestones/15","html_url":"https://github.com/codice/ddf/milestone/15","labels_url":"https://api.github.com/repos/codice/ddf/milestones/15/labels","id":2881770,"number":15,"title":"2.11.3","description":"","creator":{"login":"clockard","id":5248090,"avatar_url":"https://avatars1.githubusercontent.com/u/5248090?v=4","gravatar_id":"","url":"https://api.github.com/users/clockard","html_url":"https://github.com/clockard","followers_url":"https://api.github.com/users/clockard/followers","following_url":"https://api.github.com/users/clockard/following{/other_user}","gists_url":"https://api.github.com/users/clockard/gists{/gist_id}","starred_url":"https://api.github.com/users/clockard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/clockard/subscriptions","organizations_url":"https://api.github.com/users/clockard/orgs","repos_url":"https://api.github.com/users/clockard/repos","events_url":"https://api.github.com/users/clockard/events{/privacy}","received_events_url":"https://api.github.com/users/clockard/received_events","type":"User","site_admin":false},"open_issues":4,"closed_issues":19,"state":"open","created_at":"2017-11-01T20:53:47Z","updated_at":"2017-12-07T16:07:48Z","due_on":"2017-12-15T08:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/codice/ddf/pulls/2711/commits","review_comments_url":"https://api.github.com/repos/codice/ddf/pulls/2711/comments","review_comment_url":"https://api.github.com/repos/codice/ddf/pulls/comments{/number}","comments_url":"https://api.github.com/repos/codice/ddf/issues/2711/comments","statuses_url":"https://api.github.com/repos/codice/ddf/statuses/e3c4a86e8fbd044bcd4654351ef99263f4d96f8f","head":{"label":"ahoffer:DDF-3473","ref":"DDF-3473","sha":"e3c4a86e8fbd044bcd4654351ef99263f4d96f8f","user":{"login":"ahoffer","id":133284,"avatar_url":"https://avatars3.githubusercontent.com/u/133284?v=4","gravatar_id":"","url":"https://api.github.com/users/ahoffer","html_url":"https://github.com/ahoffer","followers_url":"https://api.github.com/users/ahoffer/followers","following_url":"https://api.github.com/users/ahoffer/following{/other_user}","gists_url":"https://api.github.com/users/ahoffer/gists{/gist_id}","starred_url":"https://api.github.com/users/ahoffer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ahoffer/subscriptions","organizations_url":"https://api.github.com/users/ahoffer/orgs","repos_url":"https://api.github.com/users/ahoffer/repos","events_url":"https://api.github.com/users/ahoffer/events{/privacy}","received_events_url":"https://api.github.com/users/ahoffer/received_events","type":"User","site_admin":false},"repo":{"id":42614877,"name":"ddf","full_name":"ahoffer/ddf","owner":{"login":"ahoffer","id":133284,"avatar_url":"https://avatars3.githubusercontent.com/u/133284?v=4","gravatar_id":"","url":"https://api.github.com/users/ahoffer","html_url":"https://github.com/ahoffer","followers_url":"https://api.github.com/users/ahoffer/followers","following_url":"https://api.github.com/users/ahoffer/following{/other_user}","gists_url":"https://api.github.com/users/ahoffer/gists{/gist_id}","starred_url":"https://api.github.com/users/ahoffer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ahoffer/subscriptions","organizations_url":"https://api.github.com/users/ahoffer/orgs","repos_url":"https://api.github.com/users/ahoffer/repos","events_url":"https://api.github.com/users/ahoffer/events{/privacy}","received_events_url":"https://api.github.com/users/ahoffer/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ahoffer/ddf","description":"The Distributed Data Framework - Distribution, SDK, and Test","fork":true,"url":"https://api.github.com/repos/ahoffer/ddf","forks_url":"https://api.github.com/repos/ahoffer/ddf/forks","keys_url":"https://api.github.com/repos/ahoffer/ddf/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ahoffer/ddf/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ahoffer/ddf/teams","hooks_url":"https://api.github.com/repos/ahoffer/ddf/hooks","issue_events_url":"https://api.github.com/repos/ahoffer/ddf/issues/events{/number}","events_url":"https://api.github.com/repos/ahoffer/ddf/events","assignees_url":"https://api.github.com/repos/ahoffer/ddf/assignees{/user}","branches_url":"https://api.github.com/repos/ahoffer/ddf/branches{/branch}","tags_url":"https://api.github.com/repos/ahoffer/ddf/tags","blobs_url":"https://api.github.com/repos/ahoffer/ddf/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ahoffer/ddf/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ahoffer/ddf/git/refs{/sha}","trees_url":"https://api.github.com/repos/ahoffer/ddf/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ahoffer/ddf/statuses/{sha}","languages_url":"https://api.github.com/repos/ahoffer/ddf/languages","stargazers_url":"https://api.github.com/repos/ahoffer/ddf/stargazers","contributors_url":"https://api.github.com/repos/ahoffer/ddf/contributors","subscribers_url":"https://api.github.com/repos/ahoffer/ddf/subscribers","subscription_url":"https://api.github.com/repos/ahoffer/ddf/subscription","commits_url":"https://api.github.com/repos/ahoffer/ddf/commits{/sha}","git_commits_url":"https://api.github.com/repos/ahoffer/ddf/git/commits{/sha}","comments_url":"https://api.github.com/repos/ahoffer/ddf/comments{/number}","issue_comment_url":"https://api.github.com/repos/ahoffer/ddf/issues/comments{/number}","contents_url":"https://api.github.com/repos/ahoffer/ddf/contents/{+path}","compare_url":"https://api.github.com/repos/ahoffer/ddf/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ahoffer/ddf/merges","archive_url":"https://api.github.com/repos/ahoffer/ddf/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ahoffer/ddf/downloads","issues_url":"https://api.github.com/repos/ahoffer/ddf/issues{/number}","pulls_url":"https://api.github.com/repos/ahoffer/ddf/pulls{/number}","milestones_url":"https://api.github.com/repos/ahoffer/ddf/milestones{/number}","notifications_url":"https://api.github.com/repos/ahoffer/ddf/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ahoffer/ddf/labels{/name}","releases_url":"https://api.github.com/repos/ahoffer/ddf/releases{/id}","deployments_url":"https://api.github.com/repos/ahoffer/ddf/deployments","created_at":"2015-09-16T21:39:29Z","updated_at":"2016-01-12T21:13:31Z","pushed_at":"2017-12-06T21:45:40Z","git_url":"git://github.com/ahoffer/ddf.git","ssh_url":"git@github.com:ahoffer/ddf.git","clone_url":"https://github.com/ahoffer/ddf.git","svn_url":"https://github.com/ahoffer/ddf","homepage":"","size":190277,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"codice:2.11.x","ref":"2.11.x","sha":"5dcc42190a72fa9e4550d5820be39a15fb273dd4","user":{"login":"codice","id":2386734,"avatar_url":"https://avatars2.githubusercontent.com/u/2386734?v=4","gravatar_id":"","url":"https://api.github.com/users/codice","html_url":"https://github.com/codice","followers_url":"https://api.github.com/users/codice/followers","following_url":"https://api.github.com/users/codice/following{/other_user}","gists_url":"https://api.github.com/users/codice/gists{/gist_id}","starred_url":"https://api.github.com/users/codice/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codice/subscriptions","organizations_url":"https://api.github.com/users/codice/orgs","repos_url":"https://api.github.com/users/codice/repos","events_url":"https://api.github.com/users/codice/events{/privacy}","received_events_url":"https://api.github.com/users/codice/received_events","type":"Organization","site_admin":false},"repo":{"id":15173563,"name":"ddf","full_name":"codice/ddf","owner":{"login":"codice","id":2386734,"avatar_url":"https://avatars2.githubusercontent.com/u/2386734?v=4","gravatar_id":"","url":"https://api.github.com/users/codice","html_url":"https://github.com/codice","followers_url":"https://api.github.com/users/codice/followers","following_url":"https://api.github.com/users/codice/following{/other_user}","gists_url":"https://api.github.com/users/codice/gists{/gist_id}","starred_url":"https://api.github.com/users/codice/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codice/subscriptions","organizations_url":"https://api.github.com/users/codice/orgs","repos_url":"https://api.github.com/users/codice/repos","events_url":"https://api.github.com/users/codice/events{/privacy}","received_events_url":"https://api.github.com/users/codice/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/codice/ddf","description":"DDF Distributed Data Framework - an open source, modular integration framework.","fork":false,"url":"https://api.github.com/repos/codice/ddf","forks_url":"https://api.github.com/repos/codice/ddf/forks","keys_url":"https://api.github.com/repos/codice/ddf/keys{/key_id}","collaborators_url":"https://api.github.com/repos/codice/ddf/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/codice/ddf/teams","hooks_url":"https://api.github.com/repos/codice/ddf/hooks","issue_events_url":"https://api.github.com/repos/codice/ddf/issues/events{/number}","events_url":"https://api.github.com/repos/codice/ddf/events","assignees_url":"https://api.github.com/repos/codice/ddf/assignees{/user}","branches_url":"https://api.github.com/repos/codice/ddf/branches{/branch}","tags_url":"https://api.github.com/repos/codice/ddf/tags","blobs_url":"https://api.github.com/repos/codice/ddf/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/codice/ddf/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/codice/ddf/git/refs{/sha}","trees_url":"https://api.github.com/repos/codice/ddf/git/trees{/sha}","statuses_url":"https://api.github.com/repos/codice/ddf/statuses/{sha}","languages_url":"https://api.github.com/repos/codice/ddf/languages","stargazers_url":"https://api.github.com/repos/codice/ddf/stargazers","contributors_url":"https://api.github.com/repos/codice/ddf/contributors","subscribers_url":"https://api.github.com/repos/codice/ddf/subscribers","subscription_url":"https://api.github.com/repos/codice/ddf/subscription","commits_url":"https://api.github.com/repos/codice/ddf/commits{/sha}","git_commits_url":"https://api.github.com/repos/codice/ddf/git/commits{/sha}","comments_url":"https://api.github.com/repos/codice/ddf/comments{/number}","issue_comment_url":"https://api.github.com/repos/codice/ddf/issues/comments{/number}","contents_url":"https://api.github.com/repos/codice/ddf/contents/{+path}","compare_url":"https://api.github.com/repos/codice/ddf/compare/{base}...{head}","merges_url":"https://api.github.com/repos/codice/ddf/merges","archive_url":"https://api.github.com/repos/codice/ddf/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/codice/ddf/downloads","issues_url":"https://api.github.com/repos/codice/ddf/issues{/number}","pulls_url":"https://api.github.com/repos/codice/ddf/pulls{/number}","milestones_url":"https://api.github.com/repos/codice/ddf/milestones{/number}","notifications_url":"https://api.github.com/repos/codice/ddf/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/codice/ddf/labels{/name}","releases_url":"https://api.github.com/repos/codice/ddf/releases{/id}","deployments_url":"https://api.github.com/repos/codice/ddf/deployments","created_at":"2013-12-13T20:38:28Z","updated_at":"2017-11-14T22:40:26Z","pushed_at":"2017-12-07T16:27:09Z","git_url":"git://github.com/codice/ddf.git","ssh_url":"git@github.com:codice/ddf.git","clone_url":"https://github.com/codice/ddf.git","svn_url":"https://github.com/codice/ddf","homepage":"http://ddf.codice.org","size":366210,"stargazers_count":68,"watchers_count":68,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":121,"mirror_url":null,"archived":false,"open_issues_count":39,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":121,"open_issues":39,"watchers":68,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/codice/ddf/pulls/2711"},"html":{"href":"https://github.com/codice/ddf/pull/2711"},"issue":{"href":"https://api.github.com/repos/codice/ddf/issues/2711"},"comments":{"href":"https://api.github.com/repos/codice/ddf/issues/2711/comments"},"review_comments":{"href":"https://api.github.com/repos/codice/ddf/pulls/2711/comments"},"review_comment":{"href":"https://api.github.com/repos/codice/ddf/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/codice/ddf/pulls/2711/commits"},"statuses":{"href":"https://api.github.com/repos/codice/ddf/statuses/e3c4a86e8fbd044bcd4654351ef99263f4d96f8f"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"rzwiefel"}}