Merge branch 'master' of github.com:AnonymusRaccoon/Aeris into feat/debug-tools

This commit is contained in:
Zoe Roux
2022-03-03 17:48:26 +01:00
8 changed files with 65 additions and 22 deletions
+3
View File
@@ -77,6 +77,7 @@ library
, network
, opaleye >=0.9.0.0 && <0.9.1.0
, rel8
, scientific ==0.3.7.0
, servant
, servant-auth
, servant-auth-server
@@ -119,6 +120,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
@@ -165,6 +167,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
+1
View File
@@ -34,6 +34,7 @@ dependencies:
- servant-errors
- data-default
- bytestring
- scientific == 0.3.7.0
- network
- base64
- text
+1 -3
View File
@@ -138,11 +138,9 @@ informWorker method id =
request <- parseRequest url
response <- httpBS
$ setRequestMethod method
$ addRequestHeader "Accept" "application/json"
$ setRequestPath (encodeUtf8 (pack $ "/worker/" <> show id))
$ setRequestPath (encodeUtf8 (pack $ "/workflow/" <> show id))
request
return ()
<|> return ()
getPipelineHandler :: AuthRes -> PipelineId -> AppM GetPipelineResponse
+24 -2
View File
@@ -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
}
, refresh = refreshHandler
}
+13 -7
View File
@@ -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
+1 -1
View File
@@ -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
+8
View File
@@ -19,6 +19,8 @@ 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)
import Data.Scientific ( toBoundedInteger )
mapInd :: (a -> Int -> b) -> [a] -> [b]
mapInd f l = zipWith f l [0 ..]
@@ -28,6 +30,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) -> toBoundedInteger $ x
_ -> Nothing
uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d
uncurry3 f (a, b, c) = f a b c
+14 -9
View File
@@ -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);