From 709a23e16926913408f0aa45822f27231ca1f8d0 Mon Sep 17 00:00:00 2001 From: GitBluub Date: Wed, 2 Mar 2022 16:00:37 +0100 Subject: [PATCH 1/6] feat: adds xpires in to databse --- api/src/Core/OIDC.hs | 20 +++++++++++++------- api/src/Utils.hs | 7 +++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/api/src/Core/OIDC.hs b/api/src/Core/OIDC.hs index 7302668..e6e9c86 100644 --- a/api/src/Core/OIDC.hs +++ b/api/src/Core/OIDC.hs @@ -11,7 +11,7 @@ import Data.Aeson.Types (Object, Value (String)) import Data.Text (Text, pack, unpack) import Network.HTTP.Simple (JSONException, addRequestHeader, getResponseBody, httpJSONEither, parseRequest, setRequestMethod, setRequestQueryString, setRequestBodyURLEncoded) import System.Environment.MrEnv (envAsBool, envAsInt, envAsInteger, envAsString) -import Utils (lookupObjString) +import Utils (lookupObjString, lookupObjInt) import Data.ByteString.Base64 data OAuth2Conf = OAuth2Conf { oauthClientId :: String @@ -60,7 +60,8 @@ getGithubTokens code _ = do Right obj -> do access <- lookupObjString obj "access_token" refresh <- lookupObjString obj "refresh_token" - Just $ ExternalToken (pack access) (pack refresh) 0 Github + expires_in <- lookupObjInt obj "expires_in" + Just $ ExternalToken (pack access) (pack refresh) expires_in Github -- DISCORD getDiscordConfig :: IO OAuth2Conf @@ -92,7 +93,8 @@ getDiscordTokens code redirect = do Right obj -> do access <- lookupObjString obj "access_token" refresh <- lookupObjString obj "refresh_token" - Just $ ExternalToken (pack access) (pack refresh) 0 Discord + expires_in <- lookupObjInt obj "expires_in" + Just $ ExternalToken (pack access) (pack refresh) expires_in Discord -- GOOGLE getGoogleConfig :: IO OAuth2Conf @@ -124,7 +126,8 @@ getGoogleTokens code redirect = do Right obj -> do access <- lookupObjString obj "access_token" refresh <- lookupObjString obj "refresh_token" - Just $ ExternalToken (pack access) (pack refresh) 0 Google + expires_in <- lookupObjInt obj "expires_in" + Just $ ExternalToken (pack access) (pack refresh) expires_in Google -- SPOTIFY getSpotifyConfig :: IO OAuth2Conf @@ -157,7 +160,8 @@ getSpotifyTokens code redirect = do Right obj -> do access <- lookupObjString obj "access_token" refresh <- lookupObjString obj "refresh_token" - Just $ ExternalToken (pack access) (pack refresh) 0 Spotify + expires_in <- lookupObjInt obj "expires_in" + Just $ ExternalToken (pack access) (pack refresh) expires_in Spotify -- TWITTER getTwitterConfig :: IO OAuth2Conf @@ -190,7 +194,8 @@ getTwitterTokens code redirect = do Right obj -> do access <- lookupObjString obj "access_token" refresh <- lookupObjString obj "refresh_token" - Just $ ExternalToken (pack access) (pack refresh) 0 Twitter + expires_in <- lookupObjInt obj "expires_in" + Just $ ExternalToken (pack access) (pack refresh) expires_in Twitter -- ANILIST getAnilistConfig :: IO OAuth2Conf @@ -222,7 +227,8 @@ getAnilistTokens code redirect = do Right obj -> do access <- lookupObjString obj "access_token" refresh <- lookupObjString obj "refresh_token" - Just $ ExternalToken (pack access) (pack refresh) 0 Anilist + expires_in <- lookupObjInt obj "expires_in" + Just $ ExternalToken (pack access) (pack refresh) expires_in Anilist diff --git a/api/src/Utils.hs b/api/src/Utils.hs index 174ca84..8f2acbb 100644 --- a/api/src/Utils.hs +++ b/api/src/Utils.hs @@ -19,6 +19,7 @@ import Core.Pipeline (PipelineParams (PipelineParams)) import Data.Time (UTCTime (UTCTime), fromGregorian, secondsToDiffTime) import Data.Default (Default, def) import Data.Aeson (Value(Number, Object), decode) +import Data.Int (Int64) mapInd :: (a -> Int -> b) -> [a] -> [b] mapInd f l = zipWith f l [0 ..] @@ -28,6 +29,12 @@ lookupObjString obj key = case Data.HashMap.Strict.lookup key obj of Just (String x) -> Just . unpack $ x _ -> Nothing + +lookupObjInt :: Object -> Text -> Maybe Int64 +lookupObjInt obj key = case Data.HashMap.Strict.lookup key obj of + Just (Number x) -> Just . toInt64 $ x + _ -> Nothing + uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d uncurry3 f (a, b, c) = f a b c From 23f72911107bcf6c73ec6a7aac0552fe5f1d3200 Mon Sep 17 00:00:00 2001 From: GitBluub Date: Wed, 2 Mar 2022 16:58:02 +0100 Subject: [PATCH 2/6] fix: added scientific package to convert to int64 --- api/aeris.cabal | 4 ++++ api/package.yaml | 1 + api/src/Utils.hs | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/api/aeris.cabal b/api/aeris.cabal index c89886c..3d28852 100644 --- a/api/aeris.cabal +++ b/api/aeris.cabal @@ -20,6 +20,7 @@ extra-source-files: services/discord.json services/github.json services/spotify.json + services/twitter.json services/youtube.json source-repository head @@ -75,6 +76,7 @@ library , network , opaleye >=0.9.0.0 && <0.9.1.0 , rel8 + , scientific ==0.3.7.0 , servant , servant-auth , servant-auth-server @@ -117,6 +119,7 @@ executable aeris-exe , network , opaleye >=0.9.0.0 && <0.9.1.0 , rel8 + , scientific ==0.3.7.0 , servant , servant-auth , servant-auth-server @@ -163,6 +166,7 @@ test-suite aeris-test , network , opaleye >=0.9.0.0 && <0.9.1.0 , rel8 + , scientific ==0.3.7.0 , servant , servant-auth , servant-auth-server diff --git a/api/package.yaml b/api/package.yaml index 1a37a24..d8b27d0 100644 --- a/api/package.yaml +++ b/api/package.yaml @@ -34,6 +34,7 @@ dependencies: - servant-errors - data-default - bytestring +- scientific == 0.3.7.0 - network - base64 - text diff --git a/api/src/Utils.hs b/api/src/Utils.hs index 8f2acbb..b3ca91d 100644 --- a/api/src/Utils.hs +++ b/api/src/Utils.hs @@ -20,6 +20,7 @@ import Data.Time (UTCTime (UTCTime), fromGregorian, secondsToDiffTime) import Data.Default (Default, def) import Data.Aeson (Value(Number, Object), decode) import Data.Int (Int64) +import Data.Scientific mapInd :: (a -> Int -> b) -> [a] -> [b] mapInd f l = zipWith f l [0 ..] @@ -32,7 +33,7 @@ lookupObjString obj key = case Data.HashMap.Strict.lookup key obj of lookupObjInt :: Object -> Text -> Maybe Int64 lookupObjInt obj key = case Data.HashMap.Strict.lookup key obj of - Just (Number x) -> Just . toInt64 $ x + Just (Number x) -> toBoundedInteger $ x _ -> Nothing uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d From 4892bb2685e816a7c0df59dc2a0749fa9db28862 Mon Sep 17 00:00:00 2001 From: GitBluub Date: Wed, 2 Mar 2022 16:59:44 +0100 Subject: [PATCH 3/6] fix: smaller import --- api/src/Utils.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/Utils.hs b/api/src/Utils.hs index b3ca91d..16a04be 100644 --- a/api/src/Utils.hs +++ b/api/src/Utils.hs @@ -20,7 +20,7 @@ import Data.Time (UTCTime (UTCTime), fromGregorian, secondsToDiffTime) import Data.Default (Default, def) import Data.Aeson (Value(Number, Object), decode) import Data.Int (Int64) -import Data.Scientific +import Data.Scientific ( toBoundedInteger ) mapInd :: (a -> Int -> b) -> [a] -> [b] mapInd f l = zipWith f l [0 ..] From fef97f29351fcc23380594c82aaab0271b088156 Mon Sep 17 00:00:00 2001 From: GitBluub Date: Thu, 3 Mar 2022 15:43:39 +0100 Subject: [PATCH 4/6] fix: inform worker good route --- api/src/Api/Pipeline.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/Api/Pipeline.hs b/api/src/Api/Pipeline.hs index 24f94b8..457e4fc 100644 --- a/api/src/Api/Pipeline.hs +++ b/api/src/Api/Pipeline.hs @@ -136,13 +136,13 @@ informWorker method id = do url <- envAsString "WORKER_URL" "worker/" request <- parseRequest url + print request response <- httpBS $ setRequestMethod method - $ addRequestHeader "Accept" "application/json" - $ setRequestPath (encodeUtf8 (pack $ "/worker/" <> show id)) + $ setRequestPath (encodeUtf8 (pack $ "/workflow/" <> show id)) request + print response return () - <|> return () getPipelineHandler :: AuthRes -> PipelineId -> AppM GetPipelineResponse From 403ee278b7fadf23e674ae33f3e6ad1da7ca08aa Mon Sep 17 00:00:00 2001 From: GitBluub Date: Thu, 3 Mar 2022 16:42:03 +0100 Subject: [PATCH 5/6] feat: refresh route for worker --- api/src/Api/Worker.hs | 26 ++++++++++++++++++++++++-- api/src/Core/User.hs | 2 +- worker/src/index.ts | 23 ++++++++++++++--------- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/api/src/Api/Worker.hs b/api/src/Api/Worker.hs index b17dbb1..27fa3ed 100644 --- a/api/src/Api/Worker.hs +++ b/api/src/Api/Worker.hs @@ -19,14 +19,16 @@ import Utils (UserAuth, uncurry3) import Api.Pipeline (GetPipelineResponse, formatGetPipelineResponse, allPipelineHandler) import Data.Aeson (FromJSON, ToJSON, defaultOptions, eitherDecode) import Data.Aeson.TH (deriveJSON) -import Core.User (UserId(UserId), ExternalToken (ExternalToken)) +import Core.User (UserId(UserId), ExternalToken (ExternalToken), Service) import Control.Monad.IO.Class (MonadIO(liftIO)) import System.Environment.MrEnv (envAsString) import Repository (getUserById', getWorkflow', getWorkflows', triggerPipeline', errorPipeline') import Db.User (UserDB(userDBId, externalTokens)) import Data.Functor.Identity (Identity) import Db.Reaction (Reaction) +import Repository.User (updateTokens, getTokensByUserId, delTokens) import GHC.Generics (Generic) +import Data.Int (Int64) import Data.Text (Text) @@ -42,9 +44,16 @@ data GetPipelineWorkerResponse = GetPipelineWorkerResponse newtype ErrorBody = ErrorBody { error :: Text } +data RefreshBody = RefreshBody + { accessToken :: Text + , refreshToken :: Text + , expiresIn :: Int64 + } + $(deriveJSON defaultOptions ''WorkerUserData) $(deriveJSON defaultOptions ''GetPipelineWorkerResponse) $(deriveJSON defaultOptions ''ErrorBody) +$(deriveJSON defaultOptions ''RefreshBody) data WorkerAPI mode = WorkerAPI { get :: mode :- "workflow" :> Capture "id" PipelineId :> @@ -55,6 +64,8 @@ data WorkerAPI mode = WorkerAPI QueryParam "WORKER_API_KEY" String :> Get '[JSON] NoContent , error :: mode :- "error" :> Capture "id" PipelineId :> QueryParam "WORKER_API_KEY" String :> ReqBody '[JSON] ErrorBody :> Post '[JSON] NoContent + , refresh :: mode :- "auth" :> Capture "service" Service :> "refresh" :> Capture "id" UserId :> + QueryParam "WORKER_API_KEY" String :> ReqBody '[JSON] RefreshBody :> Post '[JSON] NoContent } deriving stock (Generic) @@ -98,6 +109,16 @@ errorHandler pId (Just key) (ErrorBody msg) = do else throwError err403 errorHandler _ _ _ = throwError err403 +refreshHandler :: Service -> UserId -> Maybe String -> RefreshBody -> AppM NoContent +refreshHandler service uid (Just key) (RefreshBody at rt ex) = do + k <- liftIO $ envAsString "WORKER_API_KEY" "" + if k == key then do + updateTokens uid $ ExternalToken at rt ex service + return NoContent + else throwError err403 +refreshHandler _ _ _ _ = throwError err403 + + workerHandler :: WorkerAPI (AsServerT AppM) workerHandler = WorkerAPI @@ -105,4 +126,5 @@ workerHandler = , all = allPipelineHandlerWorker , trigger = triggerHandler , error = errorHandler - } \ No newline at end of file + , refresh = refreshHandler + } diff --git a/api/src/Core/User.hs b/api/src/Core/User.hs index e79e327..3e2f59a 100644 --- a/api/src/Core/User.hs +++ b/api/src/Core/User.hs @@ -22,7 +22,7 @@ import Servant.Server.Experimental.Auth (AuthServerData) import Servant.Auth.JWT (ToJWT, FromJWT) newtype UserId = UserId {toInt64 :: Int64} - deriving newtype (DBEq, DBType, Eq, Show, Num, FromJSON, ToJSON) + deriving newtype (DBEq, DBType, Eq, Show, Num, FromJSON, ToJSON, FromHttpApiData) deriving stock (Generic) data Service = Github | Google | Spotify | Twitter | Discord | Anilist diff --git a/worker/src/index.ts b/worker/src/index.ts index ff5af0b..98c2b40 100644 --- a/worker/src/index.ts +++ b/worker/src/index.ts @@ -14,28 +14,33 @@ global.AbortController = AbortController; const app = express() const pipelineEvent = new EventEmitter(); -app.put("/workflow/:id", req => { +app.put("/workflow/:id", (req, res) => { console.log(`edit pipeline ${req.params.id}`); fetch(`${process.env["WORKER_API_URL"]}/workflow/${req.params.id}?WORKER_API_KEY=${process.env["WORKER_API_KEY"]}`) - .then(res => { - pipelineEvent.emit("event", pipelineFromApi(res.json())); - }); + .then(async res => { + pipelineEvent.emit("event", pipelineFromApi(await res.json())); + }) + .catch(console.error); + res.send() }); -app.post("/workflow/:id", req => { +app.post("/workflow/:id", (req, res) => { console.log(`new pipeline ${req.params.id}`); fetch(`${process.env["WORKER_API_URL"]}/workflow/${req.params.id}?WORKER_API_KEY=${process.env["WORKER_API_KEY"]}`) - .then(res => { - pipelineEvent.emit("event", pipelineFromApi(res.json())); - }); + .then(async res => { + pipelineEvent.emit("event", pipelineFromApi(await res.json())); + }) + .catch(console.error); + res.send() }); -app.delete("/workflow/:id", req => { +app.delete("/workflow/:id", (req, res) => { console.log(`delete pipeline ${req.params.id}`); pipelineEvent.emit("event", { id: req.params.id, type: PipelineType.Never, }); + res.send() }); app.listen(5000); From 87760f5ee43ed49df897a8eff35995dc29ab48fc Mon Sep 17 00:00:00 2001 From: GitBluub Date: Thu, 3 Mar 2022 17:00:01 +0100 Subject: [PATCH 6/6] rm: debug print --- api/src/Api/Pipeline.hs | 2 -- 1 file changed, 2 deletions(-) diff --git a/api/src/Api/Pipeline.hs b/api/src/Api/Pipeline.hs index 457e4fc..a5eba94 100644 --- a/api/src/Api/Pipeline.hs +++ b/api/src/Api/Pipeline.hs @@ -136,12 +136,10 @@ informWorker method id = do url <- envAsString "WORKER_URL" "worker/" request <- parseRequest url - print request response <- httpBS $ setRequestMethod method $ setRequestPath (encodeUtf8 (pack $ "/workflow/" <> show id)) request - print response return ()