fix : 테이블 추가 및 수정
- 신규 (user_roles, user_tenants) - 수정 (roles, tenants, users)
This commit is contained in:
@@ -14,4 +14,14 @@ public function menuPermissions()
|
|||||||
{
|
{
|
||||||
return $this->hasMany(RoleMenuPermission::class, 'role_id');
|
return $this->hasMany(RoleMenuPermission::class, 'role_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function tenant()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Tenant::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function userRoles()
|
||||||
|
{
|
||||||
|
return $this->hasMany(UserRole::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,4 +42,24 @@ public function subscription()
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(Subscription::class, 'subscription_id');
|
return $this->belongsTo(Subscription::class, 'subscription_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function userTenants()
|
||||||
|
{
|
||||||
|
return $this->hasMany(UserTenant::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function users()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(User::class, 'user_tenants');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function roles()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Role::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function userRoles()
|
||||||
|
{
|
||||||
|
return $this->hasMany(UserRole::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,37 +6,29 @@
|
|||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
use Laravel\Fortify\TwoFactorAuthenticatable;
|
use Laravel\Fortify\TwoFactorAuthenticatable;
|
||||||
use Laravel\Sanctum\HasApiTokens;
|
use Laravel\Sanctum\HasApiTokens;
|
||||||
use App\Traits\UppercaseAttributes;
|
|
||||||
|
|
||||||
class User extends Authenticatable
|
class User extends Authenticatable
|
||||||
{
|
{
|
||||||
use HasApiTokens, Notifiable, TwoFactorAuthenticatable;
|
use HasApiTokens, Notifiable, TwoFactorAuthenticatable, SoftDeletes;
|
||||||
|
|
||||||
protected $table = 'members'; // 테이블 이름 변경
|
public function userTenants()
|
||||||
|
|
||||||
protected $primaryKey = 'mb_id'; // 기본 키 변경
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
'mb_id', 'mb_pass', 'mb_name', 'mb_phone', 'mb_mail',
|
|
||||||
'email_verified_at', 'mb_type', 'mb_level', 'last_login',
|
|
||||||
'reg_date', 'remember_token'
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $hidden = [
|
|
||||||
'mb_pass', 'remember_token',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $casts = [
|
|
||||||
'reg_date' => 'datetime',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function getAuthPassword()
|
|
||||||
{
|
{
|
||||||
return $this->mb_pass; // 기본 비밀번호 필드를 mb_pass로 설정
|
return $this->hasMany(UserTenant::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAuthIdentifierName()
|
public function tenants()
|
||||||
{
|
{
|
||||||
return 'mb_id'; // 기본 로그인 필드를 mb_id로 변경
|
return $this->belongsToMany(Tenant::class, 'user_tenants');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function userRoles()
|
||||||
|
{
|
||||||
|
return $this->hasMany(UserRole::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function roles()
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Role::class, 'user_roles')
|
||||||
|
->withPivot('tenant_id', 'assigned_at');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
app/Models/UserRole.php
Normal file
31
app/Models/UserRole.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use App\Traits\BelongsToTenant;
|
||||||
|
|
||||||
|
class UserRole extends Model
|
||||||
|
{
|
||||||
|
use SoftDeletes, BelongsToTenant;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'user_id', 'tenant_id', 'role_id', 'assigned_at'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tenant()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Tenant::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function role()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Role::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
25
app/Models/UserTenant.php
Normal file
25
app/Models/UserTenant.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
|
class UserTenant extends Model
|
||||||
|
{
|
||||||
|
use SoftDeletes;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'user_id', 'tenant_id', 'is_active', 'joined_at', 'left_at'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tenant()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Tenant::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
database/migrations/2025_07_26_000818_create_roles_table.php
Normal file
36
database/migrations/2025_07_26_000818_create_roles_table.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
// 1. 컬럼 nullable 해제, 주석 보강, soft delete 추가
|
||||||
|
Schema::table('roles', function (Blueprint $table) {
|
||||||
|
// tenant_id NOT NULL로 변경
|
||||||
|
$table->unsignedBigInteger('tenant_id')->nullable(false)->change();
|
||||||
|
$table->string('name', 50)->comment('역할명')->change();
|
||||||
|
$table->string('description', 255)->nullable()->comment('설명')->change();
|
||||||
|
|
||||||
|
// deleted_at 추가 (soft delete)
|
||||||
|
$table->softDeletes()->comment('삭제일시(소프트삭제)');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. (권장) 유니크 인덱스 보장: 한 테넌트 내에서 동일한 역할명 중복 불가
|
||||||
|
Schema::table('roles', function (Blueprint $table) {
|
||||||
|
$table->unique(['tenant_id', 'name'], 'uk_roles_tenant_name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('roles', function (Blueprint $table) {
|
||||||
|
// 롤백시 soft delete 및 인덱스 제거
|
||||||
|
$table->dropSoftDeletes();
|
||||||
|
$table->dropUnique('uk_roles_tenant_name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
51
database/migrations/2025_07_26_000818_create_users_table.php
Normal file
51
database/migrations/2025_07_26_000818_create_users_table.php
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
// 1. tenant_id NOT NULL 추가
|
||||||
|
$table->unsignedBigInteger('tenant_id')->after('id')->comment('FK: 테넌트 ID')->default(1); // default 값은 마이그레이션 중 기존 데이터 보호용
|
||||||
|
|
||||||
|
// 2. 컬럼별 주석 보강
|
||||||
|
$table->string('name', 255)->comment('회원 이름')->change();
|
||||||
|
$table->string('email', 255)->comment('이메일')->change();
|
||||||
|
$table->string('password', 255)->comment('비밀번호')->change();
|
||||||
|
$table->string('profile_photo_path', 2048)->nullable()->comment('프로필 사진 경로')->change();
|
||||||
|
$table->string('remember_token', 100)->nullable()->comment('자동로그인 토큰')->change();
|
||||||
|
|
||||||
|
// 3. soft delete 추가
|
||||||
|
$table->softDeletes()->comment('삭제일시(소프트삭제)');
|
||||||
|
|
||||||
|
// 4. 유니크키 변경: (tenant_id, email)로
|
||||||
|
$table->dropUnique(['email']);
|
||||||
|
$table->unique(['tenant_id', 'email'], 'uk_users_tenant_email');
|
||||||
|
});
|
||||||
|
|
||||||
|
// FK 추가 (이미 tenants 테이블이 있어야 함)
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->foreign('tenant_id')->references('id')->on('tenants');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
// 롤백: FK/유니크/컬럼 제거
|
||||||
|
$table->dropForeign(['tenant_id']);
|
||||||
|
$table->dropUnique('uk_users_tenant_email');
|
||||||
|
$table->dropColumn('tenant_id');
|
||||||
|
$table->dropSoftDeletes();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 기존 유니크 복구
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->unique('email');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('user_roles', function (Blueprint $table) {
|
||||||
|
$table->bigIncrements('id')->comment('PK: 회원별 역할 매핑 ID');
|
||||||
|
$table->unsignedBigInteger('user_id')->comment('FK: 회원ID');
|
||||||
|
$table->unsignedBigInteger('tenant_id')->comment('FK: 테넌트ID');
|
||||||
|
$table->unsignedBigInteger('role_id')->comment('FK: 역할ID');
|
||||||
|
$table->timestamp('assigned_at')->nullable()->comment('역할 할당일');
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes()->comment('삭제일시(소프트삭제)');
|
||||||
|
|
||||||
|
$table->unique(['user_id', 'tenant_id', 'role_id'], 'uk_user_tenant_role');
|
||||||
|
$table->foreign('user_id')->references('id')->on('users');
|
||||||
|
$table->foreign('tenant_id')->references('id')->on('tenants');
|
||||||
|
$table->foreign('role_id')->references('id')->on('roles');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('user_roles');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration {
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('user_tenants', function (Blueprint $table) {
|
||||||
|
$table->bigIncrements('id')->comment('PK: 회원-테넌트 소속 ID');
|
||||||
|
$table->unsignedBigInteger('user_id')->comment('FK: 회원ID');
|
||||||
|
$table->unsignedBigInteger('tenant_id')->comment('FK: 테넌트ID');
|
||||||
|
$table->boolean('is_active')->default(1)->comment('활성화 여부');
|
||||||
|
$table->timestamp('joined_at')->nullable()->comment('소속일시');
|
||||||
|
$table->timestamp('left_at')->nullable()->comment('탈퇴일시');
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes()->comment('삭제일시(소프트삭제)');
|
||||||
|
|
||||||
|
$table->unique(['user_id', 'tenant_id'], 'uk_user_tenant');
|
||||||
|
$table->foreign('user_id')->references('id')->on('users');
|
||||||
|
$table->foreign('tenant_id')->references('id')->on('tenants');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('user_tenants');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
// 외래키 먼저 삭제
|
||||||
|
$table->dropForeign('users_tenant_id_foreign');
|
||||||
|
// 컬럼 삭제
|
||||||
|
$table->dropColumn('tenant_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->unsignedBigInteger('tenant_id')->nullable()->comment('테넌트ID');
|
||||||
|
$table->foreign('tenant_id')->references('id')->on('tenants')->onDelete('set null');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user