From 5633a7cbde45a077228f9c689e06266809b58a64 Mon Sep 17 00:00:00 2001 From: Glendon Solsberry Date: Thu, 14 Nov 2019 12:07:51 -0500 Subject: [PATCH 1/6] Allow the user to specify the tokenMode --- src/MSGraph.php | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/MSGraph.php b/src/MSGraph.php index 499fa96..56158b6 100644 --- a/src/MSGraph.php +++ b/src/MSGraph.php @@ -13,11 +13,14 @@ use Microsoft\Graph\Graph; use Microsoft\Graph\Model; -class MSGraph extends AbstractAdapter +class MSGraph extends AbstractAdapter { const MODE_SHAREPOINT = 'sharepoint'; const MODE_ONEDRIVE = 'onedrive'; + const OAUTH_MODE_APP = 'oauth_app'; + const OAUTH_MODE_USER = 'oauth_user'; + // Our mode, if sharepoint or onedrive private $mode; // Our Microsoft Graph Client @@ -31,28 +34,35 @@ class MSGraph extends AbstractAdapter // Our url prefix to be used for most file operations. This gets created in our constructor private $prefix; - public function __construct($appId, $appPassword, $tokenEndpoint, $mode = self::MODE_ONEDRIVE, $targetId, $driveName = null) + public function __construct($appId, $appPassword, $tokenMode, $mode = self::MODE_ONEDRIVE, $targetId, $driveName = null, $appModeToken = null) { if($mode != self::MODE_ONEDRIVE && $mode != self::MODE_SHAREPOINT) { throw new ModeException("Unknown mode specified: " . $mode); } + if($tokenMode != self::OAUTH_MODE_USER && $tokenMode != self::OAUTH_MODE_APP) { + throw new ModeException("Unknown token mode specified: " . $tokenMode); + } $this->mode = $mode; - // Initialize the OAuth client - $oauthClient = new \League\OAuth2\Client\Provider\GenericProvider([ - 'clientId' => $appId, - 'clientSecret' => $appPassword, - 'urlAuthorize' => '', - 'urlResourceOwnerDetails' => '', - 'urlAccessToken' => $tokenEndpoint, - ]); - - try { - $this->token = $oauthClient->getAccessToken('client_credentials', [ - 'scope' => 'https://graph.microsoft.com/.default' + if ($tokenMode === self::OAUTH_MODE_USER) { + // Initialize the OAuth client + $oauthClient = new \League\OAuth2\Client\Provider\GenericProvider([ + 'clientId' => $appId, + 'clientSecret' => $appPassword, + 'urlAuthorize' => '', + 'urlResourceOwnerDetails' => '', + 'urlAccessToken' => $tokenEndpoint, ]); - } catch(IdentityProviderException $e) { - throw new AuthException($e->getMessage()); + + try { + $this->token = $oauthClient->getAccessToken('client_credentials', [ + 'scope' => 'https://graph.microsoft.com/.default' + ]); + } catch(IdentityProviderException $e) { + throw new AuthException($e->getMessage()); + } + } else if ($tokenMode === self::OAUTH_MODE_APP) { + $this->token = $appModeToken; } // Assign graph instance @@ -171,7 +181,7 @@ public function getUrl($path) } return false; } - + public function readStream($path) { @@ -189,7 +199,7 @@ public function listContents($directory = '', $recursive = false) $driveItems = $this->graph->createRequest('GET', $this->prefix . $drive->getId() .'/children') ->setReturnType(Model\DriveItem::class) ->execute(); - + $children = []; foreach ($driveItems as $driveItem) { $item = $driveItem->getProperties(); From a9ac21d29b673b76938e16f69fd6eeab2e828bed Mon Sep 17 00:00:00 2001 From: Glendon Solsberry Date: Thu, 14 Nov 2019 12:11:11 -0500 Subject: [PATCH 2/6] Use the token accurately --- src/MSGraph.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/MSGraph.php b/src/MSGraph.php index 56158b6..b1a03d3 100644 --- a/src/MSGraph.php +++ b/src/MSGraph.php @@ -61,13 +61,15 @@ public function __construct($appId, $appPassword, $tokenMode, $mode = self::MODE } catch(IdentityProviderException $e) { throw new AuthException($e->getMessage()); } + + $this->token = $this->token->getToken(); } else if ($tokenMode === self::OAUTH_MODE_APP) { $this->token = $appModeToken; } // Assign graph instance $this->graph = new Graph(); - $this->graph->setAccessToken($this->token->getToken()); + $this->graph->setAccessToken($this->token); // Check for existence if($mode == self::MODE_SHAREPOINT) { From 4d8eebafc28dd6572b541e7c29f1433f4630aada Mon Sep 17 00:00:00 2001 From: Glendon Solsberry Date: Thu, 14 Nov 2019 13:54:40 -0500 Subject: [PATCH 3/6] Split out authentication / authorization schemes to separate classes --- src/MSGraph.php | 40 ++-------------------------------------- src/MSGraphApp.php | 19 +++++++++++++++++++ src/MSGraphUser.php | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 38 deletions(-) create mode 100644 src/MSGraphApp.php create mode 100644 src/MSGraphUser.php diff --git a/src/MSGraph.php b/src/MSGraph.php index b1a03d3..ae00330 100644 --- a/src/MSGraph.php +++ b/src/MSGraph.php @@ -18,9 +18,6 @@ class MSGraph extends AbstractAdapter const MODE_SHAREPOINT = 'sharepoint'; const MODE_ONEDRIVE = 'onedrive'; - const OAUTH_MODE_APP = 'oauth_app'; - const OAUTH_MODE_USER = 'oauth_user'; - // Our mode, if sharepoint or onedrive private $mode; // Our Microsoft Graph Client @@ -34,42 +31,9 @@ class MSGraph extends AbstractAdapter // Our url prefix to be used for most file operations. This gets created in our constructor private $prefix; - public function __construct($appId, $appPassword, $tokenMode, $mode = self::MODE_ONEDRIVE, $targetId, $driveName = null, $appModeToken = null) + public function initialize($graph, $mode = self::MODE_ONEDRIVE, $targetId, $driveName) { - if($mode != self::MODE_ONEDRIVE && $mode != self::MODE_SHAREPOINT) { - throw new ModeException("Unknown mode specified: " . $mode); - } - if($tokenMode != self::OAUTH_MODE_USER && $tokenMode != self::OAUTH_MODE_APP) { - throw new ModeException("Unknown token mode specified: " . $tokenMode); - } - $this->mode = $mode; - - if ($tokenMode === self::OAUTH_MODE_USER) { - // Initialize the OAuth client - $oauthClient = new \League\OAuth2\Client\Provider\GenericProvider([ - 'clientId' => $appId, - 'clientSecret' => $appPassword, - 'urlAuthorize' => '', - 'urlResourceOwnerDetails' => '', - 'urlAccessToken' => $tokenEndpoint, - ]); - - try { - $this->token = $oauthClient->getAccessToken('client_credentials', [ - 'scope' => 'https://graph.microsoft.com/.default' - ]); - } catch(IdentityProviderException $e) { - throw new AuthException($e->getMessage()); - } - - $this->token = $this->token->getToken(); - } else if ($tokenMode === self::OAUTH_MODE_APP) { - $this->token = $appModeToken; - } - - // Assign graph instance - $this->graph = new Graph(); - $this->graph->setAccessToken($this->token); + $this->graph = $graph; // Check for existence if($mode == self::MODE_SHAREPOINT) { diff --git a/src/MSGraphApp.php b/src/MSGraphApp.php new file mode 100644 index 0000000..c049a50 --- /dev/null +++ b/src/MSGraphApp.php @@ -0,0 +1,19 @@ +setAccessToken($appModeToken); + + $this->initialize($graph, $mode, $targetId, $driveName); + } +} diff --git a/src/MSGraphUser.php b/src/MSGraphUser.php new file mode 100644 index 0000000..b5f8771 --- /dev/null +++ b/src/MSGraphUser.php @@ -0,0 +1,37 @@ + $appId, + 'clientSecret' => $appPassword, + 'urlAuthorize' => '', + 'urlResourceOwnerDetails' => '', + 'urlAccessToken' => $tokenEndpoint, + ]); + + try { + $this->token = $oauthClient->getAccessToken('client_credentials', [ + 'scope' => 'https://graph.microsoft.com/.default' + ]); + } catch(IdentityProviderException $e) { + throw new AuthException($e->getMessage()); + } + + // Assign graph instance + $graph = new Graph(); + $graph->setAccessToken($this->token->getToken()); + + $this->initialize($graph, $mode, $targetId, $driveName); + } +} From a30099e2876552057bfbff884d247b60c2f0cab4 Mon Sep 17 00:00:00 2001 From: Glendon Solsberry Date: Thu, 14 Nov 2019 13:59:45 -0500 Subject: [PATCH 4/6] Need use statements --- src/MSGraph.php | 1 - src/MSGraphApp.php | 2 ++ src/MSGraphUser.php | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/MSGraph.php b/src/MSGraph.php index ae00330..5d8e560 100644 --- a/src/MSGraph.php +++ b/src/MSGraph.php @@ -9,7 +9,6 @@ use ProcessMaker\Flysystem\Adapter\MSGraph\ModeException; use ProcessMaker\Flysystem\Adapter\MSGraph\SiteInvalidException; use League\OAuth2\Client\Provider\GenericProvider; -use League\OAuth2\Client\Provider\Exception\IdentityProviderException; use Microsoft\Graph\Graph; use Microsoft\Graph\Model; diff --git a/src/MSGraphApp.php b/src/MSGraphApp.php index c049a50..4869e26 100644 --- a/src/MSGraphApp.php +++ b/src/MSGraphApp.php @@ -2,6 +2,8 @@ namespace ProcessMaker\Flysystem\Adapter; +use Microsoft\Graph\Graph; + class MSGraphApp extends MSGraph { public function __construct($mode = self::MODE_ONEDRIVE, $targetId, $driveName = null, $appModeToken = null) diff --git a/src/MSGraphUser.php b/src/MSGraphUser.php index b5f8771..be5e0ea 100644 --- a/src/MSGraphUser.php +++ b/src/MSGraphUser.php @@ -2,6 +2,9 @@ namespace ProcessMaker\Flysystem\Adapter; +use Microsoft\Graph\Graph; +use League\OAuth2\Client\Provider\Exception\IdentityProviderException; + class MSGraphUser extends MSGraph { From 72d0fc5babd402d2b311da55424770fc7fbbd976 Mon Sep 17 00:00:00 2001 From: Glendon Solsberry Date: Thu, 14 Nov 2019 14:07:17 -0500 Subject: [PATCH 5/6] Ensure that we're setting all of the thigns we need --- src/MSGraph.php | 25 +++++++++++++++---------- src/MSGraphApp.php | 4 +--- src/MSGraphUser.php | 4 +--- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/MSGraph.php b/src/MSGraph.php index 5d8e560..c9befae 100644 --- a/src/MSGraph.php +++ b/src/MSGraph.php @@ -30,8 +30,16 @@ class MSGraph extends AbstractAdapter // Our url prefix to be used for most file operations. This gets created in our constructor private $prefix; + public function __construct($mode) + { + if ($mode != self::MODE_ONEDRIVE && $mode != self::MODE_SHAREPOINT) { + throw new ModeException("Unknown mode specified: " . $mode); + } + } + public function initialize($graph, $mode = self::MODE_ONEDRIVE, $targetId, $driveName) { + $this->mode = $mode; $this->graph = $graph; // Check for existence @@ -211,16 +219,13 @@ public function write($path, $contents, Config $config) { if($this->mode == self::MODE_SHAREPOINT) { // Attempt to write to sharepoint - try { - $driveItem = $this->graph->createRequest('PUT', $this->prefix . 'root:/' . $path . ':/content') - ->attachBody($contents) - ->setReturnType(Model\DriveItem::class) - ->execute(); - // Successfully created - return true; - } catch(Exception $e) { - throw $e; - } + $driveItem = $this->graph->createRequest('PUT', $this->prefix . 'root:/' . $path . ':/content') + ->attachBody($contents) + ->setReturnType(Model\DriveItem::class) + ->execute(); + + // Successfully created + return true; } } diff --git a/src/MSGraphApp.php b/src/MSGraphApp.php index 4869e26..298c4f7 100644 --- a/src/MSGraphApp.php +++ b/src/MSGraphApp.php @@ -8,9 +8,7 @@ class MSGraphApp extends MSGraph { public function __construct($mode = self::MODE_ONEDRIVE, $targetId, $driveName = null, $appModeToken = null) { - if($mode != self::MODE_ONEDRIVE && $mode != self::MODE_SHAREPOINT) { - throw new ModeException("Unknown mode specified: " . $mode); - } + parent::__construct($mode); // Assign graph instance $graph = new Graph(); diff --git a/src/MSGraphUser.php b/src/MSGraphUser.php index be5e0ea..789f40e 100644 --- a/src/MSGraphUser.php +++ b/src/MSGraphUser.php @@ -10,9 +10,7 @@ class MSGraphUser extends MSGraph public function __construct($appId, $appPassword, $tokenEndpoint, $mode = self::MODE_ONEDRIVE, $targetId, $driveName = null) { - if($mode != self::MODE_ONEDRIVE && $mode != self::MODE_SHAREPOINT) { - throw new ModeException("Unknown mode specified: " . $mode); - } + parent::__construct($mode); // Initialize the OAuth client $oauthClient = new \League\OAuth2\Client\Provider\GenericProvider([ From 5b0acebbcbe6b10c58d612fbda2c746c7cd9a607 Mon Sep 17 00:00:00 2001 From: Glendon Solsberry Date: Mon, 25 Nov 2019 09:37:56 -0500 Subject: [PATCH 6/6] Adds update capability to files --- src/MSGraph.php | 120 +++++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 58 deletions(-) diff --git a/src/MSGraph.php b/src/MSGraph.php index c9befae..0a13c4d 100644 --- a/src/MSGraph.php +++ b/src/MSGraph.php @@ -1,32 +1,37 @@ graph = $graph; // Check for existence - if($mode == self::MODE_SHAREPOINT) { + if ($mode == self::MODE_SHAREPOINT) { try { - $site = $this->graph->createRequest('GET', '/sites/' . $targetId) - ->setReturnType(Model\Site::class) - ->execute(); - // Assign the site id triplet to our targetId - $this->targetId = $site->getId(); - } catch(\Exception $e) { - if($e->getCode() == 400) { + $site = $this->graph->createRequest('GET', '/sites/' . $targetId) + ->setReturnType(Model\Site::class) + ->execute(); + // Assign the site id triplet to our targetId + $this->targetId = $site->getId(); + } catch (\Exception $e) { + if ($e->getCode() == 400) { throw new SiteInvalidException("The sharepoint site " . $targetId . " is invalid."); } + throw $e; } $this->prefix = "/sites/" . $this->targetId . '/drive/items/'; - if($driveName != '') { + if ($driveName != '') { // Then we specified a drive name, so let's enumerate the drives and find it $drives = $this->graph->createRequest('GET', '/sites/' . $this->targetId . '/drives') ->execute(); $drives = $drives->getBody()['value']; - foreach($drives as $drive) { - if($drive['name'] == $driveName) { + foreach ($drives as $drive) { + if ($drive['name'] == $driveName) { $this->driveId = $drive['id']; $this->prefix = "/drives/" . $this->driveId . "/items/"; + break; } } - if(!$this->driveId) { - throw new SiteInvalidException("The sharepoint drive with name " . $driveName . " could not be found."); + if (! $this->driveId) { + throw new SiteInvalidException("The sharepoint drive with name " . $driveName . " could not be found."); } - } } - } public function has($path) { - if($this->mode == self::MODE_SHAREPOINT) { + if ($this->mode == self::MODE_SHAREPOINT) { try { $driveItem = $this->graph->createRequest('GET', $this->prefix . 'root:/' . $path) ->setReturnType(Model\DriveItem::class) ->execute(); // Successfully retrieved meta data. return true; - } catch(ClientException $e) { - if($e->getCode() == 404) { + } catch (ClientException $e) { + if ($e->getCode() == 404) { // Not found, let's return false; return false; } + throw $e; - } catch(Exception $e) { + } catch (Exception $e) { throw $e; } } + return false; } public function read($path) { - if($this->mode == self::MODE_SHAREPOINT) { + if ($this->mode == self::MODE_SHAREPOINT) { try { $driveItem = $this->graph->createRequest('GET', $this->prefix . 'root:/' . $path) ->setReturnType(Model\DriveItem::class) ->execute(); // Successfully retrieved meta data. // Now get content - $contentStream = $this->graph->createRequest('GET', $this->prefix . $driveItem->getId() .'/content') + $contentStream = $this->graph->createRequest('GET', $this->prefix . $driveItem->getId() . '/content') ->setReturnType(Stream::class) ->execute(); $contents = ''; $bufferSize = 8012; // Copy over the data into a string - while (!$contentStream->eof()) { + while (! $contentStream->eof()) { $contents .= $contentStream->read($bufferSize); } + return ['contents' => $contents]; - } catch(ClientException $e) { - if($e->getCode() == 404) { + } catch (ClientException $e) { + if ($e->getCode() == 404) { // Not found, let's return false; return false; } + throw $e; - } catch(Exception $e) { + } catch (Exception $e) { throw $e; } } + return false; } public function getUrl($path) { - if($this->mode == self::MODE_SHAREPOINT) { + if ($this->mode == self::MODE_SHAREPOINT) { try { $driveItem = $this->graph->createRequest('GET', $this->prefix . 'root:/' . $path) ->setReturnType(Model\DriveItem::class) @@ -142,22 +152,23 @@ public function getUrl($path) // Successfully retrieved meta data. // Return url property return $driveItem->getWebUrl(); - } catch(ClientException $e) { - if($e->getCode() == 404) { + } catch (ClientException $e) { + if ($e->getCode() == 404) { // Not found, let's return false; return false; } + throw $e; - } catch(Exception $e) { + } catch (Exception $e) { throw $e; } } + return false; } public function readStream($path) { - } public function listContents($directory = '', $recursive = false) @@ -169,7 +180,7 @@ public function listContents($directory = '', $recursive = false) ->execute(); // Successfully retrieved meta data. // Now get content - $driveItems = $this->graph->createRequest('GET', $this->prefix . $drive->getId() .'/children') + $driveItems = $this->graph->createRequest('GET', $this->prefix . $drive->getId() . '/children') ->setReturnType(Model\DriveItem::class) ->execute(); @@ -179,6 +190,7 @@ public function listContents($directory = '', $recursive = false) $item['path'] = $directory . '/' . $driveItem->getName(); $children[] = $item; } + return $children; } catch (ClientException $e) { throw $e; @@ -186,77 +198,71 @@ public function listContents($directory = '', $recursive = false) throw $e; } } + return []; } public function getMetadata($path) { - } public function getSize($path) { - } public function getMimetype($path) { - } public function getTimestamp($path) { - } public function getVisibility($path) { - } // Write methods public function write($path, $contents, Config $config) { - if($this->mode == self::MODE_SHAREPOINT) { + if ($this->mode == self::MODE_SHAREPOINT) { // Attempt to write to sharepoint $driveItem = $this->graph->createRequest('PUT', $this->prefix . 'root:/' . $path . ':/content') - ->attachBody($contents) - ->setReturnType(Model\DriveItem::class) - ->execute(); + ->attachBody($contents) + ->setReturnType(Model\DriveItem::class) + ->execute(); // Successfully created return true; } + + return false; } public function writeStream($path, $resource, Config $config) { - } public function update($path, $contents, Config $config) { - + return $this->write($path, $contents, $config); } public function updateStream($path, $resource, Config $config) { - } public function rename($path, $newpath) { - } public function copy($path, $newpath) { - } public function delete($path) { - if($this->mode == self::MODE_SHAREPOINT) { + if ($this->mode == self::MODE_SHAREPOINT) { try { $driveItem = $this->graph->createRequest('GET', $this->prefix . 'root:/' . $path) ->setReturnType(Model\DriveItem::class) @@ -265,34 +271,32 @@ public function delete($path) // Now delete the file $this->graph->createRequest('DELETE', $this->prefix . $driveItem->getId()) ->execute(); + return true; - } catch(ClientException $e) { - if($e->getCode() == 404) { + } catch (ClientException $e) { + if ($e->getCode() == 404) { // Not found, let's return false; return false; } + throw $e; - } catch(Exception $e) { + } catch (Exception $e) { throw $e; } } - return false; + return false; } public function deleteDir($dirname) { - } public function createDir($dirname, Config $config) { - } public function setVisibility($path, $visibility) { - } - }