MDL-58127 skydrive: Upgrades to new oauth2

Support for controlled links workflow.

Part of MDL-58220
This commit is contained in:
Damyon Wiese
2017-04-03 13:41:19 +08:00
parent af28b22892
commit ffda3e395c
11 changed files with 1328 additions and 355 deletions
+56
View File
@@ -0,0 +1,56 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Class for loading/storing access records from the DB.
*
* @package core
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_skydrive;
defined('MOODLE_INTERNAL') || die();
use core\persistent;
/**
* Class for loading/storing issuer from the DB
*
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class access extends persistent {
const TABLE = 'repository_skydrive_access';
/**
* Return the definition of the properties of this model.
*
* @return array
*/
protected static function define_properties() {
return array(
'permissionid' => array(
'type' => PARAM_RAW
),
'itemid' => array(
'type' => PARAM_RAW
)
);
}
}
@@ -0,0 +1,79 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* A scheduled task.
*
* @package repository_skydrive
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_skydrive;
use \core\task\scheduled_task;
defined('MOODLE_INTERNAL') || die();
/**
* Simple task to delete temporary permission records.
* @package core
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class remove_temp_access_task extends scheduled_task {
/**
* Get a descriptive name for this task (shown to admins).
*
* @return string
*/
public function get_name() {
return get_string('removetempaccesstask', 'repository_skydrive');
}
/**
* Do the job.
* Throw exceptions on errors (the job will be retried).
*/
public function execute() {
$accessrecords = access::get_records();
$expires = new DateTime();
$expires->sub(new DateInterval("P7D"));
$timestamp = $expires->getTimestamp();
$issuerid = get_config('repository_skydrive', 'issuerid');
$issuer = \core\oauth2\api::get_issuer_by_id($issuerid);
// Add the current user as an OAuth writer.
$systemauth = \core\oauth2\api::get_system_oauth_client($issuer);
if ($systemauth === false) {
$details = 'Cannot connect as system user';
throw new repository_exception('errorwhilecommunicatingwith', 'repository', '', $details);
}
$systemservice = new repository_skydrive\rest($systemauth);
foreach ($accessrecords as $access) {
if ($access->get('timemodified') < $timestamp) {
$params = ['permissionid' => $access->get('permissionid'), 'itemid' => $access->get('itemid')];
$systemservice->call('delete_permission', $params);
$access->delete();
}
}
}
}
+159
View File
@@ -0,0 +1,159 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Microsoft Graph API Rest Interface.
*
* @package repository_skydrive
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_skydrive;
defined('MOODLE_INTERNAL') || die();
/**
* Microsoft Graph API Rest Interface.
*
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class rest extends \core\oauth2\rest {
/**
* Define the functions of the rest API.
*
* @return array Example:
* [ 'listFiles' => [ 'method' => 'get', 'endpoint' => 'http://...', 'args' => [ 'folder' => PARAM_STRING ] ] ]
*/
public function get_api_functions() {
return [
'list' => [
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/{parent}/children',
'method' => 'get',
'args' => [
'$select' => PARAM_RAW,
'$expand' => PARAM_RAW,
'parent' => PARAM_RAW,
'$skip' => PARAM_INT,
'$skipToken' => PARAM_RAW,
'$count' => PARAM_INT
],
'response' => 'json'
],
'search' => [
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/{parent}/search(q=\'{search}\')',
'method' => 'get',
'args' => [
'search' => PARAM_NOTAGS,
'$select' => PARAM_RAW,
'parent' => PARAM_RAW,
'$skip' => PARAM_INT,
'$skipToken' => PARAM_RAW,
'$count' => PARAM_INT
],
'response' => 'json'
],
'get' => [
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/items/{fileid}',
'method' => 'get',
'args' => [
'fileid' => PARAM_RAW,
'$select' => PARAM_RAW,
'$expand' => PARAM_RAW
],
'response' => 'json'
],
'list_permissions' => [
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/items/{fileid}/permissions',
'method' => 'get',
'args' => [
'$select' => PARAM_RAW,
'$expand' => PARAM_RAW,
'fileid' => PARAM_RAW,
'$skip' => PARAM_INT,
'$skipToken' => PARAM_RAW,
'$count' => PARAM_INT
],
'response' => 'json'
],
'create_permission' => [
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/items/{fileid}/invite',
'method' => 'post',
'args' => [
'fileid' => PARAM_RAW
],
'response' => 'json'
],
'get_file_by_path' => [
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/root:/{fullpath}',
'method' => 'get',
'args' => [
'fullpath' => PARAM_RAW,
'$select' => PARAM_RAW
],
'response' => 'json'
],
'create_folder' => [
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/items/{parentid}/children',
'method' => 'post',
'args' => [
'parentid' => PARAM_RAW
],
'response' => 'json'
],
'create_link' => [
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/items/{fileid}/createLink',
'method' => 'post',
'args' => [
'fileid' => PARAM_RAW
],
'response' => 'json'
],
'get_drive' => [
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive',
'method' => 'get',
'args' => [],
'response' => 'json'
],
'delete_file_by_path' => [
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/root:/{fullpath}',
'method' => 'delete',
'args' => [
'fullpath' => PARAM_RAW,
],
'response' => 'json'
],
'copy_share' => [
'endpoint' => 'https://graph.microsoft.com/v1.0/shares/{sharetoken}/root/copy',
'method' => 'post',
'args' => [
'sharetoken' => PARAM_RAW,
],
'response' => 'json'
],
'delete_permission' => [
'endpoint' => 'https://graph.microsoft.com/v1.0/me/drive/items/{fileid}/permissions/{permissionid}',
'method' => 'delete',
'args' => [
'fileid' => PARAM_RAW,
'permissionid' => PARAM_RAW
],
'response' => 'json'
],
];
}
}
+11 -3
View File
@@ -25,7 +25,15 @@
defined('MOODLE_INTERNAL') || die();
$definitions = array(
'foldername' => array(
'mode' => cache_store::MODE_SESSION,
)
// Used to store file ids for folders.
// The keys used are full path to the folder, the values are the id in google drive.
// The static acceleration size has been based upon the depths of a single path.
'folder' => array(
'mode' => cache_store::MODE_APPLICATION,
'simplekeys' => false,
'simpledata' => true,
'staticacceleration' => true,
'staticaccelerationsize' => 10,
'canuselocalstore' => true
),
);
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="repository/skydrive/db" VERSION="20170314" COMMENT="XMLDB file for Moodle repository/skydrive"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="repository_skydrive_access" COMMENT="List of temporary access grants.">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="usermodified" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="permissionid" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The permission id in OneDrive."/>
<FIELD NAME="itemid" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The item id in OneDrive."/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="usermodifiedkey" TYPE="foreign" FIELDS="usermodified" REFTABLE="user" REFFIELDS="id"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
+43
View File
@@ -0,0 +1,43 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Definition of repository_skydrive scheduled tasks.
*
* The handlers defined on this file are processed and registered into
* the Moodle DB after any install or upgrade operation. All plugins
* support this.
*
* @package repository_skydrive
* @copyright 2017 Damyon Wiese
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/* List of handlers */
$tasks = array(
array(
'classname' => 'repository_skydrive\remove_temp_access_task',
'blocking' => 0,
'minute' => 'R',
'hour' => 'R',
'day' => '*',
'dayofweek' => 'R',
'month' => '*'
),
);
+54
View File
@@ -0,0 +1,54 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
defined('MOODLE_INTERNAL') || die();
/**
* @param int $oldversion the version we are upgrading from
* @return bool result
*/
function xmldb_repository_skydrive_upgrade($oldversion) {
global $DB;
$dbman = $DB->get_manager();
if ($oldversion < 2017031400) {
// Define table repository_skydrive_access to be created.
$table = new xmldb_table('repository_skydrive_access');
// Adding fields to table repository_skydrive_access.
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
$table->add_field('permissionid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
$table->add_field('itemid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
// Adding keys to table repository_skydrive_access.
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
$table->add_key('usermodifiedkey', XMLDB_KEY_FOREIGN, array('usermodified'), 'user', array('id'));
// Conditionally launch create table for repository_skydrive_access.
if (!$dbman->table_exists($table)) {
$dbman->create_table($table);
}
// Skydrive savepoint reached.
upgrade_plugin_savepoint(true, 2017031400, 'repository', 'skydrive');
}
return true;
}
@@ -22,10 +22,20 @@
* @author Dan Poltawski <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['cachedef_foldername'] = 'Folder name cache';
$string['clientid'] = 'Client ID';
$string['configplugin'] = 'Configure Microsoft OneDrive';
$string['oauthinfo'] = '<p>To use this plugin, you must register your site <a href="https://account.live.com/developers/applications">with Microsoft</a>.<p>As part of the registration process, you will need to enter the following URL as \'Redirect domain\':</p><p>{$a->callbackurl}</p>Once registered, you will be provided with a client ID and secret which can be entered here.</p>';
$string['configplugin'] = 'Configure OneDrive plugin';
$string['skydrive:view'] = 'View OneDrive repository';
$string['pluginname'] = 'Microsoft OneDrive';
$string['secret'] = 'Secret';
$string['skydrive:view'] = 'View OneDrive';
$string['issuer'] = 'OAuth 2 service';
$string['issuer_help'] = 'Select the OAuth 2 service that is configured to talk to the OneDrive API. If the services does not exist yet, you might need to create it.';
$string['servicenotenabled'] = 'Access not configured.';
$string['oauth2serviceslink'] = '<a href="{$a}" title="Link to OAuth Services configuration">OAuth 2 Services Configuration</a>';
$string['searchfor'] = 'Search for {$a}';
$string['internal'] = 'Internal (files stored in Moodle)';
$string['external'] = 'External (only links stored in Moodle)';
$string['both'] = 'Internal and External';
$string['supportedreturntypes'] = 'Supported files';
$string['defaultreturntype'] = 'Default return type';
$string['fileoptions'] = 'The types and defaults for returned files is configurable here. Note that all files linked externally will be updated so that the owner is the Moodle system account.';
$string['owner'] = 'Owned by: {$a}';
$string['cachedef_folder'] = 'OneDrive File IDs for folders in the system account';
File diff suppressed because it is too large Load Diff
-245
View File
@@ -1,245 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Functions for operating with the skydrive API
*
* @package repository_skydrive
* @copyright 2012 Lancaster University Network Services Ltd
* @author Dan Poltawski <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir.'/oauthlib.php');
/**
* A helper class to access microsoft live resources using the api.
*
* This uses the microsfot API defined in
* http://msdn.microsoft.com/en-us/library/hh243648.aspx
*
* @package repository_skydrive
* @copyright 2012 Lancaster University Network Services Ltd
* @author Dan Poltawski <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class microsoft_skydrive extends oauth2_client {
/** @var string OAuth 2.0 scope */
const SCOPE = 'wl.skydrive';
/** @var string Base url to access API */
const API = 'https://apis.live.net/v5.0';
/** @var cache_session cache of foldernames */
var $foldernamecache = null;
/**
* Construct a skydrive request object
*
* @param string $clientid client id for OAuth 2.0 provided by microsoft
* @param string $clientsecret secret for OAuth 2.0 provided by microsoft
* @param moodle_url $returnurl url to return to after succseful auth
*/
public function __construct($clientid, $clientsecret, $returnurl) {
parent::__construct($clientid, $clientsecret, $returnurl, self::SCOPE);
// Make a session cache
$this->foldernamecache = cache::make('repository_skydrive', 'foldername');
}
/**
* Returns the auth url for OAuth 2.0 request
* @return string the auth url
*/
protected function auth_url() {
return 'https://login.live.com/oauth20_authorize.srf';
}
/**
* Returns the token url for OAuth 2.0 request
* @return string the auth url
*/
protected function token_url() {
return 'https://login.live.com/oauth20_token.srf';
}
/**
* Post request.
*
* Overridden to convert the data to a string, else curl will set the wrong headers.
*
* @param string $url The URL.
* @param array|string $params The parameters.
* @param array $options The options.
* @return bool
*/
public function post($url, $params = '', $options = array()) {
return parent::post($url, format_postdata_for_curlcall($params), $options);
}
/**
* Downloads a file to a file from skydrive using authenticated request
*
* @param string $id id of file
* @param string $path path to save file to
* @return array stucture for repository download_file
*/
public function download_file($id, $path) {
$url = self::API."/${id}/content";
// Microsoft live redirects to the real download location..
$this->setopt(array('CURLOPT_FOLLOWLOCATION' => true, 'CURLOPT_MAXREDIRS' => 3));
$content = $this->get($url);
file_put_contents($path, $content);
return array('path'=>$path, 'url'=>$url);
}
/**
* Returns a folder name property for a given folderid.
*
* @param string $folderid the folder id which is passed
* @return mixed folder name or false in case of error
*/
public function get_folder_name($folderid) {
if (empty($folderid)) {
throw new coding_exception('Empty folderid passed to get_folder_name');
}
// Cache based on oauthtoken and folderid.
$cachekey = $this->folder_cache_key($folderid);
if ($foldername = $this->foldernamecache->get($cachekey)) {
return $foldername;
}
$url = self::API."/{$folderid}";
$ret = json_decode($this->get($url));
if (isset($ret->error)) {
$this->log_out();
return false;
}
$this->foldernamecache->set($cachekey, $ret->name);
return $ret->name;
}
/**
* Returns a list of files the user has formated for files api
*
* @param string $path the path which we are in
* @return mixed Array of files formated for fileapoi
*/
public function get_file_list($path = '') {
global $OUTPUT;
$precedingpath = '';
if (empty($path)) {
$url = self::API."/me/skydrive/files/";
} else {
$parts = explode('/', $path);
$currentfolder = array_pop($parts);
$url = self::API."/{$currentfolder}/files/";
}
$ret = json_decode($this->get($url));
if (isset($ret->error)) {
$this->log_out();
return false;
}
$files = array();
foreach ($ret->data as $file) {
switch($file->type) {
case 'folder':
case 'album':
// Cache the foldername for future requests.
$cachekey = $this->folder_cache_key($file->id);
$this->foldernamecache->set($cachekey, $file->name);
$files[] = array(
'title' => $file->name,
'path' => $path.'/'.$file->id,
'size' => 0,
'date' => strtotime($file->updated_time),
'thumbnail' => $OUTPUT->image_url(file_folder_icon(90))->out(false),
'children' => array(),
);
break;
case 'photo':
$files[] = array(
'title' => $file->name,
'size' => $file->size,
'date' => strtotime($file->updated_time),
'thumbnail' => $OUTPUT->image_url(file_extension_icon($file->name, 90))->out(false),
'realthumbnail' => $file->picture,
'source' => $file->id,
'url' => $file->link,
'image_height' => $file->height,
'image_width' => $file->width,
'author' => $file->from->name,
);
break;
case 'video':
$files[] = array(
'title' => $file->name,
'size' => $file->size,
'date' => strtotime($file->updated_time),
'thumbnail' => $OUTPUT->image_url(file_extension_icon($file->name, 90))->out(false),
'realthumbnail' => $file->picture,
'source' => $file->id,
'url' => $file->link,
'author' => $file->from->name,
);
break;
case 'audio':
$files[] = array(
'title' => $file->name,
'size' => $file->size,
'date' => strtotime($file->updated_time),
'thumbnail' => $OUTPUT->image_url(file_extension_icon($file->name, 90))->out(false),
'source' => $file->id,
'url' => $file->link,
'author' => $file->from->name,
);
break;
case 'file':
$files[] = array(
'title' => $file->name,
'size' => $file->size,
'date' => strtotime($file->updated_time),
'thumbnail' => $OUTPUT->image_url(file_extension_icon($file->name, 90))->out(false),
'source' => $file->id,
'url' => $file->link,
'author' => $file->from->name,
);
break;
}
}
return $files;
}
/**
* Returns a key for foldernane cache
*
* @param string $folderid the folder id which is to be cached
* @return string the cache key to use
*/
private function folder_cache_key($folderid) {
// Cache based on oauthtoken and folderid.
return $this->get_tokenname().'_'.$folderid;
}
}
+1 -1
View File
@@ -25,6 +25,6 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2016120500; // The current plugin version (Date: YYYYMMDDXX).
$plugin->version = 2017031400; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2016112900; // Requires this Moodle version.
$plugin->component = 'repository_skydrive'; // Full name of the plugin (used for diagnostics).