{"action":"created","comment":{"url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls/comments/91686113","pull_request_review_id":12196415,"id":91686113,"diff_hunk":"@@ -0,0 +1,353 @@\n+package bakery\n+\n+import (\n+\t\"bytes\"\n+\t\"encoding/base64\"\n+\t\"encoding/binary\"\n+\t\"encoding/json\"\n+\n+\t\"golang.org/x/net/context\"\n+\t\"gopkg.in/errgo.v1\"\n+\t\"gopkg.in/macaroon.v2-unstable\"\n+\n+\t\"gopkg.in/macaroon-bakery.v2-unstable/bakery/checkers\"\n+)\n+\n+// legacyNamespace holds the standard namespace as used by\n+// pre-version3 macaroons.\n+func legacyNamespace() *checkers.Namespace {\n+\tns := checkers.NewNamespace(nil)\n+\tns.Register(checkers.StdNamespace, \"\")\n+\treturn ns\n+}\n+\n+// Macaroon represents an undischarged macaroon along its first\n+// party caveat namespace and associated third party caveat information\n+// which should be passed to the third party when discharging a caveat.\n+type Macaroon struct {\n+\t// m holds the underlying macaroon.\n+\tm *macaroon.Macaroon\n+\n+\t// version holds the version of the macaroon.\n+\tversion Version\n+\n+\t// caveatData maps from a third party caveat id to its\n+\t// associated information, usually public-key encrypted with the\n+\t// third party's public key.\n+\t//\n+\t// If version is less than Version3, this will always be nil,\n+\t// because clients prior to that version do not support\n+\t// macaroon-external caveat ids.\n+\tcaveatData map[string][]byte\n+\n+\t// namespace holds the first-party caveat namespace of the macaroon.\n+\tnamespace *checkers.Namespace\n+\n+\t// caveatIdPrefix holds the prefix to use for the ids of any third\n+\t// party caveats created. This can be set when Discharge creates a\n+\t// discharge macaroon.\n+\tcaveatIdPrefix []byte\n+}\n+\n+type macaroonJSON struct {\n+\tMacaroon *macaroon.Macaroon `json:\"m\"`\n+\tVersion  Version            `json:\"v\"`\n+\t// Note: CaveatData is encoded using URL-base64-encoded keys\n+\t// because JSON cannot deal with arbitrary byte sequences\n+\t// in its strings, and URL-base64 values to match the\n+\t// standard macaroon encoding.\n+\tCaveatData map[string]string   `json:\"cdata,omitempty\"`\n+\tNamespace  *checkers.Namespace `json:\"ns\"`\n+}\n+\n+// Clone returns a copy of the macaroon. Note that the the new\n+// macaroon's namespace still points to the same underlying Namespace -\n+// copying the macaroon does not make a copy of the namespace.\n+func (m *Macaroon) Clone() *Macaroon {\n+\tm1 := *m\n+\tm1.m = m1.m.Clone()\n+\tm1.caveatData = make(map[string][]byte)\n+\tfor id, data := range m.caveatData {\n+\t\tm1.caveatData[id] = data\n+\t}\n+\treturn &m1\n+}\n+\n+// MarshalJSON implements json.Marshaler by marshaling\n+// the macaroon into the original macaroon format if the\n+// version is earlier than Version3.\n+func (m *Macaroon) MarshalJSON() ([]byte, error) {\n+\tif m.version < Version3 {\n+\t\tif len(m.caveatData) > 0 {\n+\t\t\treturn nil, errgo.Newf(\"cannot marshal pre-version3 macaroon with external caveat data\")\n+\t\t}\n+\t\treturn m.m.MarshalJSON()\n+\t}\n+\tcaveatData := make(map[string]string)\n+\tfor id, data := range m.caveatData {\n+\t\tcaveatData[base64.RawURLEncoding.EncodeToString([]byte(id))] = base64.RawURLEncoding.EncodeToString(data)\n+\t}\n+\treturn json.Marshal(macaroonJSON{\n+\t\tMacaroon:   m.m,\n+\t\tVersion:    m.version,\n+\t\tCaveatData: caveatData,\n+\t\tNamespace:  m.namespace,\n+\t})\n+}\n+\n+// UnmarshalJSON implements json.Unmarshaler by unmarshaling in a\n+// backwardly compatible way - if provided with a previous macaroon\n+// version, it will unmarshal that too.\n+func (m *Macaroon) UnmarshalJSON(data []byte) error {\n+\t// First try with new data format.\n+\tvar m1 macaroonJSON\n+\tif err := json.Unmarshal(data, &m1); err != nil {\n+\t\t// If we get an unmarshal error, we won't be able\n+\t\t// to unmarshal into the old format either, as extra fields\n+\t\t// are ignored.\n+\t\treturn errgo.Mask(err)\n+\t}\n+\tif m1.Macaroon != nil {\n+\t\t// We've got macaroon field - it's the new format.","path":"bakery/macaroon.go","position":111,"original_position":111,"commit_id":"ff14edf2a1f9ab3b4ef0cd36277bcec80d9d9190","original_commit_id":"ff14edf2a1f9ab3b4ef0cd36277bcec80d9d9190","user":{"login":"rogpeppe","id":66491,"avatar_url":"https://avatars.githubusercontent.com/u/66491?v=3","gravatar_id":"","url":"https://api.github.com/users/rogpeppe","html_url":"https://github.com/rogpeppe","followers_url":"https://api.github.com/users/rogpeppe/followers","following_url":"https://api.github.com/users/rogpeppe/following{/other_user}","gists_url":"https://api.github.com/users/rogpeppe/gists{/gist_id}","starred_url":"https://api.github.com/users/rogpeppe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rogpeppe/subscriptions","organizations_url":"https://api.github.com/users/rogpeppe/orgs","repos_url":"https://api.github.com/users/rogpeppe/repos","events_url":"https://api.github.com/users/rogpeppe/events{/privacy}","received_events_url":"https://api.github.com/users/rogpeppe/received_events","type":"User","site_admin":false},"body":"Done, slightly differently.","created_at":"2016-12-09T09:51:07Z","updated_at":"2016-12-09T09:51:07Z","html_url":"https://github.com/go-macaroon-bakery/macaroon-bakery/pull/122#discussion_r91686113","pull_request_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls/122","_links":{"self":{"href":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls/comments/91686113"},"html":{"href":"https://github.com/go-macaroon-bakery/macaroon-bakery/pull/122#discussion_r91686113"},"pull_request":{"href":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls/122"}}},"pull_request":{"url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls/122","id":96941554,"html_url":"https://github.com/go-macaroon-bakery/macaroon-bakery/pull/122","diff_url":"https://github.com/go-macaroon-bakery/macaroon-bakery/pull/122.diff","patch_url":"https://github.com/go-macaroon-bakery/macaroon-bakery/pull/122.patch","issue_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/issues/122","number":122,"state":"open","locked":false,"title":"bakery: pass third party caveats externally","user":{"login":"rogpeppe","id":66491,"avatar_url":"https://avatars.githubusercontent.com/u/66491?v=3","gravatar_id":"","url":"https://api.github.com/users/rogpeppe","html_url":"https://github.com/rogpeppe","followers_url":"https://api.github.com/users/rogpeppe/followers","following_url":"https://api.github.com/users/rogpeppe/following{/other_user}","gists_url":"https://api.github.com/users/rogpeppe/gists{/gist_id}","starred_url":"https://api.github.com/users/rogpeppe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rogpeppe/subscriptions","organizations_url":"https://api.github.com/users/rogpeppe/orgs","repos_url":"https://api.github.com/users/rogpeppe/repos","events_url":"https://api.github.com/users/rogpeppe/events{/privacy}","received_events_url":"https://api.github.com/users/rogpeppe/received_events","type":"User","site_admin":false},"body":"We define a new bakery.Macaroon type that holds external\r\nthird party caveat information and also the namespace\r\nto use when adding first party caveats.\r\n\r\nThis is backwardly compatible with the old data format. When\r\na bakery.Macaroon containing an old macaroon is marshaled,\r\nit uses the old format; when it's unmarshaled, it understands\r\nthe old formats. This should make it possible to\r\nbe fully backward compatible with old clients.","created_at":"2016-12-07T15:11:11Z","updated_at":"2016-12-09T09:51:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"955ba3003358c751e02b9d617823cb49fcda5864","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls/122/commits","review_comments_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls/122/comments","review_comment_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls/comments{/number}","comments_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/issues/122/comments","statuses_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/statuses/ff14edf2a1f9ab3b4ef0cd36277bcec80d9d9190","head":{"label":"rogpeppe:081-external-caveat-ids","ref":"081-external-caveat-ids","sha":"ff14edf2a1f9ab3b4ef0cd36277bcec80d9d9190","user":{"login":"rogpeppe","id":66491,"avatar_url":"https://avatars.githubusercontent.com/u/66491?v=3","gravatar_id":"","url":"https://api.github.com/users/rogpeppe","html_url":"https://github.com/rogpeppe","followers_url":"https://api.github.com/users/rogpeppe/followers","following_url":"https://api.github.com/users/rogpeppe/following{/other_user}","gists_url":"https://api.github.com/users/rogpeppe/gists{/gist_id}","starred_url":"https://api.github.com/users/rogpeppe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rogpeppe/subscriptions","organizations_url":"https://api.github.com/users/rogpeppe/orgs","repos_url":"https://api.github.com/users/rogpeppe/repos","events_url":"https://api.github.com/users/rogpeppe/events{/privacy}","received_events_url":"https://api.github.com/users/rogpeppe/received_events","type":"User","site_admin":false},"repo":{"id":26593657,"name":"macaroon-bakery","full_name":"rogpeppe/macaroon-bakery","owner":{"login":"rogpeppe","id":66491,"avatar_url":"https://avatars.githubusercontent.com/u/66491?v=3","gravatar_id":"","url":"https://api.github.com/users/rogpeppe","html_url":"https://github.com/rogpeppe","followers_url":"https://api.github.com/users/rogpeppe/followers","following_url":"https://api.github.com/users/rogpeppe/following{/other_user}","gists_url":"https://api.github.com/users/rogpeppe/gists{/gist_id}","starred_url":"https://api.github.com/users/rogpeppe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rogpeppe/subscriptions","organizations_url":"https://api.github.com/users/rogpeppe/orgs","repos_url":"https://api.github.com/users/rogpeppe/repos","events_url":"https://api.github.com/users/rogpeppe/events{/privacy}","received_events_url":"https://api.github.com/users/rogpeppe/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rogpeppe/macaroon-bakery","description":"We bake 'em sweet, we bake 'em nice","fork":true,"url":"https://api.github.com/repos/rogpeppe/macaroon-bakery","forks_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/forks","keys_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/teams","hooks_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/hooks","issue_events_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/issues/events{/number}","events_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/events","assignees_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/assignees{/user}","branches_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/branches{/branch}","tags_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/tags","blobs_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/git/refs{/sha}","trees_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/statuses/{sha}","languages_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/languages","stargazers_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/stargazers","contributors_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/contributors","subscribers_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/subscribers","subscription_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/subscription","commits_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/commits{/sha}","git_commits_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/git/commits{/sha}","comments_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/comments{/number}","issue_comment_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/issues/comments{/number}","contents_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/contents/{+path}","compare_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/merges","archive_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/downloads","issues_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/issues{/number}","pulls_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/pulls{/number}","milestones_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/milestones{/number}","notifications_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/labels{/name}","releases_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/releases{/id}","deployments_url":"https://api.github.com/repos/rogpeppe/macaroon-bakery/deployments","created_at":"2014-11-13T15:18:37Z","updated_at":"2014-12-11T03:12:38Z","pushed_at":"2016-12-07T20:36:43Z","git_url":"git://github.com/rogpeppe/macaroon-bakery.git","ssh_url":"git@github.com:rogpeppe/macaroon-bakery.git","clone_url":"https://github.com/rogpeppe/macaroon-bakery.git","svn_url":"https://github.com/rogpeppe/macaroon-bakery","homepage":null,"size":725,"stargazers_count":1,"watchers_count":1,"language":"Go","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":1,"default_branch":"v0"}},"base":{"label":"go-macaroon-bakery:v2-unstable","ref":"v2-unstable","sha":"152316b6be844672054972fff0e9a3fe966950b5","user":{"login":"go-macaroon-bakery","id":9721471,"avatar_url":"https://avatars.githubusercontent.com/u/9721471?v=3","gravatar_id":"","url":"https://api.github.com/users/go-macaroon-bakery","html_url":"https://github.com/go-macaroon-bakery","followers_url":"https://api.github.com/users/go-macaroon-bakery/followers","following_url":"https://api.github.com/users/go-macaroon-bakery/following{/other_user}","gists_url":"https://api.github.com/users/go-macaroon-bakery/gists{/gist_id}","starred_url":"https://api.github.com/users/go-macaroon-bakery/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/go-macaroon-bakery/subscriptions","organizations_url":"https://api.github.com/users/go-macaroon-bakery/orgs","repos_url":"https://api.github.com/users/go-macaroon-bakery/repos","events_url":"https://api.github.com/users/go-macaroon-bakery/events{/privacy}","received_events_url":"https://api.github.com/users/go-macaroon-bakery/received_events","type":"Organization","site_admin":false},"repo":{"id":26593206,"name":"macaroon-bakery","full_name":"go-macaroon-bakery/macaroon-bakery","owner":{"login":"go-macaroon-bakery","id":9721471,"avatar_url":"https://avatars.githubusercontent.com/u/9721471?v=3","gravatar_id":"","url":"https://api.github.com/users/go-macaroon-bakery","html_url":"https://github.com/go-macaroon-bakery","followers_url":"https://api.github.com/users/go-macaroon-bakery/followers","following_url":"https://api.github.com/users/go-macaroon-bakery/following{/other_user}","gists_url":"https://api.github.com/users/go-macaroon-bakery/gists{/gist_id}","starred_url":"https://api.github.com/users/go-macaroon-bakery/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/go-macaroon-bakery/subscriptions","organizations_url":"https://api.github.com/users/go-macaroon-bakery/orgs","repos_url":"https://api.github.com/users/go-macaroon-bakery/repos","events_url":"https://api.github.com/users/go-macaroon-bakery/events{/privacy}","received_events_url":"https://api.github.com/users/go-macaroon-bakery/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/go-macaroon-bakery/macaroon-bakery","description":"We bake 'em sweet, we bake 'em nice","fork":false,"url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery","forks_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/forks","keys_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/keys{/key_id}","collaborators_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/teams","hooks_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/hooks","issue_events_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/issues/events{/number}","events_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/events","assignees_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/assignees{/user}","branches_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/branches{/branch}","tags_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/tags","blobs_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/git/refs{/sha}","trees_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/git/trees{/sha}","statuses_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/statuses/{sha}","languages_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/languages","stargazers_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/stargazers","contributors_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/contributors","subscribers_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/subscribers","subscription_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/subscription","commits_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/commits{/sha}","git_commits_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/git/commits{/sha}","comments_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/comments{/number}","issue_comment_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/issues/comments{/number}","contents_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/contents/{+path}","compare_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/compare/{base}...{head}","merges_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/merges","archive_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/downloads","issues_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/issues{/number}","pulls_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls{/number}","milestones_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/milestones{/number}","notifications_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/labels{/name}","releases_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/releases{/id}","deployments_url":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/deployments","created_at":"2014-11-13T15:08:41Z","updated_at":"2016-12-09T03:26:28Z","pushed_at":"2016-12-08T10:58:27Z","git_url":"git://github.com/go-macaroon-bakery/macaroon-bakery.git","ssh_url":"git@github.com:go-macaroon-bakery/macaroon-bakery.git","clone_url":"https://github.com/go-macaroon-bakery/macaroon-bakery.git","svn_url":"https://github.com/go-macaroon-bakery/macaroon-bakery","homepage":null,"size":675,"stargazers_count":21,"watchers_count":21,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":10,"mirror_url":null,"open_issues_count":7,"forks":10,"open_issues":7,"watchers":21,"default_branch":"v1"}},"_links":{"self":{"href":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls/122"},"html":{"href":"https://github.com/go-macaroon-bakery/macaroon-bakery/pull/122"},"issue":{"href":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/issues/122"},"comments":{"href":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/issues/122/comments"},"review_comments":{"href":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls/122/comments"},"review_comment":{"href":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/pulls/122/commits"},"statuses":{"href":"https://api.github.com/repos/go-macaroon-bakery/macaroon-bakery/statuses/ff14edf2a1f9ab3b4ef0cd36277bcec80d9d9190"}}}}
{"actor":{"display_login":"rogpeppe"}}