diff --git a/app/config/app.php b/app/config/app.php index 75e25d39ef..3b7286afa5 100755 --- a/app/config/app.php +++ b/app/config/app.php @@ -156,7 +156,8 @@ return array( 'Str' => 'Illuminate\Support\Str', 'URL' => 'Illuminate\Support\Facades\URL', 'Validator' => 'Illuminate\Support\Facades\Validator', - 'View' => 'Illuminate\Support\Facades\View' + 'View' => 'Illuminate\Support\Facades\View', + 'Reader' => 'League\Csv\Reader', ), diff --git a/app/controllers/admin/UsersController.php b/app/controllers/admin/UsersController.php index b33ca25afa..f02220b865 100755 --- a/app/controllers/admin/UsersController.php +++ b/app/controllers/admin/UsersController.php @@ -21,6 +21,8 @@ use Sentry; use Validator; use View; use Chumper\Datatable\Facades\Datatable; +use League\Csv\Reader; +use Mail; class UsersController extends AdminController { @@ -149,7 +151,7 @@ class UsersController extends AdminController // permissions here before we create the user. // Get the inputs, with some exceptions - $inputs = Input::except('csrf_token', 'password_confirm', 'groups'); + $inputs = Input::except('csrf_token', 'password_confirm', 'groups','email_user'); // @TODO: Figure out WTF I need to do this. if ($inputs['manager_id']=='') { @@ -174,6 +176,22 @@ class UsersController extends AdminController // Redirect to the new user page //return Redirect::route('update/user', $user->id)->with('success', $success); + + if (Input::get('email_user')==1) { + // Send the credentials through email + + $data = array(); + $data['email'] = e(Input::get('email')); + $data['first_name'] = e(Input::get('first_name')); + $data['password'] = e(Input::get('password')); + + Mail::send('emails.send-login', $data, function ($m) use ($user) { + $m->to($user->email, $user->first_name . ' ' . $user->last_name); + $m->subject('Welcome ' . $user->first_name); + }); + } + + return Redirect::route('users')->with('success', $success); } @@ -601,5 +619,122 @@ class UsersController extends AdminController return Redirect::route('users')->with('error', $error); } } + + /** + * User import. + * + * @return View + */ + public function getImport() + { + // Get all the available groups + $groups = Sentry::getGroupProvider()->findAll(); + // Selected groups + $selectedGroups = Input::old('groups', array()); + // Get all the available permissions + $permissions = Config::get('permissions'); + $this->encodeAllPermissions($permissions); + // Selected permissions + $selectedPermissions = Input::old('permissions', array('superuser' => -1)); + $this->encodePermissions($selectedPermissions); + // Show the page + return View::make('backend/users/import', compact('groups', 'selectedGroups', 'permissions', 'selectedPermissions')); + } + + + /** + * User import form processing. + * + * @return Redirect + */ + public function postImport() + { + + if (! ini_get("auto_detect_line_endings")) { + ini_set("auto_detect_line_endings", '1'); + } + + $csv = Reader::createFromPath(Input::file('user_import_csv')); + $csv->setNewline("\r\n"); + + if (Input::get('has_header')==1) { + $csv->setOffset(1); + } + + $duplicates = ''; + + $nbInsert = $csv->each(function ($row) use ($duplicates) { + + if (Input::get('activate')==1) { + $activated = '1'; + } else { + $activated = ''; + } + + + if (Input::get('generate_password')==1) { + $pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 10); + } else { + $pass = ''; + } + + + try { + // Check if this email already exists in the system + $user = DB::table('users')->where('email', $row[2])->first(); + if ($user) { + $duplicates .= $row[2].', '; + } else { + + $newuser = array( + 'first_name' => $row[0], + 'last_name' => $row[1], + 'email' => $row[2], + 'password' => $pass, + 'activated' => $activated, + 'permissions' => '{"user":1}' + ); + + DB::table('users')->insert($newuser); + + $udpateuser = Sentry::findUserByLogin($row[2]); + + // Update the user details + $udpateuser->password = $pass; + + // Update the user + $udpateuser->save(); + + + if (Input::get('email_user')==1) { + // Send the credentials through email + + $data = array(); + $data['email'] = $row[2]; + $data['first_name'] = $row[0]; + $data['password'] = $pass; + + Mail::send('emails.send-login', $data, function ($m) use ($newuser) { + $m->to($newuser['email'], $newuser['first_name'] . ' ' . $newuser['last_name']); + $m->subject('Welcome ' . $newuser['first_name']); + }); + } + } + + + } catch (Exception $e) { + echo 'Caught exception: ', $e->getMessage(), "\n"; + } + return true; + + + }); + + return Redirect::route('users')->with('duplicates',$duplicates)->with('success', 'Success'); + + } + + + } diff --git a/app/lang/en/admin/users/general.php b/app/lang/en/admin/users/general.php index 25e9bfb75c..550a32854d 100755 --- a/app/lang/en/admin/users/general.php +++ b/app/lang/en/admin/users/general.php @@ -11,4 +11,5 @@ return array( 'last_login' => 'Last Login', 'software_user' => 'Software Checked out to :name', 'view_user' => 'View User :name', + 'usercsv' => 'CSV file', ); diff --git a/app/lang/en/admin/users/message.php b/app/lang/en/admin/users/message.php index 53f2777981..7a14e68398 100755 --- a/app/lang/en/admin/users/message.php +++ b/app/lang/en/admin/users/message.php @@ -18,14 +18,16 @@ return array( 'unban' => 'User was successfully unbanned.', 'suspend' => 'User was successfully suspended.', 'unsuspend' => 'User was successfully unsuspended.', - 'restored' => 'User was successfully restored.' + 'restored' => 'User was successfully restored.', ++ 'import' => 'Users imported successfully.', ), 'error' => array( 'create' => 'There was an issue creating the user. Please try again.', 'update' => 'There was an issue updating the user. Please try again.', 'delete' => 'There was an issue deleting the user. Please try again.', - 'unsuspend' => 'There was an issue unsuspending the user. Please try again.' + 'unsuspend' => 'There was an issue unsuspending the user. Please try again.', + 'import' => 'There was an issue importing users. Please try again.', ), ); diff --git a/app/routes.php b/app/routes.php index 2af0ada0cb..e78f2cb017 100755 --- a/app/routes.php +++ b/app/routes.php @@ -193,6 +193,8 @@ Route::group(array('prefix' => 'admin', 'before' => 'admin-auth', 'namespace' => Route::get('/', array('as' => 'users', 'uses' => 'UsersController@getIndex')); Route::get('create', array('as' => 'create/user', 'uses' => 'UsersController@getCreate')); Route::post('create', 'UsersController@postCreate'); + Route::get('import', array('as' => 'import/user', 'uses' => 'UsersController@getImport')); + Route::post('import', 'UsersController@postImport'); Route::get('{userId}/edit', array('as' => 'update/user', 'uses' => 'UsersController@getEdit')); Route::post('{userId}/edit', 'UsersController@postEdit'); Route::get('{userId}/clone', array('as' => 'clone/user', 'uses' => 'UsersController@getClone')); diff --git a/app/views/backend/layouts/default.blade.php b/app/views/backend/layouts/default.blade.php index 1223757530..a934a25559 100644 --- a/app/views/backend/layouts/default.blade.php +++ b/app/views/backend/layouts/default.blade.php @@ -288,7 +288,14 @@ @endif -
  • @lang('admin/hardware/general.requestable')
  • +
    ' : '>') }} + + + @lang('admin/hardware/general.requestable') + + + + diff --git a/app/views/backend/users/edit.blade.php b/app/views/backend/users/edit.blade.php index 35bcae8ec8..8a37e785a0 100755 --- a/app/views/backend/users/edit.blade.php +++ b/app/views/backend/users/edit.blade.php @@ -186,6 +186,7 @@ + @@ -211,6 +212,16 @@ + + +
    +
    +
    +
    + {{ Form::checkbox('email_user', '1', Input::old('email_user')) }} Email this user their credentials? +
    +
    + diff --git a/app/views/backend/users/import.blade.php b/app/views/backend/users/import.blade.php new file mode 100644 index 0000000000..3086ed20e6 --- /dev/null +++ b/app/views/backend/users/import.blade.php @@ -0,0 +1,122 @@ +@extends('backend/layouts/default') + +{{-- Page title --}} +@section('title') +Create a User :: +@parent +@stop + +{{-- Page content --}} +@section('content') + + + + +
    + + + + +
    + +
    +
    + @if (Session::get('message')) +

    + You have an error in your CSV file:
    + {{ Session::get('message') }} +

    + @endif + +

    + Upload a CSV file with one or more users. Passwords will be auto-generated. Selecting a group will add that group to all imported users. Follow this format, new line per user:
    + firstName,lastName,email +

    + +
    + +
    + +
    +
    + + +
    +
    +
    +
    + {{ Form::checkbox('has_headers', '1', Input::old('has_headers')) }} This CSV has a header row +
    +
    + + + +
    +
    +
    +
    + {{ Form::checkbox('email_user', '1', Input::old('email_user')) }} Email these users their credentials? +
    +
    + + + +
    +
    +
    +
    + {{ Form::checkbox('generate_password', '1', Input::old('generate_password')) }} Auto-generate passwords? +
    +
    + + +
    +
    +
    +
    + {{ Form::checkbox('activate', '1', Input::old('activate')) }} Activate user? +
    +
    + + + +
    +
    + + +
    +
    + @lang('button.cancel') + +
    +
    + +
    + + +@stop \ No newline at end of file diff --git a/app/views/backend/users/index.blade.php b/app/views/backend/users/index.blade.php index e1ffec354b..017c97df7b 100755 --- a/app/views/backend/users/index.blade.php +++ b/app/views/backend/users/index.blade.php @@ -11,6 +11,7 @@
    + Import @lang('general.create') @if (Input::get('onlyTrashed')) Show Current Users diff --git a/app/views/emails/send-login.blade.php b/app/views/emails/send-login.blade.php new file mode 100644 index 0000000000..6f25eaceb0 --- /dev/null +++ b/app/views/emails/send-login.blade.php @@ -0,0 +1,16 @@ +@extends('emails/layouts/default') + +@section('content') +

    Hello {{{ $first_name }}},

    + +

    An administrator has created an account for you on the {{{ Setting::getSettings()->site_name }}} website.

    + +

    URL: {{ Config::get('app.url') }}
    +Login: {{{ $email }}}
    +Password: {{{ $password }}} +

    + +

    Best regards,

    + +

    {{{ Setting::getSettings()->site_name }}}

    +@stop diff --git a/composer.json b/composer.json index e6b395f00e..bb9728ed15 100755 --- a/composer.json +++ b/composer.json @@ -23,7 +23,8 @@ "barryvdh/laravel-debugbar": "1.x", "chumper/datatable": "dev-master", "bacon/bacon-qr-code": "dev-master", - "intervention/image": "dev-master" + "intervention/image": "dev-master", + "league/csv": "~7.0" }, "require-dev": { "phpunit/phpunit": "*", diff --git a/composer.lock b/composer.lock index 74a3207ba3..df92449a97 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "4242b20dc02d70aa7d97a211ea1e58b8", + "hash": "184f0469476babea7ab1e609f265b691", "packages": [ { "name": "bacon/bacon-qr-code", @@ -423,12 +423,12 @@ "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "15334410a781da60f861df536b460f24c8f01eeb" + "reference": "6c5c32eb6c596993d04e13b95d0c1e8153783d7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/15334410a781da60f861df536b460f24c8f01eeb", - "reference": "15334410a781da60f861df536b460f24c8f01eeb", + "url": "https://api.github.com/repos/doctrine/cache/zipball/6c5c32eb6c596993d04e13b95d0c1e8153783d7a", + "reference": "6c5c32eb6c596993d04e13b95d0c1e8153783d7a", "shasum": "" }, "require": { @@ -485,7 +485,7 @@ "cache", "caching" ], - "time": "2015-02-01 04:40:53" + "time": "2015-02-16 12:24:01" }, { "name": "doctrine/collections", @@ -559,12 +559,12 @@ "source": { "type": "git", "url": "https://github.com/doctrine/common.git", - "reference": "56360cc13bfd13893731c6c4d1d82005a61d7694" + "reference": "f1004b8b336465fafd498ee6539cc2502d16f98f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/56360cc13bfd13893731c6c4d1d82005a61d7694", - "reference": "56360cc13bfd13893731c6c4d1d82005a61d7694", + "url": "https://api.github.com/repos/doctrine/common/zipball/f1004b8b336465fafd498ee6539cc2502d16f98f", + "reference": "f1004b8b336465fafd498ee6539cc2502d16f98f", "shasum": "" }, "require": { @@ -624,7 +624,7 @@ "persistence", "spl" ], - "time": "2015-01-23 18:43:22" + "time": "2015-02-16 02:14:17" }, { "name": "doctrine/dbal", @@ -1132,6 +1132,61 @@ ], "time": "2014-09-15 02:45:24" }, + { + "name": "league/csv", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/csv.git", + "reference": "0d3c28bf20ad26e1e23599e1746aaf7c680c0477" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/0d3c28bf20ad26e1e23599e1746aaf7c680c0477", + "reference": "0d3c28bf20ad26e1e23599e1746aaf7c680c0477", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Csv\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://github.com/nyamsprod/", + "role": "Developer" + } + ], + "description": "Csv data manipulation made easy in PHP", + "keywords": [ + "csv", + "export", + "filter", + "import", + "read", + "write" + ], + "time": "2015-02-17 13:59:21" + }, { "name": "maximebf/debugbar", "version": "dev-master", @@ -1312,12 +1367,12 @@ "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "1366e833a16c4267883187da6da7b317f0582dd7" + "reference": "53eac36a3f7a116103f50dee0669451ccec35a44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1366e833a16c4267883187da6da7b317f0582dd7", - "reference": "1366e833a16c4267883187da6da7b317f0582dd7", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/53eac36a3f7a116103f50dee0669451ccec35a44", + "reference": "53eac36a3f7a116103f50dee0669451ccec35a44", "shasum": "" }, "require": { @@ -1349,7 +1404,7 @@ "parser", "php" ], - "time": "2015-01-31 21:59:38" + "time": "2015-02-13 17:03:18" }, { "name": "patchwork/utf8", @@ -2080,12 +2135,12 @@ "source": { "type": "git", "url": "https://github.com/symfony/Filesystem.git", - "reference": "177e0a8e29fab3f0556f7a973b5a42935e42a4d7" + "reference": "cb5db1cf2440ceb68760ef0e70f9d1d4ba135444" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Filesystem/zipball/177e0a8e29fab3f0556f7a973b5a42935e42a4d7", - "reference": "177e0a8e29fab3f0556f7a973b5a42935e42a4d7", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/cb5db1cf2440ceb68760ef0e70f9d1d4ba135444", + "reference": "cb5db1cf2440ceb68760ef0e70f9d1d4ba135444", "shasum": "" }, "require": { @@ -2118,7 +2173,7 @@ ], "description": "Symfony Filesystem Component", "homepage": "http://symfony.com", - "time": "2015-02-11 07:17:51" + "time": "2015-02-16 09:13:25" }, { "name": "symfony/finder", @@ -2741,12 +2796,12 @@ "source": { "type": "git", "url": "https://github.com/padraic/mockery.git", - "reference": "f770ab0cf167cccf1a701f28411fbfc9971ff90e" + "reference": "f699a69af1f0a5a314107455e6150cfadce33e6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/padraic/mockery/zipball/f770ab0cf167cccf1a701f28411fbfc9971ff90e", - "reference": "f770ab0cf167cccf1a701f28411fbfc9971ff90e", + "url": "https://api.github.com/repos/padraic/mockery/zipball/f699a69af1f0a5a314107455e6150cfadce33e6b", + "reference": "f699a69af1f0a5a314107455e6150cfadce33e6b", "shasum": "" }, "require": { @@ -2799,7 +2854,7 @@ "test double", "testing" ], - "time": "2015-02-11 12:43:02" + "time": "2015-02-15 16:05:06" }, { "name": "phpdocumentor/reflection-docblock", @@ -2807,12 +2862,12 @@ "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "09352d340640520f1047ff29f7a8e73129e2eb1c" + "reference": "ff902a0beb121a13a4d3c604bd6778a25aeae07a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/09352d340640520f1047ff29f7a8e73129e2eb1c", - "reference": "09352d340640520f1047ff29f7a8e73129e2eb1c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/ff902a0beb121a13a4d3c604bd6778a25aeae07a", + "reference": "ff902a0beb121a13a4d3c604bd6778a25aeae07a", "shasum": "" }, "require": { @@ -2848,7 +2903,7 @@ "email": "mike.vanriel@naenius.com" } ], - "time": "2015-02-03 20:57:02" + "time": "2015-02-12 12:17:11" }, { "name": "phpspec/prophecy", @@ -2856,12 +2911,12 @@ "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "3a9204c44667c302049ab4eadb02daab789e19ed" + "reference": "9ed07757cd5c46fe33d28826327d274bd142a143" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3a9204c44667c302049ab4eadb02daab789e19ed", - "reference": "3a9204c44667c302049ab4eadb02daab789e19ed", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/9ed07757cd5c46fe33d28826327d274bd142a143", + "reference": "9ed07757cd5c46fe33d28826327d274bd142a143", "shasum": "" }, "require": { @@ -2908,7 +2963,7 @@ "spy", "stub" ], - "time": "2015-02-09 17:43:38" + "time": "2015-02-16 14:11:36" }, { "name": "phpunit/php-code-coverage",