MDL-65547 tool_mobile: Allow to generate site QR codes only
authorJuan Leyva <juanleyvadelgado@gmail.com>
Wed, 22 Apr 2020 11:01:57 +0000 (13:01 +0200)
committerJuan Leyva <juanleyvadelgado@gmail.com>
Fri, 8 May 2020 14:51:36 +0000 (16:51 +0200)
admin/tool/mobile/classes/api.php
admin/tool/mobile/classes/external.php
admin/tool/mobile/lang/en/tool_mobile.php
admin/tool/mobile/lib.php
admin/tool/mobile/settings.php
admin/tool/mobile/tests/externallib_test.php

index 9c078e1..914ef5f 100644 (file)
@@ -55,6 +55,12 @@ class api {
     const MOODLE_APPS_PORTAL_URL = 'https://apps.moodle.com';
     /** @var int seconds a QR login key will expire. */
     const LOGIN_QR_KEY_TTL = 600;
+    /** @var int QR code disabled value */
+    const QR_CODE_DISABLED = 0;
+    /** @var int QR code type URL value */
+    const QR_CODE_URL = 1;
+    /** @var int QR code type login value */
+    const QR_CODE_LOGIN = 2;
 
     /**
      * Returns a list of Moodle plugins supporting the mobile app.
@@ -626,17 +632,25 @@ class api {
     }
 
     /**
-     * Generates a QR code for automatic login from the mobile app.
+     * Generates a QR code with the site URL or for automatic login from the mobile app.
      *
      * @param  stdClass $mobilesettings tool_mobile settings
-     * @return string base64 data image contents
+     * @return string base64 data image contents, null if qr disabled
      */
     public static function generate_login_qrcode(stdClass $mobilesettings) {
         global $CFG, $USER;
 
+        if ($mobilesettings->qrcodetype == static::QR_CODE_DISABLED) {
+            return null;
+        }
+
         $urlscheme = !empty($mobilesettings->forcedurlscheme) ? $mobilesettings->forcedurlscheme : 'moodlemobile';
-        $qrloginkey = static::get_qrlogin_key();
-        $data = $urlscheme . '://' . $CFG->wwwroot . '?qrlogin=' . $qrloginkey . '&userid=' . $USER->id;
+        $data = $urlscheme . '://' . $CFG->wwwroot;
+
+        if ($mobilesettings->qrcodetype == static::QR_CODE_LOGIN) {
+            $qrloginkey = static::get_qrlogin_key();
+            $data .= '?qrlogin=' . $qrloginkey . '&userid=' . $USER->id;
+        }
 
         $qrcode = new core_qrcode($data);
         $imagedata = 'data:image/png;base64,' . base64_encode($qrcode->getBarcodePngData(5, 5));
index 55dc950..fa13085 100644 (file)
@@ -628,9 +628,9 @@ class external extends external_api {
         // We need this to make work the format text functions.
         $PAGE->set_context($context);
 
-        $enableqrlogin = get_config('tool_mobile', 'enableqrlogin');
-        if (empty($enableqrlogin)) {
-            throw new moodle_exception('QR login not enabled');
+        $qrcodetype = get_config('tool_mobile', 'qrcodetype');
+        if ($qrcodetype != api::QR_CODE_LOGIN) {
+            throw new moodle_exception('qrcodedisabled', 'tool_mobile');
         }
 
         // Only requests from the Moodle mobile or desktop app. This enhances security to avoid any type of XSS attack.
index 462b474..789cfd2 100644 (file)
@@ -60,8 +60,6 @@ $string['disabledfeatures_desc'] = 'Select here the features you want to disable
 $string['displayerrorswarning'] = 'Display debug messages (debugdisplay) is enabled. It should be disabled.';
 $string['downloadcourse'] = 'Download course';
 $string['downloadcourses'] = 'Download courses';
-$string['enableqrlogin'] = 'Enable QR login';
-$string['enableqrlogin_desc'] = 'If enabled, a QR code that will log users in into the site will be displayed in the users profile page. Only works in sites with https enabled.';
 $string['enablesmartappbanners'] = 'Enable App Banners';
 $string['enablesmartappbanners_desc'] = 'If enabled, a banner promoting the mobile app will be displayed when accessing the site using a mobile browser.';
 $string['forcedurlscheme'] = 'If you want to allow only your custom branded app to be opened via a browser window, then specify its URL scheme here. If you want to allow only the official app, then set the default value. Leave the field empty if you want to allow any app.';
@@ -98,9 +96,15 @@ $string['oauth2identityproviders'] = 'OAuth 2 identity providers';
 $string['offlineuse'] = 'Offline use';
 $string['pluginname'] = 'Moodle app tools';
 $string['pluginnotenabledorconfigured'] = 'Plugin not enabled or configured.';
-$string['qrcodeformobileapplogin'] = 'QR code for mobile app login';
-$string['qrcodeformobileapploginabout'] = 'Scan this code in your mobile app and you will be automatically logged in into this site. The code expires in {$a} minutes.';
-$string['qrsiteadminsnotallowed'] = 'For security reasons login via QR code is not allowed to site administrators.';
+$string['qrcodedisabled'] = 'Access via QR code disabled';
+$string['qrcodeformobileappaccess'] = 'QR code for mobile app access';
+$string['qrcodeformobileapploginabout'] = 'Scan the QR code with your mobile app and you will be automatically logged in. The QR code will expire in {$a} minutes.';
+$string['qrcodeformobileappurlabout'] = 'Scan the QR code with your mobile app to fill in the site URL in your app.';
+$string['qrsiteadminsnotallowed'] = 'For security reasons login via QR code is not allowed for site administrators or if you are logged in as another user.';
+$string['qrcodetype'] = 'QR code access';
+$string['qrcodetype_desc'] = 'A QR code can be provided for mobile app users to scan and either have the site URL filled in or be automatically logged in without having to enter their credentials.';
+$string['qrcodetypeurl'] = 'QR code with site URL';
+$string['qrcodetypelogin'] = 'QR code with automatic login';
 $string['readingthisemailgettheapp'] = 'Reading this in an email? <a href="{$a}">Download the mobile app and receive notifications on your mobile device</a>.';
 $string['remoteaddons'] = 'Remote add-ons';
 $string['selfsignedoruntrustedcertificatewarning'] = 'It seems that the HTTPS certificate is self-signed or not trusted. The mobile app will only work with trusted sites.';
index c40d7aa..43d6cc2 100644 (file)
@@ -129,25 +129,36 @@ function tool_mobile_myprofile_navigation(\core_user\output\myprofile\tree $tree
     $newnodes = [];
     $mobilesettings = get_config('tool_mobile');
 
-    // Check if we should display a QR code for quick login.
-    if (is_https() && !empty($mobilesettings->enableqrlogin)) {
-        $qrcodeforappstr = get_string('qrcodeformobileapplogin', 'tool_mobile');
-
-        if (is_siteadmin()) {
-            $mobileqr = get_string('qrsiteadminsnotallowed', 'tool_mobile');
-        } else {
+    // Check if we should display a QR code.
+    if (!empty($mobilesettings->qrcodetype)) {
+        $mobileqr = null;
+        $qrcodeforappstr = get_string('qrcodeformobileappaccess', 'tool_mobile');
+
+        if ($mobilesettings->qrcodetype == tool_mobile\api::QR_CODE_LOGIN && is_https()) {
+
+            if (is_siteadmin() || \core\session\manager::is_loggedinas()) {
+                $mobileqr = get_string('qrsiteadminsnotallowed', 'tool_mobile');
+            } else {
+                $qrcodeimg = tool_mobile\api::generate_login_qrcode($mobilesettings);
+
+                $minutes = tool_mobile\api::LOGIN_QR_KEY_TTL / MINSECS;
+                $mobileqr = html_writer::tag('p', get_string('qrcodeformobileapploginabout', 'tool_mobile', $minutes));
+                $mobileqr .= html_writer::link('#qrcode', get_string('viewqrcode', 'tool_mobile'),
+                    ['class' => 'btn btn-primary mt-2', 'data-toggle' => 'collapse',
+                    'role' => 'button', 'aria-expanded' => 'false']);
+                $mobileqr .= html_writer::div(html_writer::img($qrcodeimg, $qrcodeforappstr), 'collapse mt-4', ['id' => 'qrcode']);
+            }
 
+        } else if ($mobilesettings->qrcodetype == tool_mobile\api::QR_CODE_URL) {
             $qrcodeimg = tool_mobile\api::generate_login_qrcode($mobilesettings);
 
-            $minutes = tool_mobile\api::LOGIN_QR_KEY_TTL / MINSECS;
-
-            $mobileqr = get_string('qrcodeformobileapploginabout', 'tool_mobile', $minutes);
-            $mobileqr .= html_writer::link('#qrcode', get_string('viewqrcode', 'tool_mobile'),
-                ['class' => 'btn btn-primary mt-2', 'data-toggle' => 'collapse', 'role' => 'button', 'aria-expanded' => 'false']);
-            $mobileqr .= html_writer::div(html_writer::img($qrcodeimg, $qrcodeforappstr), 'collapse mt-4', ['id' => 'qrcode']);
+            $mobileqr = get_string('qrcodeformobileappurlabout', 'tool_mobile');
+            $mobileqr .= html_writer::div(html_writer::img($qrcodeimg, $qrcodeforappstr));
         }
 
-        $newnodes[] = new core_user\output\myprofile\node('mobile', 'mobileappqr', $qrcodeforappstr, null, null, $mobileqr);
+        if ($mobileqr) {
+            $newnodes[] = new core_user\output\myprofile\node('mobile', 'mobileappqr', $qrcodeforappstr, null, null, $mobileqr);
+        }
     }
 
     // Check if the user is using the app, encouraging him to use it otherwise.
index 2655ad8..732bd71 100644 (file)
@@ -70,9 +70,14 @@ if ($hassiteconfig) {
                     new lang_string('typeoflogin', 'tool_mobile'),
                     new lang_string('typeoflogin_desc', 'tool_mobile'), 1, $options));
 
-        $temp->add(new admin_setting_configcheckbox('tool_mobile/enableqrlogin',
-                    new lang_string('enableqrlogin', 'tool_mobile'),
-                    new lang_string('enableqrlogin_desc', 'tool_mobile'), 1));
+        $options = [
+            tool_mobile\api::QR_CODE_DISABLED => new lang_string('qrcodedisabled', 'tool_mobile'),
+            tool_mobile\api::QR_CODE_URL => new lang_string('qrcodetypeurl', 'tool_mobile'),
+            tool_mobile\api::QR_CODE_LOGIN => new lang_string('qrcodetypelogin', 'tool_mobile'),
+        ];
+        $temp->add(new admin_setting_configselect('tool_mobile/qrcodetype',
+                    new lang_string('qrcodetype', 'tool_mobile'),
+                    new lang_string('qrcodetype_desc', 'tool_mobile'), tool_mobile\api::QR_CODE_LOGIN, $options));
 
         $temp->add(new admin_setting_configtext('tool_mobile/forcedurlscheme',
                     new lang_string('forcedurlscheme_key', 'tool_mobile'),
index 7d024ec..7b05175 100644 (file)
@@ -643,9 +643,9 @@ class tool_mobile_external_testcase extends externallib_advanced_testcase {
         $this->resetAfterTest(true);
         $this->setAdminUser();
 
-        set_config('enableqrlogin', 1, 'tool_mobile');
+        set_config('qrcodetype', tool_mobile\api::QR_CODE_DISABLED, 'tool_mobile');
 
-        $this->expectException('moodle_exception');
+        $this->expectExceptionMessage(get_string('qrcodedisabled', 'tool_mobile'));
         $result = external::get_tokens_for_qr_login('', $USER->id);
     }