mirror of
https://github.com/zoriya/Aeris.git
synced 2026-06-09 13:01:12 +00:00
Merge branch 'master' of github.com:AnonymusRaccoon/Aeris into mobile_client
This commit is contained in:
+29
-14
@@ -19,17 +19,16 @@ import qualified Data.ByteString.Char8 as B8
|
||||
import Servant.Auth.Server (AuthResult(Authenticated))
|
||||
import System.Environment.MrEnv (envAsString)
|
||||
|
||||
oauthHandler :: AuthRes -> Service -> Maybe String -> Maybe String -> AppM NoContent
|
||||
oauthHandler _ _ Nothing _ = throwError err400
|
||||
oauthHandler _ _ _ Nothing = throwError err400
|
||||
oauthHandler (Authenticated (User uid _ _)) service (Just code) (Just redirect) = do
|
||||
tokens <- liftIO $ getOauthTokens service code redirect
|
||||
oauthHandler :: AuthRes -> Service -> Maybe String -> AppM NoContent
|
||||
oauthHandler _ _ Nothing = throwError err400
|
||||
oauthHandler (Authenticated (User uid _ _)) service (Just code) = do
|
||||
tokens <- liftIO $ getOauthTokens service code
|
||||
case tokens of
|
||||
Nothing -> throwError err403
|
||||
Just t -> do
|
||||
updateTokens uid t
|
||||
return NoContent
|
||||
oauthHandler _ service (Just code) (Just redirect) = throwError err401
|
||||
oauthHandler _ service (Just code) = throwError err401
|
||||
|
||||
oauthDelHandler :: AuthRes -> Service -> AppM NoContent
|
||||
oauthDelHandler (Authenticated (User uid _ _)) service = do
|
||||
@@ -41,28 +40,34 @@ urlHandler :: Service -> Maybe String -> AppM NoContent
|
||||
urlHandler _ Nothing = throwError err400
|
||||
urlHandler Anilist (Just r) = do
|
||||
clientId <- liftIO $ envAsString "ANILIST_CLIENT_ID" ""
|
||||
backRedirect <- liftIO $ envAsString "BACK_REDIRECT_URL" ""
|
||||
throwError $ err302 { errHeaders =
|
||||
[("Location", B8.pack $ "https://anilist.co/api/v2/oauth/authorize?client_id=" ++ clientId ++ "&response_type=code&redirect_uri=" ++ r)] }
|
||||
[("Location", B8.pack $ "https://anilist.co/api/v2/oauth/authorize?client_id=" ++ clientId ++ "&response_type=code&redirect_uri=" ++ backRedirect ++ "&state=" ++ r)] }
|
||||
urlHandler Discord (Just r) = do
|
||||
clientId <- liftIO $ envAsString "DISCORD_CLIENT_ID" ""
|
||||
backRedirect <- liftIO $ envAsString "BACK_REDIRECT_URL" ""
|
||||
throwError $ err302 { errHeaders =
|
||||
[("Location", B8.pack $ "https://discord.com/api/oauth2/authorize?response_type=code&scope=identify&client_id=" ++ clientId ++ "&response_type=code&redirect_uri=" ++ r)] }
|
||||
[("Location", B8.pack $ "https://discord.com/api/oauth2/authorize?response_type=code&scope=identify&client_id=" ++ clientId ++ "&response_type=code&redirect_uri=" ++ backRedirect ++ "&state=" ++ r)] }
|
||||
urlHandler Google (Just r) = do
|
||||
clientId <- liftIO $ envAsString "GOOGLE_CLIENT_ID" ""
|
||||
backRedirect <- liftIO $ envAsString "BACK_REDIRECT_URL" ""
|
||||
throwError $ err302 { errHeaders =
|
||||
[("Location", B8.pack $ "https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/youtube.force-ssl&access_type=offline&include_granted_scopes=true&response_type=code&state=state&client_id=" ++ clientId ++ "&redirect_uri=" ++ r)] }
|
||||
[("Location", B8.pack $ "https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/youtube.force-ssl&access_type=offline&prompt=consent&include_granted_scopes=true&response_type=code&client_id=" ++ clientId ++ "&redirect_uri=" ++ backRedirect ++ "&state=" ++ r)] }
|
||||
urlHandler Twitter (Just r) = do
|
||||
clientId <- liftIO $ envAsString "TWITTER_CLIENT_ID" ""
|
||||
backRedirect <- liftIO $ envAsString "BACK_REDIRECT_URL" ""
|
||||
throwError $ err302 { errHeaders =
|
||||
[("Location", B8.pack $ "https://twitter.com/i/oauth2/authorize?response_type=code&scope=like.write like.read follows.read follows.write offline.access tweet.read tweet.write&state=state&code_challenge=challenge&code_challenge_method=plain&client_id=" ++ clientId ++ "&redirect_uri=" ++ r)] }
|
||||
[("Location", B8.pack $ "https://twitter.com/i/oauth2/authorize?response_type=code&scope=like.write like.read follows.read follows.write offline.access tweet.read tweet.write&code_challenge=challenge&code_challenge_method=plain&client_id=" ++ clientId ++ "&redirect_uri=" ++ backRedirect ++ "&state=" ++ r)] }
|
||||
urlHandler Spotify (Just r) = do
|
||||
clientId <- liftIO $ envAsString "SPOTIFY_CLIENT_ID" ""
|
||||
backRedirect <- liftIO $ envAsString "BACK_REDIRECT_URL" ""
|
||||
throwError $ err302 { errHeaders =
|
||||
[("Location", B8.pack $ "https://accounts.spotify.com/authorize?response_type=code&state=state&scope=user-library-read&client_id=" ++ clientId ++ "&redirect_uri=" ++ r)] }
|
||||
[("Location", B8.pack $ "https://accounts.spotify.com/authorize?response_type=code&scope=user-library-read&client_id=" ++ clientId ++ "&redirect_uri=" ++ backRedirect ++ "&state=" ++ r)] }
|
||||
urlHandler Github (Just r) = do
|
||||
clientId <- liftIO $ envAsString "GITHUB_CLIENT_ID" ""
|
||||
backRedirect <- liftIO $ envAsString "BACK_REDIRECT_URL" ""
|
||||
throwError $ err302 { errHeaders =
|
||||
[("Location", B8.pack $ "https://github.com/login/oauth/authorize?response_type=code&client_id=" ++ clientId ++ "&redirect_uri=" ++ r)] }
|
||||
[("Location", B8.pack $ "https://github.com/login/oauth/authorize?response_type=code&scope=repo&client_id=" ++ clientId ++ "&redirect_uri=" ++ backRedirect ++ "&state=" ++ r)] }
|
||||
|
||||
servicesHandler :: AuthRes -> AppM [String]
|
||||
servicesHandler (Authenticated (User uid name slug)) = do
|
||||
@@ -70,13 +75,23 @@ servicesHandler (Authenticated (User uid name slug)) = do
|
||||
return $ fmap (show . service) tokens
|
||||
servicesHandler _ = throwError err401
|
||||
|
||||
type OauthAPI = UserAuth :> Capture "service" Service :> QueryParam "code" String :> QueryParam "redirect_uri" String :> Get '[JSON] NoContent
|
||||
redirectHandler :: Maybe String -> Maybe String -> AppM NoContent
|
||||
redirectHandler Nothing _ = return NoContent
|
||||
redirectHandler _ Nothing = return NoContent
|
||||
redirectHandler (Just code) (Just state) = do
|
||||
throwError $ err302 { errHeaders =
|
||||
[("Location", B8.pack $ state ++ "?code=" ++ code )] }
|
||||
return NoContent
|
||||
|
||||
type OauthAPI = UserAuth :> Capture "service" Service :> QueryParam "code" String :> Get '[JSON] NoContent
|
||||
:<|> UserAuth :> Capture "service" Service :> Delete '[JSON] NoContent
|
||||
:<|> Capture "service" Service :> "url" :> QueryParam "redirect_uri" String :> Get '[JSON] NoContent
|
||||
:<|> UserAuth :> "services" :> Get '[JSON] [String]
|
||||
|
||||
:<|> "redirect" :> QueryParam "code" String :> QueryParam "state" String :> Get '[JSON] NoContent
|
||||
|
||||
oauth :: ServerT OauthAPI AppM
|
||||
oauth = oauthHandler
|
||||
:<|> oauthDelHandler
|
||||
:<|> urlHandler
|
||||
:<|> servicesHandler
|
||||
:<|> redirectHandler
|
||||
|
||||
+25
-32
@@ -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, lookupObjInt)
|
||||
import Utils (lookupObjString)
|
||||
import Data.ByteString.Base64
|
||||
data OAuth2Conf = OAuth2Conf
|
||||
{ oauthClientId :: String
|
||||
@@ -40,8 +40,8 @@ getGithubConfig =
|
||||
<*> envAsString "GITHUB_SECRET" ""
|
||||
<*> pure "https://github.com/login/oauth/access_token"
|
||||
|
||||
getGithubTokens :: String -> String -> IO (Maybe ExternalToken)
|
||||
getGithubTokens code _ = do
|
||||
getGithubTokens :: String -> IO (Maybe ExternalToken)
|
||||
getGithubTokens code = do
|
||||
gh <- getGithubConfig
|
||||
let endpoint = tokenEndpoint code gh
|
||||
request' <- parseRequest endpoint
|
||||
@@ -59,9 +59,7 @@ getGithubTokens code _ = do
|
||||
Left _ -> Nothing
|
||||
Right obj -> do
|
||||
access <- lookupObjString obj "access_token"
|
||||
refresh <- lookupObjString obj "refresh_token"
|
||||
expires_in <- lookupObjInt obj "expires_in"
|
||||
Just $ ExternalToken (pack access) (pack refresh) expires_in Github
|
||||
Just $ ExternalToken (pack access) "" 0 Github
|
||||
|
||||
-- DISCORD
|
||||
getDiscordConfig :: IO OAuth2Conf
|
||||
@@ -71,8 +69,8 @@ getDiscordConfig =
|
||||
<*> envAsString "DISCORD_SECRET" ""
|
||||
<*> pure "https://discord.com/api/oauth2/token"
|
||||
|
||||
getDiscordTokens :: String -> String -> IO (Maybe ExternalToken)
|
||||
getDiscordTokens code redirect = do
|
||||
getDiscordTokens :: String -> IO (Maybe ExternalToken)
|
||||
getDiscordTokens code = do
|
||||
cfg <- getDiscordConfig
|
||||
let endpoint = tokenEndpoint code cfg
|
||||
request' <- parseRequest endpoint
|
||||
@@ -84,7 +82,7 @@ getDiscordTokens code redirect = do
|
||||
, ("client_secret", B8.pack . oauthClientSecret $ cfg)
|
||||
, ("code", B8.pack code)
|
||||
, ("grant_type", "authorization_code")
|
||||
, ("redirect_uri", B8.pack redirect)
|
||||
, ("redirect_uri", "http://localhost:8080/auth/redirect")
|
||||
]
|
||||
request'
|
||||
response <- httpJSONEither request
|
||||
@@ -93,8 +91,7 @@ getDiscordTokens code redirect = do
|
||||
Right obj -> do
|
||||
access <- lookupObjString obj "access_token"
|
||||
refresh <- lookupObjString obj "refresh_token"
|
||||
expires_in <- lookupObjInt obj "expires_in"
|
||||
Just $ ExternalToken (pack access) (pack refresh) expires_in Discord
|
||||
Just $ ExternalToken (pack access) (pack refresh) 0 Discord
|
||||
|
||||
-- GOOGLE
|
||||
getGoogleConfig :: IO OAuth2Conf
|
||||
@@ -104,8 +101,8 @@ getGoogleConfig =
|
||||
<*> envAsString "GOOGLE_SECRET" ""
|
||||
<*> pure "https://oauth2.googleapis.com/token"
|
||||
|
||||
getGoogleTokens :: String -> String -> IO (Maybe ExternalToken)
|
||||
getGoogleTokens code redirect = do
|
||||
getGoogleTokens :: String -> IO (Maybe ExternalToken)
|
||||
getGoogleTokens code = do
|
||||
cfg <- getGoogleConfig
|
||||
let endpoint = tokenEndpoint code cfg
|
||||
request' <- parseRequest endpoint
|
||||
@@ -117,7 +114,7 @@ getGoogleTokens code redirect = do
|
||||
, ("client_secret", B8.pack . oauthClientSecret $ cfg)
|
||||
, ("code", B8.pack code)
|
||||
, ("grant_type", "authorization_code")
|
||||
, ("redirect_uri", B8.pack redirect)
|
||||
, ("redirect_uri", "http://localhost:8080/auth/redirect")
|
||||
]
|
||||
request'
|
||||
response <- httpJSONEither request
|
||||
@@ -126,8 +123,7 @@ getGoogleTokens code redirect = do
|
||||
Right obj -> do
|
||||
access <- lookupObjString obj "access_token"
|
||||
refresh <- lookupObjString obj "refresh_token"
|
||||
expires_in <- lookupObjInt obj "expires_in"
|
||||
Just $ ExternalToken (pack access) (pack refresh) expires_in Google
|
||||
Just $ ExternalToken (pack access) (pack refresh) 0 Google
|
||||
|
||||
-- SPOTIFY
|
||||
getSpotifyConfig :: IO OAuth2Conf
|
||||
@@ -137,8 +133,8 @@ getSpotifyConfig =
|
||||
<*> envAsString "SPOTIFY_SECRET" ""
|
||||
<*> pure "https://accounts.spotify.com/api/token"
|
||||
|
||||
getSpotifyTokens :: String -> String -> IO (Maybe ExternalToken)
|
||||
getSpotifyTokens code redirect = do
|
||||
getSpotifyTokens :: String -> IO (Maybe ExternalToken)
|
||||
getSpotifyTokens code = do
|
||||
cfg <- getSpotifyConfig
|
||||
|
||||
let basicAuth = encodeBase64 $ B8.pack $ oauthClientId cfg ++ ":" ++ oauthClientSecret cfg
|
||||
@@ -151,7 +147,7 @@ getSpotifyTokens code redirect = do
|
||||
setRequestBodyURLEncoded
|
||||
[ ("code", B8.pack code)
|
||||
, ("grant_type", "authorization_code")
|
||||
, ("redirect_uri", B8.pack redirect)
|
||||
, ("redirect_uri", "http://localhost:8080/auth/redirect")
|
||||
]
|
||||
request'
|
||||
response <- httpJSONEither request
|
||||
@@ -160,8 +156,7 @@ getSpotifyTokens code redirect = do
|
||||
Right obj -> do
|
||||
access <- lookupObjString obj "access_token"
|
||||
refresh <- lookupObjString obj "refresh_token"
|
||||
expires_in <- lookupObjInt obj "expires_in"
|
||||
Just $ ExternalToken (pack access) (pack refresh) expires_in Spotify
|
||||
Just $ ExternalToken (pack access) (pack refresh) 0 Spotify
|
||||
|
||||
-- TWITTER
|
||||
getTwitterConfig :: IO OAuth2Conf
|
||||
@@ -171,8 +166,8 @@ getTwitterConfig =
|
||||
<*> envAsString "TWITTER_SECRET" ""
|
||||
<*> pure "https://api.twitter.com/2/oauth2/token"
|
||||
|
||||
getTwitterTokens :: String -> String -> IO (Maybe ExternalToken)
|
||||
getTwitterTokens code redirect = do
|
||||
getTwitterTokens :: String -> IO (Maybe ExternalToken)
|
||||
getTwitterTokens code = do
|
||||
cfg <- getTwitterConfig
|
||||
let basicAuth = encodeBase64 $ B8.pack $ "Basic " ++ oauthClientId cfg ++ ":" ++ oauthClientSecret cfg
|
||||
let endpoint = tokenEndpoint code cfg
|
||||
@@ -184,7 +179,7 @@ getTwitterTokens code redirect = do
|
||||
setRequestBodyURLEncoded
|
||||
[ ("code", B8.pack code)
|
||||
, ("grant_type", "authorization_code")
|
||||
, ("redirect_uri", B8.pack redirect)
|
||||
, ("redirect_uri", "http://localhost:8080/auth/redirect")
|
||||
, ("code_verifier", "challenge")
|
||||
]
|
||||
request'
|
||||
@@ -194,8 +189,7 @@ getTwitterTokens code redirect = do
|
||||
Right obj -> do
|
||||
access <- lookupObjString obj "access_token"
|
||||
refresh <- lookupObjString obj "refresh_token"
|
||||
expires_in <- lookupObjInt obj "expires_in"
|
||||
Just $ ExternalToken (pack access) (pack refresh) expires_in Twitter
|
||||
Just $ ExternalToken (pack access) (pack refresh) 0 Twitter
|
||||
|
||||
-- ANILIST
|
||||
getAnilistConfig :: IO OAuth2Conf
|
||||
@@ -205,8 +199,8 @@ getAnilistConfig =
|
||||
<*> envAsString "ANILIST_SECRET" ""
|
||||
<*> pure "https://anilist.co/api/v2/oauth/token"
|
||||
|
||||
getAnilistTokens :: String -> String -> IO (Maybe ExternalToken)
|
||||
getAnilistTokens code redirect = do
|
||||
getAnilistTokens :: String -> IO (Maybe ExternalToken)
|
||||
getAnilistTokens code = do
|
||||
cfg <- getAnilistConfig
|
||||
let endpoint = tokenEndpoint code cfg
|
||||
request' <- parseRequest endpoint
|
||||
@@ -218,7 +212,7 @@ getAnilistTokens code redirect = do
|
||||
, ("client_secret", B8.pack . oauthClientSecret $ cfg)
|
||||
, ("code", B8.pack code)
|
||||
, ("grant_type", "authorization_code")
|
||||
, ("redirect_uri", B8.pack redirect)
|
||||
, ("redirect_uri", "http://localhost:8080/auth/redirect")
|
||||
]
|
||||
request'
|
||||
response <- httpJSONEither request
|
||||
@@ -227,14 +221,13 @@ getAnilistTokens code redirect = do
|
||||
Right obj -> do
|
||||
access <- lookupObjString obj "access_token"
|
||||
refresh <- lookupObjString obj "refresh_token"
|
||||
expires_in <- lookupObjInt obj "expires_in"
|
||||
Just $ ExternalToken (pack access) (pack refresh) expires_in Anilist
|
||||
Just $ ExternalToken (pack access) (pack refresh) 0 Anilist
|
||||
|
||||
|
||||
|
||||
|
||||
-- General
|
||||
getOauthTokens :: Service -> String -> String -> IO (Maybe ExternalToken)
|
||||
getOauthTokens :: Service -> String -> IO (Maybe ExternalToken)
|
||||
getOauthTokens Github = getGithubTokens
|
||||
getOauthTokens Discord = getDiscordTokens
|
||||
getOauthTokens Spotify = getSpotifyTokens
|
||||
|
||||
Reference in New Issue
Block a user