{"action":"created","comment":{"url":"https://api.github.com/repos/begriffs/postgrest/pulls/comments/42323034","id":42323034,"diff_hunk":"@@ -1,104 +1,52 @@\n-module PostgREST.Auth where\n+{-# LANGUAGE FlexibleContexts #-}\n+module PostgREST.Auth (\n+  setRole\n+  , setJWTEnv\n+  , tokenJWT\n+  ) where\n \n import           Control.Applicative\n-import           Control.Monad           (mzero)\n-import           Crypto.BCrypt\n import           Data.Aeson\n-import           Data.Map\n+import           Data.Map (fromList, toList)\n+import           Data.Maybe (fromMaybe)\n import           Data.Monoid\n import           Data.String.Conversions (cs)\n-import           Data.Text\n-import           Data.Maybe (isNothing)\n-import qualified Data.Vector             as V\n-import qualified Hasql                   as H\n-import qualified Hasql.Backend           as B\n-import qualified Hasql.Postgres          as P\n+import           Data.Text (Text)\n import           PostgREST.PgQuery       (pgFmtLit)\n import           Prelude\n import qualified Web.JWT                 as JWT\n+import qualified Data.HashMap.Lazy       as HashMap\n+import Data.Aeson.Lens\n+import Control.Lens.Operators\n \n-import           System.IO.Unsafe\n+setJWTEnv :: Text -> Text -> Maybe [Text]\n+setJWTEnv secret input = setDBEnv $ jwtClaims secret input\n \n-data AuthUser = AuthUser {\n-    userId   :: String\n-  , userPass :: String\n-  , userRole :: Maybe String\n-  } deriving (Show)\n-\n-instance FromJSON AuthUser where\n-  parseJSON (Object v) = AuthUser <$>\n-                         v .: \"id\" <*>\n-                         v .: \"pass\" <*>\n-                         v .:? \"role\"\n-  parseJSON _ = mzero\n-\n-instance ToJSON AuthUser where\n-  toJSON u = object [\n-      \"id\" .= userId u\n-    , \"pass\" .= userPass u\n-    , \"role\" .= userRole u ]\n-\n-type DbRole = Text\n-type UserId = Text\n-\n-data LoginAttempt =\n-    NoCredentials\n-  | MalformedAuth\n-  | LoginFailed\n-  | LoginSuccess DbRole UserId\n-  deriving (Eq, Show)\n-\n-checkPass :: Text -> Text -> Bool\n-checkPass = (. cs) . validatePassword . cs\n-\n-setRole :: Text -> H.Tx P.Postgres s ()\n-setRole role = H.unitEx $ B.Stmt (\"set local role \" <> cs (pgFmtLit role)) V.empty True\n-\n-setUserId :: Text -> H.Tx P.Postgres s ()\n-setUserId uid =\n-  if uid /= \"\"\n-    then H.unitEx $ B.Stmt (\"set local user_vars.user_id = \" <> cs (pgFmtLit uid)) V.empty True\n-    else resetUserId\n-\n-resetUserId :: H.Tx P.Postgres s ()\n-resetUserId = H.unitEx [H.stmt|reset user_vars.user_id|]\n-\n-addUser :: Text -> Text -> Maybe Text -> H.Tx P.Postgres s ()\n-addUser identity pass role =\n-  H.unitEx $\n-    if isNothing role\n-      then [H.stmt|insert into postgrest.auth (id, pass) values (?, ?)|]\n-        identity hashedText\n-      else [H.stmt|insert into postgrest.auth (id, pass, rolname) values (?, ?, ?)|]\n-        identity hashedText role\n-  where Just hashed = unsafePerformIO $ hashPasswordUsingPolicy fastBcryptHashingPolicy (cs pass)\n-        hashedText = cs hashed :: Text\n-\n-signInRole :: Text -> Text -> H.Tx P.Postgres s LoginAttempt\n-signInRole user pass = do\n-  u <- H.maybeEx $ [H.stmt|select id, pass, rolname from postgrest.auth where id = ?|] user\n-  return $ maybe LoginFailed (\\r ->\n-      let (uid, hashed, role) = r in\n-      if checkPass hashed pass\n-         then LoginSuccess role uid\n-         else LoginFailed\n-    ) u\n-\n-signInWithJWT :: Text -> Text -> LoginAttempt\n-signInWithJWT secret input = case maybeRole of\n-    Just (Just (String role)) -> case maybeUserId of\n-      Just (Just (String uid)) -> LoginSuccess (cs role) (cs uid)\n-      _   -> LoginFailed\n-    _   -> LoginFailed\n+setDBEnv :: Maybe JWT.ClaimsMap -> Maybe [Text]\n+setDBEnv maybeClaims =\n+  (map setVar . toList) <$> maybeClaims\n+  where\n+    setVar (\"role\", String val) = setRole val","path":"src/PostgREST/Auth.hs","position":111,"original_position":111,"commit_id":"241a38e9585ea1a9588bfa3a9fbf60d3ca05eff7","original_commit_id":"241a38e9585ea1a9588bfa3a9fbf60d3ca05eff7","user":{"login":"begriffs","id":911911,"avatar_url":"https://avatars.githubusercontent.com/u/911911?v=3","gravatar_id":"","url":"https://api.github.com/users/begriffs","html_url":"https://github.com/begriffs","followers_url":"https://api.github.com/users/begriffs/followers","following_url":"https://api.github.com/users/begriffs/following{/other_user}","gists_url":"https://api.github.com/users/begriffs/gists{/gist_id}","starred_url":"https://api.github.com/users/begriffs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/begriffs/subscriptions","organizations_url":"https://api.github.com/users/begriffs/orgs","repos_url":"https://api.github.com/users/begriffs/repos","events_url":"https://api.github.com/users/begriffs/events{/privacy}","received_events_url":"https://api.github.com/users/begriffs/received_events","type":"User","site_admin":false},"body":"Just remembered there is similar code in [PostgREST.PgQuery.insertableValue](https://github.com/begriffs/postgrest/blob/master/src/PostgREST/PgQuery.hs#L300).\r\n\r\nYou could try\r\n\r\n```haskell\r\nsetVar (\"role\", String val) = setRole val\r\nsetVar (k, val) = \"set local postgrest.claims.\" <> pgFmtIdent k <>\r\n                  \" = \" <> insertableValue val <> \";\"\r\n```\r\n\r\nAlso notice the `pgFmtIdent` on `k`.","created_at":"2015-10-18T16:56:14Z","updated_at":"2015-10-18T16:56:14Z","html_url":"https://github.com/begriffs/postgrest/pull/320#discussion_r42323034","pull_request_url":"https://api.github.com/repos/begriffs/postgrest/pulls/320","_links":{"self":{"href":"https://api.github.com/repos/begriffs/postgrest/pulls/comments/42323034"},"html":{"href":"https://github.com/begriffs/postgrest/pull/320#discussion_r42323034"},"pull_request":{"href":"https://api.github.com/repos/begriffs/postgrest/pulls/320"}}},"pull_request":{"url":"https://api.github.com/repos/begriffs/postgrest/pulls/320","id":47860651,"html_url":"https://github.com/begriffs/postgrest/pull/320","diff_url":"https://github.com/begriffs/postgrest/pull/320.diff","patch_url":"https://github.com/begriffs/postgrest/pull/320.patch","issue_url":"https://api.github.com/repos/begriffs/postgrest/issues/320","number":320,"state":"open","locked":false,"title":"Jwt generic variables","user":{"login":"diogob","id":20662,"avatar_url":"https://avatars.githubusercontent.com/u/20662?v=3","gravatar_id":"","url":"https://api.github.com/users/diogob","html_url":"https://github.com/diogob","followers_url":"https://api.github.com/users/diogob/followers","following_url":"https://api.github.com/users/diogob/following{/other_user}","gists_url":"https://api.github.com/users/diogob/gists{/gist_id}","starred_url":"https://api.github.com/users/diogob/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diogob/subscriptions","organizations_url":"https://api.github.com/users/diogob/orgs","repos_url":"https://api.github.com/users/diogob/repos","events_url":"https://api.github.com/users/diogob/events{/privacy}","received_events_url":"https://api.github.com/users/diogob/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-10-16T00:59:50Z","updated_at":"2015-10-18T16:56:14Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4e5b6a916d1096f1bbb50ef576721eadcc92ab5f","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/begriffs/postgrest/pulls/320/commits","review_comments_url":"https://api.github.com/repos/begriffs/postgrest/pulls/320/comments","review_comment_url":"https://api.github.com/repos/begriffs/postgrest/pulls/comments{/number}","comments_url":"https://api.github.com/repos/begriffs/postgrest/issues/320/comments","statuses_url":"https://api.github.com/repos/begriffs/postgrest/statuses/241a38e9585ea1a9588bfa3a9fbf60d3ca05eff7","head":{"label":"diogob:jwt_generic_variables","ref":"jwt_generic_variables","sha":"241a38e9585ea1a9588bfa3a9fbf60d3ca05eff7","user":{"login":"diogob","id":20662,"avatar_url":"https://avatars.githubusercontent.com/u/20662?v=3","gravatar_id":"","url":"https://api.github.com/users/diogob","html_url":"https://github.com/diogob","followers_url":"https://api.github.com/users/diogob/followers","following_url":"https://api.github.com/users/diogob/following{/other_user}","gists_url":"https://api.github.com/users/diogob/gists{/gist_id}","starred_url":"https://api.github.com/users/diogob/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diogob/subscriptions","organizations_url":"https://api.github.com/users/diogob/orgs","repos_url":"https://api.github.com/users/diogob/repos","events_url":"https://api.github.com/users/diogob/events{/privacy}","received_events_url":"https://api.github.com/users/diogob/received_events","type":"User","site_admin":false},"repo":{"id":36082351,"name":"postgrest","full_name":"diogob/postgrest","owner":{"login":"diogob","id":20662,"avatar_url":"https://avatars.githubusercontent.com/u/20662?v=3","gravatar_id":"","url":"https://api.github.com/users/diogob","html_url":"https://github.com/diogob","followers_url":"https://api.github.com/users/diogob/followers","following_url":"https://api.github.com/users/diogob/following{/other_user}","gists_url":"https://api.github.com/users/diogob/gists{/gist_id}","starred_url":"https://api.github.com/users/diogob/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diogob/subscriptions","organizations_url":"https://api.github.com/users/diogob/orgs","repos_url":"https://api.github.com/users/diogob/repos","events_url":"https://api.github.com/users/diogob/events{/privacy}","received_events_url":"https://api.github.com/users/diogob/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/diogob/postgrest","description":"REST API for any Postgres database","fork":true,"url":"https://api.github.com/repos/diogob/postgrest","forks_url":"https://api.github.com/repos/diogob/postgrest/forks","keys_url":"https://api.github.com/repos/diogob/postgrest/keys{/key_id}","collaborators_url":"https://api.github.com/repos/diogob/postgrest/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/diogob/postgrest/teams","hooks_url":"https://api.github.com/repos/diogob/postgrest/hooks","issue_events_url":"https://api.github.com/repos/diogob/postgrest/issues/events{/number}","events_url":"https://api.github.com/repos/diogob/postgrest/events","assignees_url":"https://api.github.com/repos/diogob/postgrest/assignees{/user}","branches_url":"https://api.github.com/repos/diogob/postgrest/branches{/branch}","tags_url":"https://api.github.com/repos/diogob/postgrest/tags","blobs_url":"https://api.github.com/repos/diogob/postgrest/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/diogob/postgrest/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/diogob/postgrest/git/refs{/sha}","trees_url":"https://api.github.com/repos/diogob/postgrest/git/trees{/sha}","statuses_url":"https://api.github.com/repos/diogob/postgrest/statuses/{sha}","languages_url":"https://api.github.com/repos/diogob/postgrest/languages","stargazers_url":"https://api.github.com/repos/diogob/postgrest/stargazers","contributors_url":"https://api.github.com/repos/diogob/postgrest/contributors","subscribers_url":"https://api.github.com/repos/diogob/postgrest/subscribers","subscription_url":"https://api.github.com/repos/diogob/postgrest/subscription","commits_url":"https://api.github.com/repos/diogob/postgrest/commits{/sha}","git_commits_url":"https://api.github.com/repos/diogob/postgrest/git/commits{/sha}","comments_url":"https://api.github.com/repos/diogob/postgrest/comments{/number}","issue_comment_url":"https://api.github.com/repos/diogob/postgrest/issues/comments{/number}","contents_url":"https://api.github.com/repos/diogob/postgrest/contents/{+path}","compare_url":"https://api.github.com/repos/diogob/postgrest/compare/{base}...{head}","merges_url":"https://api.github.com/repos/diogob/postgrest/merges","archive_url":"https://api.github.com/repos/diogob/postgrest/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/diogob/postgrest/downloads","issues_url":"https://api.github.com/repos/diogob/postgrest/issues{/number}","pulls_url":"https://api.github.com/repos/diogob/postgrest/pulls{/number}","milestones_url":"https://api.github.com/repos/diogob/postgrest/milestones{/number}","notifications_url":"https://api.github.com/repos/diogob/postgrest/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/diogob/postgrest/labels{/name}","releases_url":"https://api.github.com/repos/diogob/postgrest/releases{/id}","created_at":"2015-05-22T16:20:22Z","updated_at":"2015-05-22T16:20:23Z","pushed_at":"2015-10-18T06:30:42Z","git_url":"git://github.com/diogob/postgrest.git","ssh_url":"git@github.com:diogob/postgrest.git","clone_url":"https://github.com/diogob/postgrest.git","svn_url":"https://github.com/diogob/postgrest","homepage":"","size":894,"stargazers_count":0,"watchers_count":0,"language":"Haskell","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":"begriffs:v3","ref":"v3","sha":"2c67b8d7bab9a7f86c532ffcffe5e55f3127ecf2","user":{"login":"begriffs","id":911911,"avatar_url":"https://avatars.githubusercontent.com/u/911911?v=3","gravatar_id":"","url":"https://api.github.com/users/begriffs","html_url":"https://github.com/begriffs","followers_url":"https://api.github.com/users/begriffs/followers","following_url":"https://api.github.com/users/begriffs/following{/other_user}","gists_url":"https://api.github.com/users/begriffs/gists{/gist_id}","starred_url":"https://api.github.com/users/begriffs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/begriffs/subscriptions","organizations_url":"https://api.github.com/users/begriffs/orgs","repos_url":"https://api.github.com/users/begriffs/repos","events_url":"https://api.github.com/users/begriffs/events{/privacy}","received_events_url":"https://api.github.com/users/begriffs/received_events","type":"User","site_admin":false},"repo":{"id":20787122,"name":"postgrest","full_name":"begriffs/postgrest","owner":{"login":"begriffs","id":911911,"avatar_url":"https://avatars.githubusercontent.com/u/911911?v=3","gravatar_id":"","url":"https://api.github.com/users/begriffs","html_url":"https://github.com/begriffs","followers_url":"https://api.github.com/users/begriffs/followers","following_url":"https://api.github.com/users/begriffs/following{/other_user}","gists_url":"https://api.github.com/users/begriffs/gists{/gist_id}","starred_url":"https://api.github.com/users/begriffs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/begriffs/subscriptions","organizations_url":"https://api.github.com/users/begriffs/orgs","repos_url":"https://api.github.com/users/begriffs/repos","events_url":"https://api.github.com/users/begriffs/events{/privacy}","received_events_url":"https://api.github.com/users/begriffs/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/begriffs/postgrest","description":"REST API for any Postgres database","fork":false,"url":"https://api.github.com/repos/begriffs/postgrest","forks_url":"https://api.github.com/repos/begriffs/postgrest/forks","keys_url":"https://api.github.com/repos/begriffs/postgrest/keys{/key_id}","collaborators_url":"https://api.github.com/repos/begriffs/postgrest/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/begriffs/postgrest/teams","hooks_url":"https://api.github.com/repos/begriffs/postgrest/hooks","issue_events_url":"https://api.github.com/repos/begriffs/postgrest/issues/events{/number}","events_url":"https://api.github.com/repos/begriffs/postgrest/events","assignees_url":"https://api.github.com/repos/begriffs/postgrest/assignees{/user}","branches_url":"https://api.github.com/repos/begriffs/postgrest/branches{/branch}","tags_url":"https://api.github.com/repos/begriffs/postgrest/tags","blobs_url":"https://api.github.com/repos/begriffs/postgrest/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/begriffs/postgrest/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/begriffs/postgrest/git/refs{/sha}","trees_url":"https://api.github.com/repos/begriffs/postgrest/git/trees{/sha}","statuses_url":"https://api.github.com/repos/begriffs/postgrest/statuses/{sha}","languages_url":"https://api.github.com/repos/begriffs/postgrest/languages","stargazers_url":"https://api.github.com/repos/begriffs/postgrest/stargazers","contributors_url":"https://api.github.com/repos/begriffs/postgrest/contributors","subscribers_url":"https://api.github.com/repos/begriffs/postgrest/subscribers","subscription_url":"https://api.github.com/repos/begriffs/postgrest/subscription","commits_url":"https://api.github.com/repos/begriffs/postgrest/commits{/sha}","git_commits_url":"https://api.github.com/repos/begriffs/postgrest/git/commits{/sha}","comments_url":"https://api.github.com/repos/begriffs/postgrest/comments{/number}","issue_comment_url":"https://api.github.com/repos/begriffs/postgrest/issues/comments{/number}","contents_url":"https://api.github.com/repos/begriffs/postgrest/contents/{+path}","compare_url":"https://api.github.com/repos/begriffs/postgrest/compare/{base}...{head}","merges_url":"https://api.github.com/repos/begriffs/postgrest/merges","archive_url":"https://api.github.com/repos/begriffs/postgrest/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/begriffs/postgrest/downloads","issues_url":"https://api.github.com/repos/begriffs/postgrest/issues{/number}","pulls_url":"https://api.github.com/repos/begriffs/postgrest/pulls{/number}","milestones_url":"https://api.github.com/repos/begriffs/postgrest/milestones{/number}","notifications_url":"https://api.github.com/repos/begriffs/postgrest/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/begriffs/postgrest/labels{/name}","releases_url":"https://api.github.com/repos/begriffs/postgrest/releases{/id}","created_at":"2014-06-13T00:23:00Z","updated_at":"2015-10-18T15:58:33Z","pushed_at":"2015-10-18T06:30:43Z","git_url":"git://github.com/begriffs/postgrest.git","ssh_url":"git@github.com:begriffs/postgrest.git","clone_url":"https://github.com/begriffs/postgrest.git","svn_url":"https://github.com/begriffs/postgrest","homepage":"","size":3717,"stargazers_count":5621,"watchers_count":5621,"language":"Haskell","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":172,"mirror_url":null,"open_issues_count":84,"forks":172,"open_issues":84,"watchers":5621,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/begriffs/postgrest/pulls/320"},"html":{"href":"https://github.com/begriffs/postgrest/pull/320"},"issue":{"href":"https://api.github.com/repos/begriffs/postgrest/issues/320"},"comments":{"href":"https://api.github.com/repos/begriffs/postgrest/issues/320/comments"},"review_comments":{"href":"https://api.github.com/repos/begriffs/postgrest/pulls/320/comments"},"review_comment":{"href":"https://api.github.com/repos/begriffs/postgrest/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/begriffs/postgrest/pulls/320/commits"},"statuses":{"href":"https://api.github.com/repos/begriffs/postgrest/statuses/241a38e9585ea1a9588bfa3a9fbf60d3ca05eff7"}}}}