owncloud-archive / apps

Repo for ownCloud apps. Code here is work in progress and not intended for endusers
373 stars 337 forks source link

login IMAP authentication, default quota, auto add to group #2107

Open crysman opened 9 years ago

crysman commented 9 years ago

I've been pointed here from https://forum.owncloud.org/viewtopic.php?f=31&t=30651#p97503 so I do so.

The problem: I have some problems with my owncloud settings related to IMAP authentication.

  1. setting default quota does not work - when I login to cloud as admin, in the users, there is "default" instead of "333 MB"
  2. setting default group does not work - user appears with no group membership
  3. I do not wish to set these things every login, but just once when the very first login occurs

Here is my modified imap.php file (/var/www/owncloud/apps/user_external/lib/imap.php):

<?php
/**
 * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
 * This file is licensed under the Affero General Public License version 3 or
 * later.
 * See the COPYING-README file.
 */

/**
 * User authentication against an IMAP mail server
 *
 * @category Apps
 * @package  UserExternal
 * @author   Robin Appelman <icewind@owncloud.com>
 * @license  http://www.gnu.org/licenses/agpl AGPL
 * @link     http://github.com/owncloud/apps
 */
class OC_User_IMAP extends \OCA\user_external\Base {
   private $mailbox;

   /**
    * Create new IMAP authentication provider
    *
    * @param string $mailbox PHP imap_open mailbox definition, e.g.
    *                        {127.0.0.1:143/imap/readonly}
    */
   public function __construct($mailbox) {
      parent::__construct($mailbox);
      $this->mailbox=$mailbox;
   }

   /**
    * Check if the password is correct without logging in the user
    *
    * @param string $uid      The username
    * @param string $password The password
    *
    * @return true/false
    */
   public function checkPassword($uid, $password) {
      if (!function_exists('imap_open')) {
         OCP\Util::writeLog('user_external', 'ERROR: PHP imap extension is not installed', OCP\Util::ERROR);
         return false;
      }
      $mbox = @imap_open($this->mailbox, $uid, $password, OP_HALFOPEN, 1);
      imap_errors();
      imap_alerts();
      if($mbox !== FALSE) {
         imap_close($mbox);
         $uid = mb_strtolower($uid);
      /* START added/edited by crysman 2015-08 ...*/
         //protection against whole e-mail input (we want users to login just with the part before @):
         if( stripos($uid, "@") == false ) {
            $this->storeUser($uid);
         } else {
            return false;
         }
                        $config = \OC::$server->getConfig();

         //Set default quota:
                        if($config->getUserValue($uid, 'files', 'quota') === null) {
                          $config->setUserValue($uid, 'files', 'quota', '333 MB');
                        }

                        //Set the IMAP user's email to their login:
                        $config->setUserValue( $uid, 'settings', 'email', $uid.'@ourdomain.cz');

                        //Add a new user automatically to "myFavouriteGroup" group:
                        $user = \OC::$server->getUserSession()->getUser();
                        if($user !== null) {
                          $group = \OC::$server->getGroupManager()->get('myFavouriteGroup');
                          if(!$group->inGroup($user)) {
                            $group->addUser($user);
                          }
                        }
      /* END crysman*/
         return $uid;
      }else{
         return false;
      }
   }
}

Modified lines are marked by "START added/edited by crysman 2015-08" comment. The rest is unchanged from the original.

Steps to reproduce

enable the plugin and try it

Expected behaviour

  1. I want a code that makes all the three steps above just once on the first login.
  2. I want the code to actually work

    Actual behaviour

  3. obviously, the email is set every login
  4. the rest does not work at all

    Server configuration

Operating system: Debian GNU/Linux 7.9 (wheezy)

Web server: Apache/2.4.10 (Debian)

Database: mysql Ver 15.1 Distrib 10.0.20-MariaDB

PHP version: PHP 5.5.27

ownCloud version: (see ownCloud admin page) ownCloud 8.0.4 (stable)

Updated from an older ownCloud or fresh install: update

...not important in the context

crysman commented 9 years ago

Please, before considering it as "Enhancement" for developers, any hints how could I make it work myself? Why the trivial setting default quota and group does not work? Wrong variables? Wrong syntax? I do not get it... Thanks a lot.

ghost commented 9 years ago

Hi,

if you want to implement this yourself its probably better to ask for help at the developers mailinglist:

https://mailman.owncloud.org/mailman/listinfo/devel

or the IRC channel #owncloud-dev on freenode as written in your forums post.

crysman commented 8 years ago

OK, I've just asked on devel mailing list, let's hope they will not redirect me again to some other site/resource.

If I come up to the solution, I will public it here (if somebody else doesn't make it here right ahead :)

emm3t commented 8 years ago

Did this get incorporated into a definitive solution? The problem I have is (probably) the trivial bit. I just want users to be able to login as username instead of username@domain.com and the account that is created is username. Any hints would be appreciated

crysman commented 8 years ago

Unfortunately not :(

Well, this line of code

$config->setUserValue( $uid, 'settings', 'email', $uid.'@ourdomain.cz');

does work. The problem is that it is being executed all over and over again on every login of every user... That is not optimal at all...

Just don't forget to treat the input first:

         //protection against whole e-mail input (we want users to login just with the part before @):
         if( stripos($uid, "@") == false ) {
            $this->storeUser($uid);
         } else {
            return false;
         }
alexschomb commented 8 years ago

I guess the best way to implement this would be a cronjob that implements the owncloud API. Unfortunately I don't know how to start. Has anyone got a cron snippet?

crysman commented 8 years ago

I disagree with cronjob, this is something the IMAP plugin should be capable of handling. Having some part in plugin and other in cron (or something else) makes things less transparent and lot harder to maintain...

alexschomb commented 8 years ago

There are certain benefits of a cronjob over the authentication plugin itself. Think about sessions. The authentication script (checkPassword) will run only if users login. This means all changes to your IMAP user structure (banning users, deleting accounts, ...) will only take part if the session / cookie runs out or the user signs in again. This can invoke sincere security problems.

hdezela commented 8 years ago

Here's a quick and dirty cron job I use for this:

<?php
// FUNCIONES BASICAS
require_once('/home/webdata/script/funciones.php');

// ALGUNOS VARIABLES NECESARIOS
$raiz_nube = '/home/webdata/owncloud';
$def_quota = '256 MB';
$def_group = 'Winet';
$actualiza = array();

// SACAMOS TODOS LOS USUARIOS EXTERNOS
$usuarios = sqlNube("SELECT uid FROM oc_users_external");

// VERIFICAMOS LOS DATOS
foreach($usuarios['data'] as $k=>$v) {
    // POR DEFAULT NO HACEMOS NADA
    $actualiza[$v['uid']]['quota'] = FALSE;
    $actualiza[$v['uid']]['group'] = FALSE;

    // PRIMERO LA QUOTA
    $quota = sqlNube("SELECT configvalue FROM oc_preferences WHERE userid = '".$v['uid']."' AND appid = 'files' AND configkey = 'quota'");
    if($quota['total'] < 1) {
        // SI NO ESTA, PONEMOS
        $actualiza[$v['uid']]['quota'] = "insert";
    } elseif($quota['data'][0]['configvalue'] != $def_quota) {
        // SI NO ES IGUAL, CAMBIAMOS
        $actualiza[$v['uid']]['quota'] = "update";
    }

    // AHORA EL GRUPO
    $group = sqlNube("SELECT gid FROM oc_group_user WHERE uid = '".$v['uid']."'");
    if($group['total'] < 1) {
        // SI NO ESTA, PONEMOS
        $actualiza[$v['uid']]['group'] = "insert";
    } elseif($group['data'][0]['gid'] != $def_group) {
        // SI NO ES IGUAL, CAMBIAMOS
        $actualiza[$v['uid']]['group'] = "update";
    }
}

// ACTUALIZAMOS LO NECESARIO
foreach($actualiza as $k=>$v) {
    // QUOTA
    switch($v['quota']) {
        case "insert": sqlNube("INSERT INTO oc_preferences (userid,appid,configkey,configvalue) VALUES('".$k."','files','quota','".$def_quota."')"); break;
        case "update": sqlNube("UPDATE oc_preferences SET configvalue = '".$def_quota."' WHERE userid = '".$k."' AND appid = 'files' AND configkey = 'quota'"); break;
    }
    // GRUPO
    switch($v['group']) {
        case "insert": sqlNube("INSERT INTO oc_group_user (gid,uid) VALUES('".$def_group."','".$k."')"); break;
        case "update": sqlNube("UPDATE oc_group_user SET gid = '".$def_group."' WHERE uid = '".$k."'"); break;
    }
}

It looks up all external users and checks if the settings are equal to the defaults, then either creates or updates them. I've had it working for about a week without issues. Maybe more eyes can help refine it.