packages feed

ms-graph-api 0.5.0.0 → 0.6.0.0

raw patch · 11 files changed

+195/−90 lines, 11 filesdep +validation-microdep −validation-selectivePVP ok

version bump matches the API change (PVP)

Dependencies added: validation-micro

Dependencies removed: validation-selective

API changes (from Hackage documentation)

- MSGraphAPI.Files.DriveItems: downloadFile :: Text -> Text -> AccessToken -> Req ByteString
- MSGraphAPI.Files.DriveItems: downloadFileMe :: Text -> AccessToken -> Req ByteString
- MSGraphAPI.User: User :: Text -> Text -> Text -> User
- MSGraphAPI.User: [uDisplayName] :: User -> Text
- MSGraphAPI.User: [uId] :: User -> Text
- MSGraphAPI.User: [uUserPrincipalName] :: User -> Text
- MSGraphAPI.User: data User
- MSGraphAPI.User: get :: Text -> AccessToken -> Req User
- MSGraphAPI.User: getMe :: AccessToken -> Req User
- MSGraphAPI.User: instance Data.Aeson.Types.FromJSON.FromJSON MSGraphAPI.User.User
- MSGraphAPI.User: instance GHC.Classes.Eq MSGraphAPI.User.User
- MSGraphAPI.User: instance GHC.Classes.Ord MSGraphAPI.User.User
- MSGraphAPI.User: instance GHC.Generics.Generic MSGraphAPI.User.User
- MSGraphAPI.User: instance GHC.Show.Show MSGraphAPI.User.User
+ MSGraphAPI.Files.DriveItem: DriveItem :: Text -> Text -> LocalTime -> DriveItem
+ MSGraphAPI.Files.DriveItem: [diId] :: DriveItem -> Text
+ MSGraphAPI.Files.DriveItem: [diLastModifiedDateTime] :: DriveItem -> LocalTime
+ MSGraphAPI.Files.DriveItem: [diName] :: DriveItem -> Text
+ MSGraphAPI.Files.DriveItem: data DriveItem
+ MSGraphAPI.Files.DriveItem: downloadFile :: Text -> Text -> AccessToken -> Req ByteString
+ MSGraphAPI.Files.DriveItem: downloadFileMe :: Text -> AccessToken -> Req ByteString
+ MSGraphAPI.Files.DriveItem: instance Data.Aeson.Types.FromJSON.FromJSON MSGraphAPI.Files.DriveItem.DriveItem
+ MSGraphAPI.Files.DriveItem: instance GHC.Classes.Eq MSGraphAPI.Files.DriveItem.DriveItem
+ MSGraphAPI.Files.DriveItem: instance GHC.Classes.Ord MSGraphAPI.Files.DriveItem.DriveItem
+ MSGraphAPI.Files.DriveItem: instance GHC.Generics.Generic MSGraphAPI.Files.DriveItem.DriveItem
+ MSGraphAPI.Files.DriveItem: instance GHC.Show.Show MSGraphAPI.Files.DriveItem.DriveItem
+ MSGraphAPI.Users.Group: Group :: Text -> Text -> Text -> Group
+ MSGraphAPI.Users.Group: [gDescription] :: Group -> Text
+ MSGraphAPI.Users.Group: [gDisplayName] :: Group -> Text
+ MSGraphAPI.Users.Group: [gId] :: Group -> Text
+ MSGraphAPI.Users.Group: data Group
+ MSGraphAPI.Users.Group: getGroupsDriveItems :: Text -> AccessToken -> Req (Collection DriveItem)
+ MSGraphAPI.Users.Group: getUserJoinedTeams :: Text -> AccessToken -> Req (Collection Group)
+ MSGraphAPI.Users.Group: instance Data.Aeson.Types.FromJSON.FromJSON MSGraphAPI.Users.Group.Group
+ MSGraphAPI.Users.Group: instance GHC.Classes.Eq MSGraphAPI.Users.Group.Group
+ MSGraphAPI.Users.Group: instance GHC.Classes.Ord MSGraphAPI.Users.Group.Group
+ MSGraphAPI.Users.Group: instance GHC.Generics.Generic MSGraphAPI.Users.Group.Group
+ MSGraphAPI.Users.Group: instance GHC.Show.Show MSGraphAPI.Users.Group.Group
+ MSGraphAPI.Users.User: User :: Text -> Text -> Text -> User
+ MSGraphAPI.Users.User: [uDisplayName] :: User -> Text
+ MSGraphAPI.Users.User: [uId] :: User -> Text
+ MSGraphAPI.Users.User: [uUserPrincipalName] :: User -> Text
+ MSGraphAPI.Users.User: data User
+ MSGraphAPI.Users.User: get :: Text -> AccessToken -> Req User
+ MSGraphAPI.Users.User: getMe :: AccessToken -> Req User
+ MSGraphAPI.Users.User: instance Data.Aeson.Types.FromJSON.FromJSON MSGraphAPI.Users.User.User
+ MSGraphAPI.Users.User: instance GHC.Classes.Eq MSGraphAPI.Users.User.User
+ MSGraphAPI.Users.User: instance GHC.Classes.Ord MSGraphAPI.Users.User.User
+ MSGraphAPI.Users.User: instance GHC.Generics.Generic MSGraphAPI.Users.User.User
+ MSGraphAPI.Users.User: instance GHC.Show.Show MSGraphAPI.Users.User.User

Files

CHANGELOG.md view
@@ -8,6 +8,10 @@  ## Unreleased +## 0.6.0.0++Depend on `validation-micro` rather than `validation-selective`.+ ## 0.5.0.0  Add 'getE', 'postE', 'tryReq' to pattern match against HTTP exceptions
README.md view
@@ -7,16 +7,25 @@ ![main](https://github.com/unfoldml/ms-graph-api/actions/workflows/haskell.yml/badge.svg?branch=main)  -## Description+## Introduction -This library provides both the client interface and authorization infrastructure to integrate with Microsoft infrastructure, e.g. using ActiveDirectory as an OAuth2 identity provider.+This library provides both the client interface (under the `MSGraphAPI` namespace) as well as helpers to integrate with Microsoft infrastructure, e.g. using ActiveDirectory as an OAuth2 identity provider. +With the provided auth functions (see `Network.OAuth2.Session`) you can easily implement OAuth2 for your application, and the resulting token store is thread-safe and automatically renews before expiring.+ ## Status -This library is still in development, so expect missing funcionality.+This library is still in development, so expect missing functionality. If there's anything you would like to see added, feel free to [open an issue](https://github.com/unfoldml/ms-graph-api/issues/new).+In general, since the MS Graph API is quite large, features will be added to this library on a need basis.++## Evolution of the library+ Some breaking changes might also be introduced as the library matures.++We adhere to a simplified version of the [Package Versioning Policy](https://pvp.haskell.org/): breaking changes are signaled by increasing the major version number (e.g. 0.x -> 1.x ).+  ## Copyright 
ms-graph-api.cabal view
@@ -1,5 +1,5 @@ name:                ms-graph-api-version:             0.5.0.0+version:             0.6.0.0 synopsis:            Microsoft Graph API description:         Bindings to the Microsoft Graph API homepage:            https://github.com/unfoldml/ms-graph-api@@ -20,8 +20,10 @@   hs-source-dirs:      src   exposed-modules:                             MSGraphAPI.User+                       MSGraphAPI.Users.User+                       MSGraphAPI.Users.Group                        MSGraphAPI.Drive-                       MSGraphAPI.Files.DriveItems+                       MSGraphAPI.Files.DriveItem                        Network.OAuth2.Provider.AzureAD                        Network.OAuth2.Session                        MSGraphAPI.Internal.Common@@ -45,7 +47,7 @@                      , transformers >= 0.5                      , unliftio                      , uri-bytestring-                     , validation-selective+                     , validation-micro                      , wai                      , warp   ghc-options:         -Wall
+ src/MSGraphAPI/Files/DriveItem.hs view
@@ -0,0 +1,46 @@+module MSGraphAPI.Files.DriveItem where++import GHC.Generics (Generic(..))++-- aeson+import qualified Data.Aeson as A (ToJSON(..), FromJSON(..), genericParseJSON)+-- bytestring+import qualified Data.ByteString.Lazy as LBS (ByteString)+-- hoauth+import Network.OAuth.OAuth2.Internal (AccessToken(..))+-- req+import Network.HTTP.Req (Req)+-- text+import Data.Text (Text, pack, unpack)+-- time+import Data.Time (LocalTime)++import qualified MSGraphAPI.Internal.Common as MSG (get, getLbs, post, Collection, aesonOptions)++data DriveItem = DriveItem {+  diId :: Text+  , diName :: Text+  , diLastModifiedDateTime :: LocalTime+                           } deriving (Eq, Ord, Show, Generic)+instance A.FromJSON DriveItem where+  parseJSON = A.genericParseJSON (MSG.aesonOptions "di")+++-- | download a complete file from user's directory+--+-- @GET \/me\/drive\/items\/{item-id}\/content@+--+-- https://learn.microsoft.com/en-us/graph/api/driveitem-get-content?view=graph-rest-1.0&tabs=http#request+downloadFileMe :: Text -- ^ item ID+               -> AccessToken -> Req LBS.ByteString+downloadFileMe itemId = MSG.getLbs ["me", "drive", "items", itemId, "content"] mempty++-- | download a file from a drive+--+-- @GET \/drives\/{drive-id}\/items\/{item-id}\/content@+--+-- https://learn.microsoft.com/en-us/graph/api/driveitem-get-content?view=graph-rest-1.0&tabs=http#request+downloadFile :: Text -- ^ drive ID+             -> Text -- ^ file ID+             -> AccessToken -> Req LBS.ByteString+downloadFile did itemId = MSG.getLbs ["drives", did, "items", itemId, "content"] mempty
− src/MSGraphAPI/Files/DriveItems.hs
@@ -1,35 +0,0 @@-module MSGraphAPI.Files.DriveItems where--import GHC.Generics (Generic(..))---- aeson-import qualified Data.Aeson as A (ToJSON(..), FromJSON(..), genericParseJSON)--- bytestring-import qualified Data.ByteString.Lazy as LBS (ByteString)--- hoauth-import Network.OAuth.OAuth2.Internal (AccessToken(..))--- req-import Network.HTTP.Req (Req)--- text-import Data.Text (Text, pack, unpack)--import qualified MSGraphAPI.Internal.Common as MSG (get, getLbs, post, Collection, aesonOptions)---- | download a complete file from user's directory------ @GET \/me\/drive\/items\/{item-id}\/content@------ https://learn.microsoft.com/en-us/graph/api/driveitem-get-content?view=graph-rest-1.0&tabs=http#request-downloadFileMe :: Text -- ^ item ID-               -> AccessToken -> Req LBS.ByteString-downloadFileMe itemId = MSG.getLbs ["me", "drive", "items", itemId, "content"] mempty---- | download a file from a drive------ @GET \/drives\/{drive-id}\/items\/{item-id}\/content@------ https://learn.microsoft.com/en-us/graph/api/driveitem-get-content?view=graph-rest-1.0&tabs=http#request-downloadFile :: Text -- ^ drive ID-             -> Text -- ^ file ID-             -> AccessToken -> Req LBS.ByteString-downloadFile did itemId = MSG.getLbs ["drives", did, "items", itemId, "content"] mempty
src/MSGraphAPI/User.hs view
@@ -1,57 +1,35 @@ module MSGraphAPI.User where -import GHC.Generics (Generic(..)) -import Data.List (sort, sortBy, stripPrefix, uncons)-import Data.Maybe (listToMaybe, fromMaybe)--- import Data.Ord (comparing)-import Data.Char (toLower)-import Data.String (IsString(..))-import Data.Word (Word) --- aeson-import qualified Data.Aeson as A (ToJSON(..), FromJSON(..), genericParseJSON, defaultOptions, Options(..), withObject, withText, (.:), (.:?), object, (.=), Key, Value, camelTo2)-import qualified Data.Aeson.Types as A (Parser, Object)--- import qualified Data.Aeson.KeyMap as AKV (KeyMap, lookup)--- containers--- import qualified Data.Map as M (Map, empty, insert, lookup)--- hoauth-import Network.OAuth.OAuth2.Internal (AccessToken(..))--- req-import Network.HTTP.Req (Req)--- text-import Data.Text (Text, pack, unpack)--- time-import Data.Time.LocalTime (ZonedTime, zonedTimeToLocalTime)+-- import Data.List (sort, sortBy, stripPrefix, uncons)+-- import Data.Maybe (listToMaybe, fromMaybe)+-- -- import Data.Ord (comparing)+-- import Data.Char (toLower)+-- import Data.String (IsString(..))+-- import Data.Word (Word) -import qualified MSGraphAPI.Internal.Common as MSG (get, post, aesonOptions)+-- -- aeson+-- import qualified Data.Aeson as A (ToJSON(..), FromJSON(..), genericParseJSON, defaultOptions, Options(..), withObject, withText, (.:), (.:?), object, (.=), Key, Value, camelTo2)+-- import qualified Data.Aeson.Types as A (Parser, Object)+-- -- import qualified Data.Aeson.KeyMap as AKV (KeyMap, lookup)+-- -- containers+-- -- import qualified Data.Map as M (Map, empty, insert, lookup)+-- -- hoauth+-- import Network.OAuth.OAuth2.Internal (AccessToken(..))+-- -- req+-- import Network.HTTP.Req (Req)+-- -- text+-- import Data.Text (Text, pack, unpack)+-- -- time+-- import Data.Time.LocalTime (ZonedTime, zonedTimeToLocalTime) --- | Get user information------ @GET \/users\/{user-id}@------ https://learn.microsoft.com/en-us/graph/api/user-get?view=graph-rest-1.0&tabs=http#request-get :: Text -- ^ user id-    -> AccessToken -> Req User-get uid = MSG.get ["users", uid] mempty+-- import qualified MSGraphAPI.Internal.Common as MSG (get, post, aesonOptions)+-- -- import MSGraphAPI.Users.User (User) --- | Get information on signed-in user------ Calling the \/me endpoint requires a signed-in user and therefore a delegated permission. Application permissions are not supported when using the \/me endpoint.------ @GET \/me@------ https://learn.microsoft.com/en-us/graph/api/user-get?view=graph-rest-1.0&tabs=http#request-1-getMe :: AccessToken -> Req User-getMe = MSG.get ["me"] mempty  -data User = User {-  uId :: Text-  , uUserPrincipalName :: Text-  , uDisplayName :: Text-                 } deriving (Eq, Ord, Show, Generic)-instance A.FromJSON User where-  parseJSON = A.genericParseJSON (MSG.aesonOptions "u")++  
+ src/MSGraphAPI/Users/Group.hs view
@@ -0,0 +1,55 @@+-- | User+module MSGraphAPI.Users.Group where++import GHC.Generics (Generic(..))++-- aeson+import qualified Data.Aeson as A (ToJSON(..), FromJSON(..), eitherDecode, genericParseJSON, defaultOptions, Options(..), withObject, withText, (.:), (.:?), object, (.=))+-- hoauth+import Network.OAuth.OAuth2.Internal (AccessToken(..))+-- req+import Network.HTTP.Req (Req)+-- text+import Data.Text (Text, pack, unpack)++import qualified MSGraphAPI.Internal.Common as MSG (Collection(..), get, post, aesonOptions)+import MSGraphAPI.Files.DriveItem (DriveItem)++-- | Groups are collections of principals with shared access to resources in Microsoft services or in your app. Different principals such as users, other groups, devices, and applications can be part of groups. +--+-- httpstea://learn.microsoft.com/en-us/graph/api/resources/groups-overview?view=graph-rest-1.0&tabs=http+data Group = Group {+  gId :: Text+  , gDisplayName :: Text+  , gDescription :: Text+                   } deriving (Eq, Ord, Show, Generic)+instance A.FromJSON Group where+  parseJSON = A.genericParseJSON (MSG.aesonOptions "g")++-- | Get the teams in Microsoft Teams that the user is a direct member of.+--+-- @GET \/users\/{id | user-principal-name}\/joinedTeams@+--+-- https://learn.microsoft.com/en-us/graph/api/user-list-joinedteams?view=graph-rest-1.0&tabs=http+getUserJoinedTeams :: Text -- ^ User ID+                   -> AccessToken -> Req (MSG.Collection Group)+getUserJoinedTeams uid = MSG.get ["users", uid, "joinedTeams"] mempty++-- | Get the 'DriveItem's in the 'Group' storage, starting from the root item+--+-- @GET \/groups\/{group-id}\/drive\/root\/children@+--+-- https://learn.microsoft.com/en-us/graph/api/driveitem-list-children?view=graph-rest-1.0&tabs=http+getGroupsDriveItems :: Text -- ^ Group ID+                    -> AccessToken -> Req (MSG.Collection DriveItem)+getGroupsDriveItems gid = MSG.get ["groups", gid, "drive", "root", "children"] mempty+++-- data X = X { xName :: Text } deriving (Eq, Ord, Show, Generic)+-- instance A.FromJSON X where+--   parseJSON = A.genericParseJSON (MSG.aesonOptions "x")++-- pt0 :: Either String (MSG.Collection DriveItem)+-- pt0 = A.eitherDecode t0+--   where+--     t0 = "{\r\n  \"value\": [\r\n    {\"name\": \"myfile.jpg\"  },\r\n    {\"name\": \"Documents\" },\r\n    {\"name\": \"Photos\" },\r\n    {\"name\": \"my sheet(1).xlsx\"}\r\n  ]\r\n}"
+ src/MSGraphAPI/Users/User.hs view
@@ -0,0 +1,44 @@+-- | User+module MSGraphAPI.Users.User where++import GHC.Generics (Generic(..))++-- aeson+import qualified Data.Aeson as A (ToJSON(..), FromJSON(..), genericParseJSON, defaultOptions, Options(..), withObject, withText, (.:), (.:?), object, (.=))+-- hoauth+import Network.OAuth.OAuth2.Internal (AccessToken(..))+-- req+import Network.HTTP.Req (Req)+-- text+import Data.Text (Text, pack, unpack)++import qualified MSGraphAPI.Internal.Common as MSG (get, post, aesonOptions)+++data User = User {+  uId :: Text+  , uUserPrincipalName :: Text+  , uDisplayName :: Text+                 } deriving (Eq, Ord, Show, Generic)+instance A.FromJSON User where+  parseJSON = A.genericParseJSON (MSG.aesonOptions "u")+++-- | Get user information+--+-- @GET \/users\/{user-id}@+--+-- https://learn.microsoft.com/en-us/graph/api/user-get?view=graph-rest-1.0&tabs=http#request+get :: Text -- ^ user id+    -> AccessToken -> Req User+get uid = MSG.get ["users", uid] mempty++-- | Get information on signed-in user+--+-- Calling the \/me endpoint requires a signed-in user and therefore a delegated permission. Application permissions are not supported when using the \/me endpoint.+--+-- @GET \/me@+--+-- https://learn.microsoft.com/en-us/graph/api/user-get?view=graph-rest-1.0&tabs=http#request-1+getMe :: AccessToken -> Req User+getMe = MSG.get ["me"] mempty
src/Network/OAuth2/JWT.hs view
@@ -26,8 +26,8 @@ import qualified Data.Text as T (Text, unpack) -- time import Data.Time (UTCTime(..), NominalDiffTime, getCurrentTime, fromGregorian, addUTCTime, diffUTCTime)--- validation-selective-import Validation (Validation(..), failure, validationToEither, maybeToSuccess)+-- validation-micro+import Validation.Micro (Validation(..), failure, validationToEither, maybeToSuccess)   -- | 'sub' field
src/Network/OAuth2/Provider/AzureAD.hs view
@@ -45,6 +45,8 @@                          }  -- | NB : scopes @openid@ and @offline_access@ are ALWAYS requested since the library assumes we have access to refresh tokens and ID tokens+--+-- Reference on Microsoft Graph permissions : https://learn.microsoft.com/en-us/graph/permissions-reference azureADApp :: OAuthCfg -- ^ OAuth configuration            -> IdpApplication 'AuthorizationCode AzureAD azureADApp (OAuthCfg appname clid sec scopes authstate reduri) = defaultAzureADApp{
src/Network/OAuth2/Session.hs view
@@ -65,7 +65,7 @@ -- uri-bytestring import URI.ByteString (URI) -- validation-selective-import Validation (Validation, failure, validationToEither)+import Validation.Micro (Validation, failure, validationToEither)  import Network.OAuth2.Provider.AzureAD (OAuthCfg, azureADApp, AzureAD) import Network.OAuth2.JWT (jwtClaims, UserSub(..), userSub, ApiAudience, apiAudience, decValidSub, decValidExp, decValidNbf, JWTException(..))