Basic tenant structure
This commit is contained in:
21
app/Enumerations/CostUnitType.php
Normal file
21
app/Enumerations/CostUnitType.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Scopes\CommonModel;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
/**
|
||||
* @property string $slug
|
||||
* @property string $name
|
||||
*/
|
||||
class CostUnitType extends CommonModel
|
||||
{
|
||||
public const COST_UNIT_TYPE_EVENT = 'event';
|
||||
public const COST_UNIT_TYPE_RUNNING_JOB = 'running_job';
|
||||
|
||||
protected $fillable = [
|
||||
'slug',
|
||||
'name',
|
||||
];
|
||||
}
|
||||
22
app/Enumerations/EatingHabit.php
Normal file
22
app/Enumerations/EatingHabit.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Scopes\CommonModel;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
/**
|
||||
* @property string $slug
|
||||
* @property string $name
|
||||
*/
|
||||
class EatingHabit extends CommonModel
|
||||
{
|
||||
public const string EATING_HABIT_OMNIVOR = 'EATING_HABIT_OMNIVOR';
|
||||
public const string EATING_HABIT_VEGETARIAN = 'EATING_HABIT_VEGETARIAN';
|
||||
public const string EATING_HABIT_VEGAN = 'EATING_HABIT_VEGAN';
|
||||
|
||||
protected $fillable = [
|
||||
'slug',
|
||||
'name',
|
||||
];
|
||||
}
|
||||
22
app/Enumerations/FirstAidPermission.php
Normal file
22
app/Enumerations/FirstAidPermission.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Scopes\CommonModel;
|
||||
|
||||
/**
|
||||
* @property string $slug
|
||||
* @property string $name
|
||||
*/
|
||||
class FirstAidPermission extends CommonModel
|
||||
{
|
||||
public const string FIRST_AID_PERMISSION_ALLOWED = 'FIRST_AID_PERMISSION_ALLOWED';
|
||||
public const string FIRST_AID_PERMISSION_DENIED = 'FIRST_AID_PERMISSION_DENIED';
|
||||
|
||||
|
||||
protected $fillable = [
|
||||
'slug',
|
||||
'name',
|
||||
'description'
|
||||
];
|
||||
}
|
||||
26
app/Enumerations/SwimmingPermission.php
Normal file
26
app/Enumerations/SwimmingPermission.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Scopes\CommonModel;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
/**
|
||||
* @property string $slug
|
||||
* @property string $name
|
||||
*/
|
||||
class SwimmingPermission extends CommonModel
|
||||
{
|
||||
public const string SWIMMING_PERMISSION_ALLOWED = 'SWIMMING_PERMISSION_ALLOWED';
|
||||
public const string SWIMMING_PERMISSION_LIMITED = 'SWIMMING_PERMISSION_LIMITED';
|
||||
public const string SWIMMING_PERMISSION_DENIED = 'SWIMMING_PERMISSION_DENIED';
|
||||
|
||||
|
||||
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'slug',
|
||||
'name',
|
||||
];
|
||||
}
|
||||
17
app/Enumerations/UserRole.php
Normal file
17
app/Enumerations/UserRole.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enumerations;
|
||||
|
||||
use App\Scopes\CommonModel;
|
||||
|
||||
class UserRole extends CommonModel {
|
||||
public const USER_ROLE_ADMIN = 'ROLE_ADMINISTRATOR';
|
||||
public const USER_ROLE_GROUP_LEADER = 'ROLE_GROUP_LEADER';
|
||||
public const USER_ROLE_USER = 'ROLE_USER';
|
||||
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'slug'
|
||||
];
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
abstract class Controller
|
||||
{
|
||||
//
|
||||
}
|
||||
43
app/Installer/DevelopmentDataSeeder.php
Normal file
43
app/Installer/DevelopmentDataSeeder.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Installer;
|
||||
|
||||
use App\Enumerations\UserRole;
|
||||
use App\Models\Tenant;
|
||||
use App\Models\User;
|
||||
|
||||
class DevelopmentDataSeeder {
|
||||
public function execute() {
|
||||
$this->installTenants();
|
||||
$this->installUsers();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private function installTenants() {
|
||||
Tenant::create([
|
||||
'slug' => 'wilde-moehre',
|
||||
'local_group_name' => 'Stamm Wilde Möhre',
|
||||
'url' => 'wilde-moehre.mareike.local',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'email' => 'test@example1.com',
|
||||
'city' => 'Halle (Saale)',
|
||||
'postcode' => '06120',
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
private function installUsers() {
|
||||
User::create([
|
||||
'firstname' => 'Development',
|
||||
'lastname' => 'User',
|
||||
'user_role' => UserRole::USER_ROLE_ADMIN,
|
||||
'tenant' => 'lv',
|
||||
'email' => 'th.guenther@saale-mail.de',
|
||||
'password' => bcrypt('development'),
|
||||
'local_group_id' => 1,
|
||||
'username' => 'development',
|
||||
]);
|
||||
}
|
||||
}
|
||||
71
app/Installer/ProductionDataSeeder.php
Normal file
71
app/Installer/ProductionDataSeeder.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace App\Installer;
|
||||
|
||||
use App\Enumerations\CostUnitType;
|
||||
use App\Enumerations\EatingHabit;
|
||||
use App\Enumerations\FirstAidPermission;
|
||||
use App\Enumerations\SwimmingPermission;
|
||||
use App\Enumerations\UserRole;
|
||||
use App\Models\Tenant;
|
||||
|
||||
class ProductionDataSeeder {
|
||||
public function execute() {
|
||||
$this->installUserRoles();
|
||||
$this->installCostUnitTypes();
|
||||
$this->installSwimmingPermissions();
|
||||
$this->installEatingHabits();
|
||||
$this->installFirstAidPermissions();
|
||||
$this->installTenants();
|
||||
}
|
||||
|
||||
private function installUserRoles() {
|
||||
UserRole::create(['name' => 'Administrator*in', 'slug' => UserRole::USER_ROLE_ADMIN]);
|
||||
UserRole::create(['name' => 'Vorstandsmitglied', 'slug' => UserRole::USER_ROLE_GROUP_LEADER]);
|
||||
UserRole::create(['name' => 'Benutzer*in', 'slug' => UserRole::USER_ROLE_USER]);
|
||||
}
|
||||
|
||||
private function installSwimmingPermissions() {
|
||||
SwimmingPermission::create(['name' => 'Mein Kind darf baden und kann schwimmen', 'slug' => SwimmingPermission::SWIMMING_PERMISSION_ALLOWED]);
|
||||
SwimmingPermission::create(['name' => 'Mein Kind darf baden und kann NICHT schwimmen', 'slug' => SwimmingPermission::SWIMMING_PERMISSION_LIMITED]);
|
||||
SwimmingPermission::create(['name' => 'Mein Kind darf nicht baden', 'slug' => SwimmingPermission::SWIMMING_PERMISSION_DENIED]);
|
||||
}
|
||||
|
||||
private function installEatingHabits() {
|
||||
EatingHabit::create(['name' => 'Vegan', 'slug' => EatingHabit::EATING_HABIT_VEGAN]);
|
||||
EatingHabit::create(['name' => 'Vegetarisch', 'slug' => EatingHabit::EATING_HABIT_VEGETARIAN]);
|
||||
EatingHabit::create(['name' => 'Omnivor', 'slug' => EatingHabit::EATING_HABIT_OMNIVOR]);
|
||||
|
||||
}
|
||||
private function installFirstAidPermissions() {
|
||||
FirstAidPermission::create([
|
||||
'name' => 'Zugestimmt',
|
||||
'description' => 'Ich STIMME der Anwendung von erweiteren Erste-Hilfe-Maßnahmen an meinem Kind explizit ZU.',
|
||||
'slug' => FirstAidPermission::FIRST_AID_PERMISSION_ALLOWED]);
|
||||
|
||||
FirstAidPermission::create([
|
||||
'name' => 'Verweigert',
|
||||
'description' => 'Ich LEHNE die Anwendung von erweiteren Erste-Hilfe-Maßnahmen an meinem Kind explizit AB.',
|
||||
'slug' => FirstAidPermission::FIRST_AID_PERMISSION_DENIED]);
|
||||
}
|
||||
|
||||
private function installCostUnitTypes() {
|
||||
CostUnitType::create(['slug' => CostUnitType::COST_UNIT_TYPE_EVENT, 'name' => 'Veranstaltung']);
|
||||
CostUnitType::create(['slug' => CostUnitType::COST_UNIT_TYPE_RUNNING_JOB, 'name' => 'Laufende Tätigkeit']);
|
||||
|
||||
}
|
||||
|
||||
private function installTenants() {
|
||||
Tenant::create([
|
||||
'slug' => 'lv',
|
||||
'local_group_name' => 'Landesunmittelbare Mitglieder',
|
||||
'url' => 'mareike.local',
|
||||
'account_iban' => 'DE12345678901234567890',
|
||||
'email' => 'test@example.com',
|
||||
'city' => 'Lommatzsch',
|
||||
'postcode' => '01623',
|
||||
'is_active_local_group' => true,
|
||||
'has_active_instance' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
namespace App\Middleware;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Inertia\Middleware;
|
||||
24
app/Middleware/IdentifyTenant.php
Normal file
24
app/Middleware/IdentifyTenant.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Middleware;
|
||||
|
||||
use App\Models\Tenant;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class IdentifyTenant
|
||||
{
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$host = $request->getHost();
|
||||
$tenant = Tenant::where(['url' => $host, 'has_active_instance' => true])->first();
|
||||
|
||||
if (! $tenant) {
|
||||
throw new NotFoundHttpException('Tenant not found');
|
||||
}
|
||||
|
||||
app()->instance('tenant', $tenant);
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
39
app/Models/Tenant.php
Normal file
39
app/Models/Tenant.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Scopes\CommonModel;
|
||||
|
||||
/**
|
||||
* @property string $slug
|
||||
* @property string $local_group
|
||||
* @property string $email
|
||||
* @property string $url
|
||||
* @property string $account_iban
|
||||
* @property string $city
|
||||
* @property string $postcode
|
||||
* @property string $gdpr_text
|
||||
* @property string $impress_text
|
||||
* @property string $url_participation_rules
|
||||
* @property boolean $events_allowed
|
||||
* @property boolean $has_active_instance
|
||||
*/
|
||||
class Tenant extends CommonModel
|
||||
{
|
||||
public const PRIMARY_TENANT_NAME = 'LV';
|
||||
|
||||
protected $fillable = [
|
||||
'slug',
|
||||
'local_group_name',
|
||||
'email',
|
||||
'url',
|
||||
'account_iban',
|
||||
'city',
|
||||
'postcode',
|
||||
'gdpr_text',
|
||||
'impress_text',
|
||||
'url_participation_rules',
|
||||
'is_active_local_group',
|
||||
'has_active_instance'
|
||||
];
|
||||
}
|
||||
@@ -2,15 +2,12 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\UserFactory> */
|
||||
use HasFactory, Notifiable;
|
||||
use Notifiable;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
@@ -18,8 +15,28 @@ class User extends Authenticatable
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'tenant_id',
|
||||
'user_role',
|
||||
'username',
|
||||
'firstname',
|
||||
'nickname',
|
||||
'lastname',
|
||||
'local_group_id',
|
||||
'membership_id',
|
||||
'address_1',
|
||||
'address_2',
|
||||
'postcode',
|
||||
'city',
|
||||
'email',
|
||||
'phone',
|
||||
'birthday',
|
||||
'medications',
|
||||
'allergies',
|
||||
'intolerances',
|
||||
'eating_habits',
|
||||
'swimming_permission',
|
||||
'first_aid_permission',
|
||||
'bank_account_iban',
|
||||
'password',
|
||||
];
|
||||
|
||||
@@ -29,7 +46,6 @@ class User extends Authenticatable
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
@@ -19,6 +20,11 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
//
|
||||
Auth::provider('tenant-users', function ($app, array $config) {
|
||||
return new TenantUserProvider(
|
||||
$app['hash'],
|
||||
$config['model']
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
26
app/Providers/InertiaProvider.php
Normal file
26
app/Providers/InertiaProvider.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Inertia\Inertia;
|
||||
use Inertia\Response;
|
||||
|
||||
final class InertiaProvider
|
||||
{
|
||||
private string $vueFile;
|
||||
private array $props;
|
||||
|
||||
public function __construct(string $vueFile, array $props) {
|
||||
$this->vueFile = $vueFile;
|
||||
$this->props = $props;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function render() : Response {
|
||||
return Inertia::render(
|
||||
str_replace('/', '/Views/', $this->vueFile),
|
||||
$this->props
|
||||
);
|
||||
}
|
||||
}
|
||||
23
app/Providers/TenantUserProvider.php
Normal file
23
app/Providers/TenantUserProvider.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Auth\EloquentUserProvider;
|
||||
|
||||
class TenantUserProvider extends EloquentUserProvider
|
||||
{
|
||||
public function retrieveByCredentials(array $credentials)
|
||||
{
|
||||
$query = $this->createModel()->newQuery();
|
||||
|
||||
foreach ($credentials as $key => $value) {
|
||||
if (! str_contains($key, 'password')) {
|
||||
$query->where($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
$query->where('tenant', app('tenant')->slug);
|
||||
|
||||
return $query->first();
|
||||
}
|
||||
}
|
||||
10
app/Scopes/CommonModel.php
Normal file
10
app/Scopes/CommonModel.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Scopes;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
abstract class CommonModel extends Model
|
||||
{
|
||||
|
||||
}
|
||||
13
app/Scopes/InstancedModel.php
Normal file
13
app/Scopes/InstancedModel.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Scopes;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
abstract class InstancedModel extends Model
|
||||
{
|
||||
protected static function booted()
|
||||
{
|
||||
static::addGlobalScope(new SiteScope());
|
||||
}
|
||||
}
|
||||
14
app/Scopes/SiteScope.php
Normal file
14
app/Scopes/SiteScope.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
namespace App\Scopes;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Scope;
|
||||
|
||||
class SiteScope implements Scope
|
||||
{
|
||||
public function apply(Builder $builder, Model $model): void
|
||||
{
|
||||
$builder->where($model->getTable() . '.tenant', app('tenant')->slug);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user