From 13a6e1e8be29b115f2c18816cb00fd4bf21ab4ea Mon Sep 17 00:00:00 2001 From: Sergi Tur Badenas Date: Thu, 13 Jul 2017 13:18:24 +0200 Subject: [PATCH] Sync --- composer.json | 1 + config/users.php | 56 ++++- ...07_13_172230_create_google_users_table.php | 56 +++++ resources/views/googleApps/google.blade.php | 17 ++ .../Controllers/GoogleAppsUsersController.php | 220 ++++++++++++++++++ .../Controllers/UsersMigrationController.php | 20 +- src/Http/routes.php | 15 ++ src/Models/GoogleApps/GoogleUser.php | 20 ++ .../UsersManagementServiceProvider.php | 27 ++- src/Services/GoogleApps/GoogleAppsService.php | 141 +++++++++++ src/Services/UserMigrations.php | 9 +- src/Traits/HasPaginator.php | 31 +++ src/Traits/HasUserMigrations.php | 1 + src/helpers.php | 9 + 14 files changed, 616 insertions(+), 7 deletions(-) create mode 100644 database/migrations/2017_07_13_172230_create_google_users_table.php create mode 100644 resources/views/googleApps/google.blade.php create mode 100644 src/Http/Controllers/GoogleAppsUsersController.php create mode 100644 src/Models/GoogleApps/GoogleUser.php create mode 100644 src/Services/GoogleApps/GoogleAppsService.php create mode 100644 src/Traits/HasPaginator.php diff --git a/composer.json b/composer.json index 2ba972e..e63047c 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ "acacha/stateful-eloquent": "^0.1.3", "laravel/passport": "^2.0", "predis/predis": "^1.1", + "pulkitjalan/google-apiclient": "^3.1", "scool/ebre_escool_model": "dev-master", "spatie/laravel-permission": "^2.1", "venturecraft/revisionable": "^1.28" diff --git a/config/users.php b/config/users.php index 59b83d2..56ed6b2 100644 --- a/config/users.php +++ b/config/users.php @@ -26,9 +26,9 @@ /* |-------------------------------------------------------------------------- - | Register Acacha Stateful Service Provider? + | Register Acacha Stateful Service Provider? |-------------------------------------------------------------------------- - | Set this value to true to register Acacha\Stateful\Providers\StatefulServiceProvider. + | Set this value to true to register Acacha\Stateful\Providers\StatefulServiceProvider. | Remember to manually register the service provider in your config/app.php file if | this value is set to false. | @@ -36,6 +36,17 @@ 'register_acacha_stateful_service_provider' => true, + /* + |-------------------------------------------------------------------------- + | Register Google Service Provider? + |-------------------------------------------------------------------------- + | Set this value to true to register PulkitJalan\Google\GoogleServiceProvider::class. + | Remember to manually register the service provider in your config/app.php file if + | this value is set to false and you want Google API support. + | + */ + 'register_google_service_provider' => true, + /* |------------------------------------------------------------------------------------------------- | Register Acacha Stateful Service Provider? @@ -58,4 +69,45 @@ 'source_database_connection_name' => 'ebre_escool', + /* + |------------------------------------------------------------------------------------------------- + | Google apps/Suite domain. + |------------------------------------------------------------------------------------------------- + | The Google Apps/Suite domain. + | + */ + + 'google_apps_domain' => env('GOOGLE_APPS_DOMAIN', 'iesebre.com'), + + /* + |------------------------------------------------------------------------------------------------- + | Google apps admin user email + |------------------------------------------------------------------------------------------------- + | The Google Apps admin user email used to access to Google Apps. + | + */ + + 'google_apps_admin_user_email' => env('GOOGLE_APPS_ADMIN_USER_EMAIL', 'sergitur@iesebre.com'), + + /* + |------------------------------------------------------------------------------------------------- + | Google apps user email used to check connection to Google Apps. + |------------------------------------------------------------------------------------------------- + | The Google Apps user email used to check connection to Google Apps. + | + */ + + 'google_apps_user_email_to_check_connection' => + env('GOOGLE_APPS_USER_EMAIL_TO_CHECK_CONNECTION', 'stur@iesebre.com'), + + /* + |------------------------------------------------------------------------------------------------- + | Google apps users per page. + |------------------------------------------------------------------------------------------------- + | Google apps default value for users for page when paginating. + | + */ + + 'google_apps_users_per_page' => 15, + ]; diff --git a/database/migrations/2017_07_13_172230_create_google_users_table.php b/database/migrations/2017_07_13_172230_create_google_users_table.php new file mode 100644 index 0000000..df280ff --- /dev/null +++ b/database/migrations/2017_07_13_172230_create_google_users_table.php @@ -0,0 +1,56 @@ +increments('id'); + $table->string('customerId'); + $table->string('kind'); + $table->integer('google_id')->unsigned()->nullable(); + $table->string('etag'); + $table->string('primaryEmail')->unique(); + $table->string('givenName'); + $table->string('familyName'); + $table->string('fullName'); + $table->string('orgUnitPath'); + $table->json('organizations')->nullable(); + $table->boolean('isAdmin'); + $table->boolean('isDelegatedAdmin'); + $table->dateTime('lastLoginTime'); + $table->dateTime('creationTime'); + $table->dateTime('deletionTime')->nullable(); + $table->dateTime('agreedToTerms'); + $table->string('password')->nullable(); + $table->string('hashFunction')->nullable(); + $table->boolean('suspended'); + $table->string('suspensionReason')->nullable(); + $table->boolean('changePasswordAtNextLogin'); + $table->json('emails'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('google_users'); + } +} diff --git a/resources/views/googleApps/google.blade.php b/resources/views/googleApps/google.blade.php new file mode 100644 index 0000000..41211c3 --- /dev/null +++ b/resources/views/googleApps/google.blade.php @@ -0,0 +1,17 @@ +@extends('adminlte::page') + +@section('htmlheader_title') + Google Apps Users Management +@endsection + +@section('main-content') +
+
+ + + + + +
+
+@endsection \ No newline at end of file diff --git a/src/Http/Controllers/GoogleAppsUsersController.php b/src/Http/Controllers/GoogleAppsUsersController.php new file mode 100644 index 0000000..76718a0 --- /dev/null +++ b/src/Http/Controllers/GoogleAppsUsersController.php @@ -0,0 +1,220 @@ +service = $service; + } + + + /** + * Show Google apps users. + */ + public function index() + { + $this->authorize('see-google-apps-users'); + $data = []; + + return view('acacha_users::googleApps.google', $data); + } + + /** + * Sync local database from Google Apps/Suite data. + */ + public function localSync(Request $request) + { + $this->authorize('sync-google-apps-users'); + + return $this->service->localSync(); + } + + /** + * List Google apps users. + */ + public function all(Request $request) + { + $this->authorize('list-google-apps-users'); + + $perPage = config('users.google_apps_users_per_page' , 15); + if ($request->has('perPage')) { + $perPage = $request->input('perPage'); + } + + $users = $this->service->getUsers($perPage); + + return $this->paginate($users, $perPage); + } + + /** + * Check google apps connection. + * + * @return array + */ + public function check() + { + $this->authorize('check-google-apps-connection'); + + return $this->service->getConnectionState(); + } + + public function google3() + { + $directory = Google::make('directory'); + dump($directory->users); + } + + public function google5() + { + //List all users: https://developers.google.com/apps-script/advanced/admin-sdk-directory + +// page = AdminDirectory.Users.list({ +// domain: 'example.com', +// orderBy: 'givenName', +// maxResults: 100, +// pageToken: pageToken +// }); + } + + public function google4() + { + //Example list 100 users + $directory = Google::make('directory'); + dump(get_class($directory->users)); + dump($directory); + try { + $r = $directory->users->listUsers([ + 'domain' => 'iesebre.com', + 'maxResults' => 500 + ]); + dump($r); + } catch (\Exception $e) { + dd($e); + } + } + + public function google7() + { + //Example list 500 users. max results maxim value is 500 + $directory = Google::make('directory'); + dump(get_class($directory->users)); + try { + $r = $directory->users->listUsers([ + 'domain' => 'iesebre.com', + 'maxResults' => 500 + ]); + dump($r); + } catch (\Exception $e) { + dd($e); + } + } + + public function google8() + { + // Count total number of users + $directory = Google::make('directory'); + $count = 0; + $pageToken = null; + do { + try { + $r = $directory->users->listUsers([ + 'domain' => 'iesebre.com', + 'maxResults' => 500, + 'pageToken' => $pageToken + ]); + $pageToken = $r->nextPageToken; +// dump($pageToken); +// dump($r); +// dump($r->users); + $count = $count + count($r->users); + dump('count: ' . $count); + } catch (\Exception $e) { + dd($e); + } + } while ($pageToken); + + dd($count); + } + + public function google10() + { + return $this->service->localSync(); + } + + public function esborrar() + { + $googleClient = Google::getClient(); +// dd($googleClient); + $directory = Google::make('directory'); +// dd($directory); + + $email = "stur@iesebre.com"; + try { + $r = $directory->users->get($email); + if($r) { + echo "Name: ".$r->name->fullName."
"; + echo "Suspended?: ".(($r->suspended === true) ? 'Yes' : 'No')."
"; + echo "Org/Unit/Path: ".$r->orgUnitPath."
"; + } else { + echo "User does not exist: $email
"; + } + } catch (\Exception $e) { + dd('exception!!!'); + } + + // if the user doesn't exist, it's safe to create the new user + +// $user_to_impersonate = 'adminaccount@example.com'; +// $scopes = array('https://www.googleapis.com/auth/admin.directory.user'); +// $cred = new Google_Auth_AssertionCredentials( +// $service_account_name, +// $scopes, +// $key, +// 'notasecret', // Default P12 password +// 'http://oauth.net/grant_type/jwt/1.0/bearer', // Default grant type +// $user_to_impersonate +// ); + +//$dir = new Google_Service_Directory($client); +//$email = "possiblities@example.com"; +//$r = $dir->users->get($email); +//if($r) { +// echo "Name: ".$r->name->fullName."
"; +// echo "Suspended?: ".(($r->suspended === true) ? 'Yes' : 'No')."
"; +// echo "Org/Unit/Path: ".$r->orgUnitPath."
"; +//} else { +// echo "User does not exist: $email
"; +// // if the user doesn't exist, it's safe to create the new user +//} + } + +} \ No newline at end of file diff --git a/src/Http/Controllers/UsersMigrationController.php b/src/Http/Controllers/UsersMigrationController.php index 75aa6ee..5328988 100644 --- a/src/Http/Controllers/UsersMigrationController.php +++ b/src/Http/Controllers/UsersMigrationController.php @@ -174,7 +174,8 @@ protected function usersToMigrateByRequest($request) { if ($users = $request->has('users')) return $this->usersToMigrate($users, $request); if ($filter = $request->has('filter')) return $this->usersToMigrateByFilter($filter, $request); - return $this->allUsers($request); + if ($filter = $request->has('all')) return $this->allUsers($request); + return $this->pendingUsersToMigrate($request); } /** @@ -213,7 +214,7 @@ protected function dumpCurrentConnection() */ protected function usersToMigrateByFilter($filter, $request) { - + //TODO } /** @@ -226,4 +227,19 @@ protected function allUsers($request) { return \Scool\EbreEscoolModel\User::with('person')->get(); } + + /** + * Get all pending users to migrate. + * + * @param $request + * @return \Illuminate\Database\Eloquent\Collection|static[] + */ + protected function pendingUsersToMigrate($request) + { + $ids = UserMigration::all()->pluck('source_user_id'); + return ($ids->count() > 0) + ? \Scool\EbreEscoolModel\User::whereNotIn('id',$ids)->with('person')->get() + : [] ; + } + } diff --git a/src/Http/routes.php b/src/Http/routes.php index 21705b1..66dfaa4 100644 --- a/src/Http/routes.php +++ b/src/Http/routes.php @@ -17,6 +17,16 @@ //Users migration Route::get('management/users-migration', 'UsersMigrationController@index')->name('users-migration'); + + //Google apps + Route::get('/management/users/google', 'GoogleAppsUsersController@index'); + Route::get('/management/users/google2', 'GoogleAppsUsersController@check'); + Route::get('/management/users/google1', 'GoogleAppsUsersController@esborrar'); + Route::get('/management/users/google3', 'GoogleAppsUsersController@google3'); + Route::get('/management/users/google4', 'GoogleAppsUsersController@google4'); + Route::get('/management/users/google8', 'GoogleAppsUsersController@google8'); + Route::get('/management/users/google10', 'GoogleAppsUsersController@google10'); + }); // "Public" accessible but protected by token Route::get('/management/users/user-invitation-accept', 'UserInvitationsController@accept'); @@ -85,6 +95,11 @@ Route::get('/management/users-migration/history', 'UsersMigrationController@history'); Route::get('/management/users-migration/batch_history', 'UsersMigrationController@batchHistory'); + Route::get('/management/users-google/check', 'GoogleAppsUsersController@check'); + Route::get('/management/users-google/local-sync', 'GoogleAppsUsersController@localSync'); + + Route::get('/management/users-google', 'GoogleAppsUsersController@all'); + }); Route::post('/management/user-invitations-accept', 'UserInvitationsController@postAccept'); diff --git a/src/Models/GoogleApps/GoogleUser.php b/src/Models/GoogleApps/GoogleUser.php new file mode 100644 index 0000000..d1c3c94 --- /dev/null +++ b/src/Models/GoogleApps/GoogleUser.php @@ -0,0 +1,20 @@ +registerAcachaStatefulServiceProvider(); - Passport::routes(); + } + + if (config('acacha_users.register_google_service_provider', true)) { + $this->registerGoogleServiceProvider(); } } @@ -90,6 +95,24 @@ protected function registerAcachaStatefulServiceProvider() $this->app->register(StatefulServiceProvider::class); } + /** + * Register Google Service Provider. + */ + protected function registerGoogleServiceProvider() + { + $this->app->register(GoogleServiceProvider::class); + + $this->app->booting(function() { + $loader = AliasLoader::getInstance(); + $loader->alias('Google', Google::class); + }); + + app()->extend(\PulkitJalan\Google\Client::class, function ($command, $app) { + $config = $app['config']['google']; + return new \PulkitJalan\Google\Client($config, config('users.google_apps_admin_user_email')); + }); + } + /** * Bootstrap the application services. */ diff --git a/src/Services/GoogleApps/GoogleAppsService.php b/src/Services/GoogleApps/GoogleAppsService.php new file mode 100644 index 0000000..459d627 --- /dev/null +++ b/src/Services/GoogleApps/GoogleAppsService.php @@ -0,0 +1,141 @@ +users->get($email = config('users.google_apps_user_email_to_check_connection')); + if($r) { + $state = 'connected'; + } else { + echo 'User does not exists: $email
'; + } + } catch (\Exception $e) { + $state = 'error'; + $message = json_decode($e->getMessage()); + } + + $result = [ + 'state' => $state + ]; + + if ($state != 'connected') $result['message'] = $message; + + return $result; + } + + /** + * Get total number of users. + */ + public function totalNumberOfUsers() + { + return count($this->allUsers()); + } + + /** + * Get all users from google apps. + * + * @return array|mixed + */ + protected function allUsers() + { + $directory = Google::make('directory'); + $pageToken = null; + $users = []; + do { + try { + $r = $directory->users->listUsers([ + 'domain' => config('users.google_apps_domain'), + 'maxResults' => config('users.google_apps_users_maxResults'), + 'pageToken' => $pageToken + ]); + $pageToken = $r->nextPageToken; + $users = array_merge($users, $r->users); + } catch (\Exception $e) { + return json_decode($e->getMessage()); + } + } while ($pageToken); + return $users; + } + + /** + * Sync local database with remote Google apps info. + */ + public function localSync() + { + $users = Cache::rememberForever('google_app_users', function () { +// return $this->getUsers(); + return $this->allUsers(); + }); + + foreach ($users as $user) { +// dd($user); + $user = GoogleUser::firstOrCreate([ + 'customerId' => $user->customerId, + 'kind' => $user->kind, + 'google_id'=> $user->id, + 'etag'=> $user->etag, + 'primaryEmail'=> $user->primaryEmail, + 'givenName'=> $user->name->givenName, + 'familyName'=> $user->name->familyName, + 'fullName'=> $user->name->fullName, + 'orgUnitPath'=> $user->orgUnitPath, + 'organizations'=> json_decode($user->organizations), + 'isAdmin'=> $user->isAdmin, + 'isDelegatedAdmin'=> $user->isDelegatedAdmin, + 'lastLoginTime'=> $user->lastLoginTime, + 'creationTime'=> $user->creationTime, + 'deletionTime'=> $user->deletionTime, + 'agreedToTerms'=> $user->agreedToTerms, + 'password'=> $user->password, + 'hashFunction'=> $user->hashFunction, + 'suspended'=> $user->suspended, + 'suspensionReason'=> $user->suspensionReason, + 'changePasswordAtNextLogin'=> $user->changePasswordAtNextLogin, + 'emails'=> json_encode($user->emails), + ]); +// dd($user); + } + } + + /** + * Get users. + * + * @param int $perPage + * @return int|mixed + */ + public function getUsers($perPage = 15) + { + $directory = Google::make('directory'); + try { + $r = $directory->users->listUsers([ + 'domain' => config('users.google_apps_domain'), + 'maxResults' => $perPage + ]); + } catch (\Exception $e) { + return json_decode($e->getMessage()); + } + + return $r->users; + } +} \ No newline at end of file diff --git a/src/Services/UserMigrations.php b/src/Services/UserMigrations.php index d3b19c0..d4ffb69 100644 --- a/src/Services/UserMigrations.php +++ b/src/Services/UserMigrations.php @@ -3,6 +3,7 @@ namespace Acacha\Users\Services; use Acacha\Users\Events\ProgressBarStatusHasBeenUpdated; +use Acacha\Users\Events\UserCreated; use Acacha\Users\Models\ProgressBatch; use Illuminate\Support\Collection; use Psr\Log\InvalidArgumentException; @@ -49,13 +50,18 @@ public function migrateUsers($usersToMigrate, $batch) $max_execution_time = ini_get('max_execution_time'); set_time_limit ( 0); - if (count($usersToMigrate) == 0 ) return; + if (count($usersToMigrate) == 0 ){ + info('Users migration : Nothing to migrate!'); + event(new ProgressBarStatusHasBeenUpdated('users-migration-progress-bar', 100,'Migration finished. Nothing to migrate!' )); + return; + } info('Users migration : A new batch user migration ( id: ' . $batch->id .') has been initialized!'); $progressIncrement = $this->progressIncrement($usersToMigrate); $progress= 0; $migratedUsers=0; $errorUsers=0; + dump($usersToMigrate); foreach ($usersToMigrate as $user) { if ($batch->stopped()) { info('Users migration : A batch user migration ( id: ' . $batch->id .') has been stopped!'); @@ -102,6 +108,7 @@ public function migrateUser($user, $batchId) 'password' => bcrypt('secret') ]); event(new UserHasBeenMigrated($user->id, $user->toJson(), $newUser, $batchId)); + event(new UserCreated($newUser)); return $newUser; } catch( QueryException $e) { event(new UserHasBeenMigrated($user->id, $user->toJson(), null, $batchId)); diff --git a/src/Traits/HasPaginator.php b/src/Traits/HasPaginator.php new file mode 100644 index 0000000..696b34c --- /dev/null +++ b/src/Traits/HasPaginator.php @@ -0,0 +1,31 @@ +slice(($currentPage - 1) * $perPage, $perPage); + + return new LengthAwarePaginator($currentPageItems, count($items), $perPage); + } +} \ No newline at end of file diff --git a/src/Traits/HasUserMigrations.php b/src/Traits/HasUserMigrations.php index 2ddb65c..1f78869 100644 --- a/src/Traits/HasUserMigrations.php +++ b/src/Traits/HasUserMigrations.php @@ -19,6 +19,7 @@ trait HasUserMigrations */ public function scopeMigrated($query) { + //TODO: Custom query to improve performance or Cache! return $query->has('migration'); } diff --git a/src/helpers.php b/src/helpers.php index 1c51c86..af3b836 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -114,6 +114,15 @@ function initialize_users_management_permissions() permission_first_or_create('reset-user-password'); give_permission_to_role($manageUsers,'reset-user-password'); + //Google apps users + permission_first_or_create('see-google-apps-users'); + permission_first_or_create('check-google-apps-connection'); + permission_first_or_create('list-google-apps-users'); + permission_first_or_create('sync-google-apps-users'); + give_permission_to_role($manageUsers,'see-google-apps-users'); + give_permission_to_role($manageUsers,'check-google-apps-connection'); + give_permission_to_role($manageUsers,'list-google-apps-users'); + give_permission_to_role($manageUsers,'sync-google-apps-users'); app(PermissionRegistrar::class)->registerPermissions(); }