{"action":"created","issue":{"url":"https://api.github.com/repos/hexpm/hex_web/issues/378","repository_url":"https://api.github.com/repos/hexpm/hex_web","labels_url":"https://api.github.com/repos/hexpm/hex_web/issues/378/labels{/name}","comments_url":"https://api.github.com/repos/hexpm/hex_web/issues/378/comments","events_url":"https://api.github.com/repos/hexpm/hex_web/issues/378/events","html_url":"https://github.com/hexpm/hex_web/pull/378","id":164387877,"number":378,"title":"Revoke one or all keys for a user","user":{"login":"potatosalad","id":1804,"avatar_url":"https://avatars.githubusercontent.com/u/1804?v=3","gravatar_id":"","url":"https://api.github.com/users/potatosalad","html_url":"https://github.com/potatosalad","followers_url":"https://api.github.com/users/potatosalad/followers","following_url":"https://api.github.com/users/potatosalad/following{/other_user}","gists_url":"https://api.github.com/users/potatosalad/gists{/gist_id}","starred_url":"https://api.github.com/users/potatosalad/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/potatosalad/subscriptions","organizations_url":"https://api.github.com/users/potatosalad/orgs","repos_url":"https://api.github.com/users/potatosalad/repos","events_url":"https://api.github.com/users/potatosalad/events{/privacy}","received_events_url":"https://api.github.com/users/potatosalad/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":6,"created_at":"2016-07-07T19:25:22Z","updated_at":"2016-07-11T10:23:49Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/hexpm/hex_web/pulls/378","html_url":"https://github.com/hexpm/hex_web/pull/378","diff_url":"https://github.com/hexpm/hex_web/pull/378.diff","patch_url":"https://github.com/hexpm/hex_web/pull/378.patch"},"body":"This pull request should hopefully resolve #374, #375, and #376.\r\n\r\n### Summary of changes\r\n\r\n1. Keys are marked as revoked instead of deleted (see #375)\r\n2. All keys associated with a user may be revoked with `DELETE /api/keys` (see #374)\r\n3. Added a checkbox on password reset form so user can choose whether they want to revoke all of their API keys at the same time (see #376)\r\n   ![image](https://cloud.githubusercontent.com/assets/1804/16666232/f533d14a-4443-11e6-9925-e6d313b3d8a1.png)\r\n\r\n##### Minor changes\r\n\r\nThese changes are in preparation for some of the issues mentioned for the [hex](https://github.com/hexpm/hex) project.\r\n\r\n1. If the current API key used for authentication has been revoked, the name and revocation time are returned to the client.  Otherwise, no content is returned.  (see hexpm/hex#252 and hexpm/hex#253)\r\n2. Revoking all API keys should now be possible within a mix task.  (see hexpm/hex#251)\r\n\r\n### Key Revocation Design\r\n\r\n**Update 2016/07/07:** Changes to design after code review.\r\n\r\nOne new column has been added to the `keys` table: `revoked_at`.\r\n\r\nThe `Ecto.Query` for the revocation operations are demonstrated below:\r\n\r\n```elixir\r\n# Revoke all keys\r\nrevoked_at = Ecto.DateTime.utc\r\nfrom(k in assoc(user, :keys),\r\n  where: is_nil(k.revoked_at),\r\n  update: [set: [revoked_at: fragment(\"?\", ^revoked_at)]])\r\n|> HexWeb.Repo.update_all([])\r\n\r\n# Revoke one key\r\nkey_name = \"test\"\r\nrevoked_at = Ecto.DateTime.utc\r\nfrom(k in assoc(user, :keys),\r\n  where: k.name == ^key_name and is_nil(k.revoked_at),\r\n  update: [set: [revoked_at: fragment(\"?\", ^revoked_at)]])\r\n|> HexWeb.Repo.update_all([])\r\n```"},"comment":{"url":"https://api.github.com/repos/hexpm/hex_web/issues/comments/231697339","html_url":"https://github.com/hexpm/hex_web/pull/378#issuecomment-231697339","issue_url":"https://api.github.com/repos/hexpm/hex_web/issues/378","id":231697339,"user":{"login":"ericmj","id":316890,"avatar_url":"https://avatars.githubusercontent.com/u/316890?v=3","gravatar_id":"","url":"https://api.github.com/users/ericmj","html_url":"https://github.com/ericmj","followers_url":"https://api.github.com/users/ericmj/followers","following_url":"https://api.github.com/users/ericmj/following{/other_user}","gists_url":"https://api.github.com/users/ericmj/gists{/gist_id}","starred_url":"https://api.github.com/users/ericmj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ericmj/subscriptions","organizations_url":"https://api.github.com/users/ericmj/orgs","repos_url":"https://api.github.com/users/ericmj/repos","events_url":"https://api.github.com/users/ericmj/events{/privacy}","received_events_url":"https://api.github.com/users/ericmj/received_events","type":"User","site_admin":false},"created_at":"2016-07-11T10:23:49Z","updated_at":"2016-07-11T10:23:49Z","body":"Beautiful :heart:"}}
{"actor":{"display_login":"ericmj"}}