Skip to content

Commit

Permalink
MDL-22236 Webservice file upload - Allow webservice file uploads dire…
Browse files Browse the repository at this point in the history
…ct to a draft filearea.

Via post to /webservice/upload.php
  • Loading branch information
Damyon Wiese committed Aug 8, 2013
1 parent f05ea82 commit 106c55f
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 11 deletions.
9 changes: 7 additions & 2 deletions admin/webservice/forms.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,17 @@ function definition() {
$mform->addHelpButton('restrictedusers', 'restrictedusers', 'webservice');
$mform->setType('restrictedusers', PARAM_BOOL);

//can users download files
// Can users download files?
$mform->addElement('advcheckbox', 'downloadfiles', get_string('downloadfiles', 'webservice'));
$mform->setAdvanced('downloadfiles');
$mform->addHelpButton('downloadfiles', 'downloadfiles', 'webservice');
$mform->setType('downloadfiles', PARAM_BOOL);

// Can users upload files?
$mform->addElement('advcheckbox', 'uploadfiles', get_string('uploadfiles', 'webservice'));
$mform->setAdvanced('uploadfiles');
$mform->addHelpButton('uploadfiles', 'uploadfiles', 'webservice');

/// needed to select automatically the 'No required capability" option
$currentcapabilityexist = false;
if (empty($service->requiredcapability)) {
Expand Down Expand Up @@ -297,4 +302,4 @@ function validation($data, $files) {
return $errors;
}

}
}
2 changes: 2 additions & 0 deletions lang/en/webservice.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@
$string['unknownoptionkey'] = 'Unknown option key ({$a})';
$string['unnamedstringparam'] = 'A string parameter is unnamed.';
$string['updateusersettings'] = 'Update';
$string['uploadfiles'] = 'Can upload files';
$string['uploadfiles_help'] = 'If enabled, any user can upload files with their security keys to their own private files area or a draft file area. Any user file quotas apply.';
$string['userasclients'] = 'Users as clients with token';
$string['userasclientsdescription'] = 'The following steps help you to set up the Moodle web service for users as clients. These steps also help to set up the recommended token (security keys) authentication method. In this use case, the user will generate his token from the security keys page via My profile settings.';
$string['usermissingcaps'] = 'Missing capabilities: {$a}';
Expand Down
1 change: 1 addition & 0 deletions lib/db/install.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2565,6 +2565,7 @@
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="shortname" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="a unique shortname"/>
<FIELD NAME="downloadfiles" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="1 if the service allow people to download file from webservice/plugins.php - 0 if not"/>
<FIELD NAME="uploadfiles" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="1 if the service allow people to upload files to webservice/upload.php - 0 if not"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
Expand Down
3 changes: 2 additions & 1 deletion lib/db/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,7 @@
'enabled' => 0,
'restrictedusers' => 0,
'shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE,
'downloadfiles' => 1
'downloadfiles' => 1,
'uploadfiles' => 1
),
);
14 changes: 14 additions & 0 deletions lib/db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -2313,5 +2313,19 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2013072600.01);
}

if ($oldversion < 2013080700.01) {
// Define field uploadfiles to be added to external_services.
$table = new xmldb_table('external_services');
$field = new xmldb_field('uploadfiles', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'downloadfiles');

// Conditionally launch add field uploadfiles.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}

// Main savepoint reached.
upgrade_main_savepoint(true, 2013080700.01);
}

return true;
}
6 changes: 6 additions & 0 deletions lib/upgradelib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,7 @@ function external_update_descriptions($component) {
$service['requiredcapability'] = empty($service['requiredcapability']) ? null : $service['requiredcapability'];
$service['restrictedusers'] = !isset($service['restrictedusers']) ? 1 : $service['restrictedusers'];
$service['downloadfiles'] = !isset($service['downloadfiles']) ? 0 : $service['downloadfiles'];
$service['uploadfiles'] = !isset($service['uploadfiles']) ? 0 : $service['uploadfiles'];
$service['shortname'] = !isset($service['shortname']) ? null : $service['shortname'];

$update = false;
Expand All @@ -1060,6 +1061,10 @@ function external_update_descriptions($component) {
$dbservice->downloadfiles = $service['downloadfiles'];
$update = true;
}
if ($dbservice->uploadfiles != $service['uploadfiles']) {
$dbservice->uploadfiles = $service['uploadfiles'];
$update = true;
}
//if shortname is not a PARAM_ALPHANUMEXT, fail (tested here for service update and creation)
if (isset($service['shortname']) and
(clean_param($service['shortname'], PARAM_ALPHANUMEXT) != $service['shortname'])) {
Expand Down Expand Up @@ -1114,6 +1119,7 @@ function external_update_descriptions($component) {
$dbservice->requiredcapability = empty($service['requiredcapability']) ? null : $service['requiredcapability'];
$dbservice->restrictedusers = !isset($service['restrictedusers']) ? 1 : $service['restrictedusers'];
$dbservice->downloadfiles = !isset($service['downloadfiles']) ? 0 : $service['downloadfiles'];
$dbservice->uploadfiles = !isset($service['uploadfiles']) ? 0 : $service['uploadfiles'];
$dbservice->shortname = !isset($service['shortname']) ? null : $service['shortname'];
$dbservice->component = $component;
$dbservice->timecreated = time();
Expand Down
2 changes: 1 addition & 1 deletion version.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

defined('MOODLE_INTERNAL') || die();

$version = 2013080700.00; // YYYYMMDD = weekly release date of this DEV branch
$version = 2013080700.01; // YYYYMMDD = weekly release date of this DEV branch
// RR = release increments - 00 in DEV branches
// .XX = incremental changes

Expand Down
3 changes: 3 additions & 0 deletions webservice/externallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public static function get_site_info($serviceshortnames = array()) {
$service = $DB->get_record_sql($servicesql, array($token, $USER->id));

$siteinfo['downloadfiles'] = $service->downloadfiles;
$siteinfo['uploadfiles'] = $service->uploadfiles;

if (!empty($service)) {
// Return the release and version number for web service users only.
Expand Down Expand Up @@ -195,6 +196,8 @@ public static function get_site_info_returns() {
),
'downloadfiles' => new external_value(PARAM_INT, '1 if users are allowed to download files, 0 if not',
VALUE_OPTIONAL),
'uploadfiles' => new external_value(PARAM_INT, '1 if users are allowed to upload files, 0 if not',
VALUE_OPTIONAL),
'release' => new external_value(PARAM_TEXT, 'Moodle release number', VALUE_OPTIONAL),
'version' => new external_value(PARAM_TEXT, 'Moodle version number', VALUE_OPTIONAL),
'mobilecssurl' => new external_value(PARAM_URL, 'Mobile custom CSS theme', VALUE_OPTIONAL)
Expand Down
3 changes: 3 additions & 0 deletions webservice/tests/externallib_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public function test_get_site_info() {
$webservice->component = 'moodle';
$webservice->timecreated = time();
$webservice->downloadfiles = true;
$webservice->uploadfiles = true;
$externalserviceid = $DB->insert_record('external_services', $webservice);

// Add a function to the service
Expand Down Expand Up @@ -97,6 +98,8 @@ public function test_get_site_info() {
$function = array_pop($siteinfo['functions']);
$this->assertEquals($function['name'], 'core_course_get_contents');
$this->assertEquals($function['version'], $siteinfo['version']);
$this->assertEquals(1, $siteinfo['downloadfiles']);
$this->assertEquals(1, $siteinfo['uploadfiles']);
}

}
13 changes: 13 additions & 0 deletions webservice/upgrade.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
This files describes API changes in /webservice/*
information provided here is intended especially for developers.

This information is intended for authors of webservices, not people writing webservice clients.

=== 2.6 ===

* webservice/upload.php
Accepts 2 new post parameters to allow uploading of files to a users draft area.
- filearea should be either 'private' (default) or 'draft'
- itemid unused if the filearea is 'private', for 'draft' it can be the id of a previously
created draft area - or 0 which will generate a new draft area for the files.

49 changes: 42 additions & 7 deletions webservice/upload.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
* filepath => the private file aera path (where files will be stored)
* [_FILES] => for example you can send the files with <input type=file>,
* or with curl magic: 'file_1' => '@/path/to/file', or ...
* filearea => 'private' or 'draft' (default = 'private'). These are the only 2 areas we are allowing
* direct uploads via webservices. The private file area is deprecated - please don't use it.
* itemid => For draft areas this is the draftid - this can be used to add a list of files
* to a draft area in separate requests. If it is 0, a new draftid will be generated.
* For private files, this is ignored.
*
* @package core_webservice
* @copyright 2011 Dongsheng Cai <[email protected]>
Expand All @@ -42,13 +47,22 @@
require_once(dirname(dirname(__FILE__)) . '/config.php');
require_once($CFG->dirroot . '/webservice/lib.php');
$filepath = optional_param('filepath', '/', PARAM_PATH);
// The default file area is 'private' for user private files. This
// area is actually deprecated and only supported for backwards compatibility with
// the mobile app.
$filearea = optional_param('filearea', 'private', PARAM_ALPHA);
$itemid = optional_param('itemid', 0, PARAM_INT);

echo $OUTPUT->header();

// authenticate the user
$token = required_param('token', PARAM_ALPHANUM);
$webservicelib = new webservice();
$authenticationinfo = $webservicelib->authenticate_user($token);
$fileuploaddisabled = empty($authenticationinfo['service']->uploadfiles);
if ($fileuploaddisabled) {
throw new webservice_access_exception('Web service file upload must be enabled in external service settings');
}

// check the user can manage his own files (can upload)
$context = context_user::instance($USER->id);
Expand Down Expand Up @@ -105,13 +119,34 @@

$fs = get_file_storage();

$usedspace = 0;
$privatefiles = $fs->get_area_files($context->id, 'user', 'private', false, 'id', false);
foreach ($privatefiles as $file) {
$usedspace += $file->get_filesize();
if ($filearea == 'draft' && $itemid <= 0) {
$itemid = file_get_unused_draft_itemid();
}

// Get any existing file size limits.
$maxareabytes = FILE_AREA_MAX_BYTES_UNLIMITED;
$maxupload = get_user_max_upload_file_size($context, $CFG->maxbytes);
if ($filearea == 'private') {
// Private files area is limited by $CFG->userquota.
if (!has_capability('moodle/user:ignoreuserquota', $context)) {
$maxareabytes = $CFG->userquota;
}
}

// Count the size of all existing files in this area.
if ($maxareabytes > 0) {
$usedspace = 0;
$existingfiles = $fs->get_area_files($context->id, 'user', $filearea, false, 'id', false);
foreach ($existingfiles as $file) {
$usedspace += $file->get_filesize();
}
if ($totalsize > ($maxareabytes - $usedspace)) {
throw new file_exception('userquotalimit');
}
}

if ($totalsize > ($CFG->userquota - $usedspace)) {
// Check the size of this upload.
if ($maxupload !== USER_CAN_IGNORE_FILE_SIZE_LIMITS && $totalsize > $maxupload) {
throw new file_exception('userquotalimit');
}

Expand All @@ -126,10 +161,10 @@
$file_record->component = 'user';
$file_record->contextid = $context->id;
$file_record->userid = $USER->id;
$file_record->filearea = 'private';
$file_record->filearea = $filearea;
$file_record->filename = $file->filename;
$file_record->filepath = $filepath;
$file_record->itemid = 0;
$file_record->itemid = $itemid;
$file_record->license = $CFG->sitedefaultlicense;
$file_record->author = fullname($authenticationinfo['user']);
$file_record->source = '';
Expand Down

0 comments on commit 106c55f

Please sign in to comment.