webworld888/migrations/UserMigration.php
2021-10-26 19:14:12 +09:00

536 lines
18 KiB
PHP

<?php
/**
* UserMigration.php
*
* PHP version 7
*
* @category Migrations
* @package Xpressengine\Migrations
* @author XE Developers <developers@xpressengine.com>
* @copyright 2020 Copyright XEHub Corp. <https://www.xehub.io>
* @license http://www.gnu.org/licenses/lgpl-3.0-standalone.html LGPL
* @link https://xpressengine.io
*/
namespace Xpressengine\Migrations;
use Illuminate\Database\Schema\Blueprint;
use DB;
use Schema;
use XeLang;
use Xpressengine\Support\Migration;
use Xpressengine\User\Models\User;
use Xpressengine\User\UserRegisterHandler;
/**
* Class UserMigration
*
* @category Migrations
* @package Xpressengine\Migrations
* @author XE Developers <developers@xpressengine.com>
* @copyright 2020 Copyright XEHub Corp. <https://www.xehub.io>
* @license http://www.gnu.org/licenses/lgpl-3.0-standalone.html LGPL
* @link https://xpressengine.io
*/
class UserMigration extends Migration
{
/**
* Run when install the application.
*
* @return void
*/
public function install()
{
Schema::create('user', function (Blueprint $table) {
$table->engine = "InnoDB";
$table->string('id', 36)->comment('user ID');
$table->string('display_name', 255)->comment('display name.');
$table->string('email', 255)->nullable()->comment('email');
$table->string('login_id', 255)->unique()->comment('id');
$table->string('password', 255)->nullable()->comment('password');
$table->string('rating', 15)->default('user')->comment('user rating. guest/user/manager/super');
$table->string('status', 20)->comment('account status. activated/deactivated');
$table->text('introduction')->default(null)->nullable()->comment('user introduction');
$table->string('profile_image_id', 36)->nullable()->comment('profile image file ID');
$table->string('remember_token', 255)->nullable()->comment('token for keep login');
$table->timestamp('login_at')->nullable()->comment('login date');
$table->timestamp('created_at')->nullable()->index()->comment('created date');
$table->timestamp('updated_at')->nullable()->index()->comment('updated date');
$table->timestamp('password_updated_at')->nullable()->comment('password updated date');
$table->primary('id');
});
Schema::create('user_group', function (Blueprint $table) {
$table->engine = "InnoDB";
$table->string('id', 36)->comment('group ID');
$table->string('name')->comment('group name');
$table->string('description', 1000)->comment('group description');
$table->integer('order')->default(0)->index()->comment('order number');
$table->timestamp('created_at')->nullable()->index()->comment('created date');
$table->timestamp('updated_at')->nullable()->comment('updated date');
$table->primary('id');
});
Schema::create('user_group_user', function (Blueprint $table) {
// user IDs included in the use group
$table->engine = "InnoDB";
$table->increments('id')->comment('ID');
$table->string('group_id', 36)->comment('group ID');
$table->string('user_id', 36)->comment('user ID');
$table->timestamp('created_at')->nullable()->comment('created date');
$table->unique(['group_id', 'user_id']);
$table->index('group_id');
$table->index('user_id');
});
Schema::create('user_account', function (Blueprint $table) {
// user account. Login via account information provided by other providers. As like OAuth.
$table->engine = "InnoDB";
$table->string('id', 36)->comment('ID');
$table->string('user_id')->comment('user ID');
$table->string('account_id')->comment('account Id');
$table->string('email')->nullable()->comment('email');
$table->char('provider', 20)->comment('OAuth provider. naver/twitter/facebook/...');
$table->string('token', 500)->comment('token');
$table->string('token_secret', 500)->comment('token secret');
$table->timestamp('created_at')->nullable()->comment('created date');
$table->timestamp('updated_at')->nullable()->comment('updated date');
$table->primary('id');
$table->unique(['provider', 'account_id']);
});
Schema::create('user_email', function (Blueprint $table) {
$table->engine = "InnoDB";
$table->increments('id')->comment('ID');
$table->string('user_id', 36)->comment('user ID');
$table->string('address')->comment('email address');
$table->timestamp('created_at')->nullable()->index()->comment('created date');
$table->timestamp('updated_at')->nullable()->comment('updated date');
$table->index('user_id');
$table->index('address');
});
Schema::create('user_pending_email', function (Blueprint $table) {
// email confirm
$table->engine = "InnoDB";
$table->increments('id')->comment('ID');
$table->string('user_id', 36)->comment('user ID');
$table->string('address')->comment('email address');
$table->string('confirmation_code')->nullable()->comment('confirmation code');
$table->timestamp('created_at')->nullable()->index()->comment('created date');
$table->timestamp('updated_at')->nullable()->comment('updated date');
$table->index('user_id');
$table->index('address');
});
Schema::create('user_password_resets', function (Blueprint $table) {
// find account password
$table->engine = "InnoDB";
$table->increments('id')->comment('ID');
$table->string('email')->index()->comment('email address');
$table->string('token')->index()->comment('token');
$table->timestamp('created_at')->nullable()->comment('created date');
});
Schema::create('user_register_token', function (Blueprint $table) {
// find account password
$table->engine = "InnoDB";
$table->string('id', 36)->comment('user ID');
$table->string('guard', 100)->comment('the guard creating token');
$table->text('data')->comment('token data');
$table->timestamp('created_at')->nullable()->comment('created date');
});
Schema::create('user_terms', function (Blueprint $table) {
$table->string('id', 36);
$table->string('title');
$table->string('content')->nullable();
$table->string('description')->nullable();
$table->integer('order')->default(0);
$table->boolean('is_enabled')->default(false);
$table->boolean('is_require')->default(true);
$table->primary('id');
$table->engine = "InnoDB";
});
Schema::create('user_login_log', function (Blueprint $table) {
$table->engine = "InnoDB";
$table->bigIncrements('id')->comment('row id');
$table->string('user_id', 36)->comment('user ID');
$table->string('user_agent')->comment('user agent');
$table->string('ip', 15)->comment('ip');
$table->timestamp('created_at')->nullable()->comment('created date');
$table->index('user_id');
});
$this->createUserTermAgreeTable();
}
/**
* Run after installation.
*
* @return void
*/
public function installed()
{
DB::table('config')->insert([
['name' => 'user', 'vars' => '[]'],
['name' => 'user.common', 'vars' => '{"useCaptcha":false,"webmasterName":"webmaster","webmasterEmail":"webmaster@domain.com"}'],
['name' => 'user.register', 'vars' => '{"secureLevel":"low","joinable":true,"register_process":"activated","term_agree_type":"pre","display_name_unique":false,"use_display_name":true,"password_rules":"min:6|alpha|numeric|special_char"}'],
['name' => 'toggleMenu@user', 'vars' => '{"activate":["user\/toggleMenu\/xpressengine@profile","user\/toggleMenu\/xpressengine@manage"]}']
]);
}
/**
* Run after service activation.
*
* @return void
*/
public function init()
{
$registerConfig = app('xe.config')->get('user.register');
// add default user groups
$joinGroup = app('xe.user')->groups()->create(
[
'name' => '정회원',
'description' => 'default user group'
]
);
app('xe.user')->groups()->create(
[
'name' => '준회원',
'description' => 'sub user group'
]
);
$registerConfig->set('joinGroup', $joinGroup->id);
$displayNameCaption = XeLang::genUserKey();
foreach (XeLang::getLocales() as $locale) {
$value = "닉네임";
if ($locale != 'ko') {
$value = "Nickname";
}
XeLang::save($displayNameCaption, $locale, $value);
}
$registerConfig->set('display_name_caption', $displayNameCaption);
app('xe.config')->modify($registerConfig);
// set admin's group
auth()->user()->joinGroups($joinGroup);
}
/**
* check updated
*
* @param null $installedVersion installed version
*
* @return bool
*/
public function checkUpdated($installedVersion = null)
{
if ($this->checkNeedMergeConfig() == true) {
return false;
}
if ($this->checkExistRegisterConfig() == false) {
return false;
}
if ($this->checkNeedAddTermTableColumns() === false) {
return false;
}
if ($this->checkExistUserTermAgreeTable() === false) {
return false;
}
if ($this->checkExistUserLoginIdColumn() === false) {
return false;
}
return true;
}
/**
* run update
*
* @param null $installedVersion installed version
*
* @return void
*/
public function update($installedVersion = null)
{
if ($this->checkNeedMergeConfig() == true) {
$this->mergeConfig();
}
if ($this->checkExistRegisterConfig() == false) {
$this->divideRegisterConfig();
}
if ($this->checkNeedAddTermTableColumns() === false) {
$this->addTermTableColumns();
$this->updateOldTermsRequire();
}
if ($this->checkExistUserTermAgreeTable() === false) {
$this->createUserTermAgreeTable();
}
//TODO 실행 조건 추가
$this->deleteDisplayNameUnique();
if ($this->checkExistUserLoginIdColumn() === false) {
$this->createUserLoginIdColumn();
$this->migrationLoginIdColumn();
$this->setLoginIdColumnUnique();
}
}
/**
* check need user setting merge(common, join)
*
* @return bool
*/
private function checkNeedMergeConfig()
{
return app('xe.config')->get('user.join') !== null;
}
/**
* run user setting merge(common, join)
*
* @return void
*/
private function mergeConfig()
{
$commonConfig = app('xe.config')->get('user.common');
$joinConfig = app('xe.config')->get('user.join');
$commonConfigAttribute = $commonConfig->getPureAll();
$joinConfigAttribute = $joinConfig->getPureAll();
foreach ($joinConfigAttribute as $name => $value) {
$commonConfigAttribute[$name] = $value;
}
app('xe.config')->put('user.common', $commonConfigAttribute);
app('xe.config')->remove($joinConfig);
}
/**
* check exist register config
*
* @return bool
*/
private function checkExistRegisterConfig()
{
return app('xe.config')->get('user.register') !== null;
}
/**
* divide from user.common to user.register
*
* @return void
*/
private function divideRegisterConfig()
{
$commonConfig = app('xe.config')->get('user.common');
$originalCommonConfigAttribute = $commonConfig->getPureAll();
$commonConfigAttribute = ['useCaptcha', 'webmasterName', 'webmasterEmail'];
$registerConfigAttribute = array_diff_key($originalCommonConfigAttribute, array_flip($commonConfigAttribute));
$newCommonConfigAttribute = [];
foreach ($commonConfigAttribute as $config) {
if (isset($originalCommonConfigAttribute[$config]) === true) {
$newCommonConfigAttribute[$config] = $originalCommonConfigAttribute[$config];
}
}
if (isset($registerConfigAttribute['guard_forced']) && $registerConfigAttribute['guard_forced'] === true) {
$registerConfigAttribute['register_process'] = User::STATUS_PENDING_EMAIL;
} else {
$registerConfigAttribute['register_process'] = User::STATUS_ACTIVATED;
}
unset($registerConfigAttribute['guard_forced']);
$registerConfigAttribute['term_agree_type'] = UserRegisterHandler::TERM_AGREE_PRE;
$registerConfigAttribute['display_name_unique'] = true;
$registerConfigAttribute['use_display_name'] = true;
$registerConfigAttribute['dynamic_fields'] = array_keys(app('xe.dynamicField')->gets('user'));
$displayNameCaption = XeLang::genUserKey();
foreach (XeLang::getLocales() as $locale) {
$value = "닉네임";
if ($locale != 'ko') {
$value = "Nickname";
}
XeLang::save($displayNameCaption, $locale, $value);
}
$registerConfigAttribute['display_name_caption'] = $displayNameCaption;
$passwordRuleLevel = app('config')->get('xe.user.password.default');
$registerConfigAttribute['password_rules'] = app('config')->get("xe.user.password.levels.{$passwordRuleLevel}");
if (isset($registerConfigAttribute['secureLevel']) === true) {
unset($registerConfigAttribute['secureLevel']);
}
app('xe.config')->put('user.common', $newCommonConfigAttribute);
app('xe.config')->set('user.register', $registerConfigAttribute);
}
/**
* Check need term table update
*
* @return bool
*/
private function checkNeedAddTermTableColumns()
{
return Schema::hasColumn('user_terms', 'is_require') && Schema::hasColumn('user_terms', 'description');
}
/**
* Add term table description, is_require columns
*
* @return void
*/
private function addTermTableColumns()
{
Schema::table('user_terms', function (Blueprint $table) {
$table->string('description')->after('title')->nullable();
$table->boolean('is_require')->default(true)->nullable();
});
}
/**
* Old term update require
*
* @return void
*/
private function updateOldTermsRequire()
{
\DB::table('user_terms')->update(['is_require' => true]);
}
/**
* Check exist user term agree table
*
* @return bool
*/
private function checkExistUserTermAgreeTable()
{
return Schema::hasTable('user_term_agrees');
}
/**
* Create user term agree table
*
* @return void
*/
private function createUserTermAgreeTable()
{
Schema::create('user_term_agrees', function (Blueprint $table) {
$table->string('id', 36);
$table->string('user_id', 36);
$table->string('term_id', 36);
$table->softDeletes();
$table->timestamps();
$table->unique(['user_id', 'term_id']);
$table->index('user_id');
$table->index('term_id');
});
}
/**
* display_name field unique 삭제
*
* @return void
*/
private function deleteDisplayNameUnique()
{
try {
Schema::table('user', function (Blueprint $table) {
$table->dropUnique('user_display_name_unique');
});
} catch (\Exception $e) {
}
}
/**
* User 테이블에 login_id 컬럼이 존재 여부 확인
*
* @return bool
*/
private function checkExistUserLoginIdColumn()
{
return Schema::hasColumn('user', 'login_id');
}
/**
* User 테이블에 login_id 컬럼 생성
*
* @return void
*/
private function createUserLoginIdColumn()
{
Schema::table('user', function (Blueprint $table) {
$table->string('login_id')->after('email');
});
}
/**
* user email에서 계정을 login_id로 update
* 중복된 login_id는 확인해서 login_id 뒤에 index를 붙임
*
* @return void
*/
private function migrationLoginIdColumn()
{
\DB::table('user')->update(['login_id' => \DB::raw("REPLACE(SUBSTRING_INDEX(email, '@', 1), '.', '')")]);
$duplicateEmails = \DB::table('user')->select('login_id')
->groupBy('login_id')->havingRaw('count(login_id) > 1')->get();
foreach ($duplicateEmails as $duplicateEmail) {
$duplicateUsers = User::where('login_id', $duplicateEmail->login_id)->orderBy('created_at')->get();
foreach ($duplicateUsers as $index => $duplicateUser) {
$duplicateUser->login_id .= ($index + 1);
$duplicateUser->save();
}
}
}
/**
* login_id 업데이트 후 unique 지정
*
* @return void
*/
private function setLoginIdColumnUnique()
{
Schema::table('user', function (Blueprint $table) {
$table->unique('login_id');
});
}
}