Add users, teams, authentication, profile/login/register/navbar views
This commit is contained in:
parent
436d22e385
commit
e47d493776
40
app/Actions/Fortify/CreateNewUser.php
Normal file
40
app/Actions/Fortify/CreateNewUser.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Laravel\Fortify\Contracts\CreatesNewUsers;
|
||||
|
||||
class CreateNewUser implements CreatesNewUsers
|
||||
{
|
||||
use PasswordValidationRules;
|
||||
|
||||
/**
|
||||
* Validate and create a newly registered user.
|
||||
*
|
||||
* @param array<string, string> $input
|
||||
*/
|
||||
public function create(array $input): User
|
||||
{
|
||||
Validator::make($input, [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => [
|
||||
'required',
|
||||
'string',
|
||||
'email',
|
||||
'max:255',
|
||||
Rule::unique(User::class),
|
||||
],
|
||||
'password' => $this->passwordRules(),
|
||||
])->validate();
|
||||
|
||||
return User::create([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
'password' => Hash::make($input['password']),
|
||||
]);
|
||||
}
|
||||
}
|
18
app/Actions/Fortify/PasswordValidationRules.php
Normal file
18
app/Actions/Fortify/PasswordValidationRules.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use Laravel\Fortify\Rules\Password;
|
||||
|
||||
trait PasswordValidationRules
|
||||
{
|
||||
/**
|
||||
* Get the validation rules used to validate passwords.
|
||||
*
|
||||
* @return array<int, \Illuminate\Contracts\Validation\Rule|array|string>
|
||||
*/
|
||||
protected function passwordRules(): array
|
||||
{
|
||||
return ['required', 'string', new Password, 'confirmed'];
|
||||
}
|
||||
}
|
29
app/Actions/Fortify/ResetUserPassword.php
Normal file
29
app/Actions/Fortify/ResetUserPassword.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Fortify\Contracts\ResetsUserPasswords;
|
||||
|
||||
class ResetUserPassword implements ResetsUserPasswords
|
||||
{
|
||||
use PasswordValidationRules;
|
||||
|
||||
/**
|
||||
* Validate and reset the user's forgotten password.
|
||||
*
|
||||
* @param array<string, string> $input
|
||||
*/
|
||||
public function reset(User $user, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'password' => $this->passwordRules(),
|
||||
])->validate();
|
||||
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($input['password']),
|
||||
])->save();
|
||||
}
|
||||
}
|
32
app/Actions/Fortify/UpdateUserPassword.php
Normal file
32
app/Actions/Fortify/UpdateUserPassword.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Fortify\Contracts\UpdatesUserPasswords;
|
||||
|
||||
class UpdateUserPassword implements UpdatesUserPasswords
|
||||
{
|
||||
use PasswordValidationRules;
|
||||
|
||||
/**
|
||||
* Validate and update the user's password.
|
||||
*
|
||||
* @param array<string, string> $input
|
||||
*/
|
||||
public function update(User $user, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'current_password' => ['required', 'string', 'current_password:web'],
|
||||
'password' => $this->passwordRules(),
|
||||
], [
|
||||
'current_password.current_password' => __('The provided password does not match your current password.'),
|
||||
])->validateWithBag('updatePassword');
|
||||
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($input['password']),
|
||||
])->save();
|
||||
}
|
||||
}
|
58
app/Actions/Fortify/UpdateUserProfileInformation.php
Normal file
58
app/Actions/Fortify/UpdateUserProfileInformation.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Fortify;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Laravel\Fortify\Contracts\UpdatesUserProfileInformation;
|
||||
|
||||
class UpdateUserProfileInformation implements UpdatesUserProfileInformation
|
||||
{
|
||||
/**
|
||||
* Validate and update the given user's profile information.
|
||||
*
|
||||
* @param array<string, string> $input
|
||||
*/
|
||||
public function update(User $user, array $input): void
|
||||
{
|
||||
Validator::make($input, [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
|
||||
'email' => [
|
||||
'required',
|
||||
'string',
|
||||
'email',
|
||||
'max:255',
|
||||
Rule::unique('users')->ignore($user->id),
|
||||
],
|
||||
])->validateWithBag('updateProfileInformation');
|
||||
|
||||
if ($input['email'] !== $user->email &&
|
||||
$user instanceof MustVerifyEmail) {
|
||||
$this->updateVerifiedUser($user, $input);
|
||||
} else {
|
||||
$user->forceFill([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
])->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given verified user's profile information.
|
||||
*
|
||||
* @param array<string, string> $input
|
||||
*/
|
||||
protected function updateVerifiedUser(User $user, array $input): void
|
||||
{
|
||||
$user->forceFill([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
'email_verified_at' => null,
|
||||
])->save();
|
||||
|
||||
$user->sendEmailVerificationNotification();
|
||||
}
|
||||
}
|
26
app/Http/Livewire/SwitchTeam.php
Normal file
26
app/Http/Livewire/SwitchTeam.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Team;
|
||||
use Livewire\Component;
|
||||
|
||||
class SwitchTeam extends Component
|
||||
{
|
||||
public function switch_to($team_id)
|
||||
{
|
||||
if (!auth()->user()->teams->contains($team_id)) {
|
||||
return;
|
||||
}
|
||||
$team_to_switch_to = Team::find($team_id);
|
||||
if (!$team_to_switch_to) {
|
||||
return;
|
||||
}
|
||||
session(['currentTeam' => $team_to_switch_to]);
|
||||
return redirect(request()->header('Referer'));
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.switch-team');
|
||||
}
|
||||
}
|
18
app/Models/BaseModel.php
Normal file
18
app/Models/BaseModel.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Xaevik\Cuid2\Cuid2;
|
||||
|
||||
abstract class BaseModel extends Model
|
||||
{
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::creating(function (Model $model) {
|
||||
$model->uuid = (string) new Cuid2();
|
||||
});
|
||||
}
|
||||
}
|
13
app/Models/Team.php
Normal file
13
app/Models/Team.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
class Team extends BaseModel
|
||||
{
|
||||
protected $casts = [
|
||||
'personal_team' => 'boolean',
|
||||
];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
];
|
||||
}
|
@ -2,11 +2,12 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
use Xaevik\Cuid2\Cuid2;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
@ -41,4 +42,28 @@ class User extends Authenticatable
|
||||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
];
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::creating(function (Model $model) {
|
||||
$model->uuid = (string) new Cuid2();
|
||||
});
|
||||
}
|
||||
public function teams()
|
||||
{
|
||||
return $this->belongsToMany(Team::class);
|
||||
}
|
||||
public function currentTeam()
|
||||
{
|
||||
return $this->belongsTo(Team::class);
|
||||
}
|
||||
public function otherTeams()
|
||||
{
|
||||
$team_id = session('currentTeam')->id;
|
||||
return auth()->user()->teams->filter(function ($team) use ($team_id) {
|
||||
return $team->id != $team_id;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
60
app/Providers/FortifyServiceProvider.php
Normal file
60
app/Providers/FortifyServiceProvider.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Actions\Fortify\CreateNewUser;
|
||||
use App\Actions\Fortify\ResetUserPassword;
|
||||
use App\Actions\Fortify\UpdateUserPassword;
|
||||
use App\Actions\Fortify\UpdateUserProfileInformation;
|
||||
use App\Models\User;
|
||||
use Illuminate\Cache\RateLimiting\Limit;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Laravel\Fortify\Fortify;
|
||||
|
||||
class FortifyServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
Fortify::loginView(fn () => view('auth.login'));
|
||||
Fortify::registerView(fn () => view('auth.register'));
|
||||
Fortify::authenticateUsing(function (Request $request) {
|
||||
$user = User::where('email', $request->email)->with('teams')->first();
|
||||
if (
|
||||
$user &&
|
||||
Hash::check($request->password, $user->password)
|
||||
) {
|
||||
session(['currentTeam' => $user->currentTeam = $user->teams->firstWhere('personal_team', true)]);
|
||||
return $user;
|
||||
}
|
||||
});
|
||||
Fortify::createUsersUsing(CreateNewUser::class);
|
||||
Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
|
||||
Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
|
||||
Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
|
||||
|
||||
RateLimiter::for('login', function (Request $request) {
|
||||
$email = (string) $request->email;
|
||||
|
||||
return Limit::perMinute(5)->by($email.$request->ip());
|
||||
});
|
||||
|
||||
RateLimiter::for('two-factor', function (Request $request) {
|
||||
return Limit::perMinute(5)->by($request->session()->get('login.id'));
|
||||
});
|
||||
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ class RouteServiceProvider extends ServiceProvider
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const HOME = '/home';
|
||||
public const HOME = '/';
|
||||
|
||||
/**
|
||||
* Define your route model bindings, pattern filters, and other route configuration.
|
||||
|
@ -7,13 +7,15 @@
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"laravel/fortify": "^1.16",
|
||||
"laravel/framework": "^10.0",
|
||||
"laravel/sanctum": "^3.2",
|
||||
"laravel/tinker": "^2.8",
|
||||
"livewire/livewire": "^2.12",
|
||||
"spatie/laravel-activitylog": "^4.7",
|
||||
"spatie/laravel-data": "^3.2",
|
||||
"spatie/laravel-ray": "^1.32"
|
||||
"spatie/laravel-ray": "^1.32",
|
||||
"xaevik/cuid2": "^1.7"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.9.1",
|
||||
|
344
composer.lock
generated
344
composer.lock
generated
@ -4,8 +4,62 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "c6bfcd94dc256f9124e84a380eaaf556",
|
||||
"content-hash": "0860841db6def79a62c268b0858d1f8a",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
"version": "2.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Bacon/BaconQrCode.git",
|
||||
"reference": "8674e51bb65af933a5ffaf1c308a660387c35c22"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/8674e51bb65af933a5ffaf1c308a660387c35c22",
|
||||
"reference": "8674e51bb65af933a5ffaf1c308a660387c35c22",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"dasprid/enum": "^1.0.3",
|
||||
"ext-iconv": "*",
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phly/keep-a-changelog": "^2.1",
|
||||
"phpunit/phpunit": "^7 | ^8 | ^9",
|
||||
"spatie/phpunit-snapshot-assertions": "^4.2.9",
|
||||
"squizlabs/php_codesniffer": "^3.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-imagick": "to generate QR code images"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"BaconQrCode\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-2-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ben Scholzen 'DASPRiD'",
|
||||
"email": "mail@dasprids.de",
|
||||
"homepage": "https://dasprids.de/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "BaconQrCode is a QR code generator for PHP.",
|
||||
"homepage": "https://github.com/Bacon/BaconQrCode",
|
||||
"support": {
|
||||
"issues": "https://github.com/Bacon/BaconQrCode/issues",
|
||||
"source": "https://github.com/Bacon/BaconQrCode/tree/2.0.8"
|
||||
},
|
||||
"time": "2022-12-07T17:46:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "brick/math",
|
||||
"version": "0.10.2",
|
||||
@ -62,6 +116,56 @@
|
||||
],
|
||||
"time": "2022-08-10T22:54:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dasprid/enum",
|
||||
"version": "1.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DASPRiD/Enum.git",
|
||||
"reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
|
||||
"reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1 <9.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7 | ^8 | ^9",
|
||||
"squizlabs/php_codesniffer": "*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"DASPRiD\\Enum\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-2-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ben Scholzen 'DASPRiD'",
|
||||
"email": "mail@dasprids.de",
|
||||
"homepage": "https://dasprids.de/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "PHP 7.1 enum implementation",
|
||||
"keywords": [
|
||||
"enum",
|
||||
"map"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/DASPRiD/Enum/issues",
|
||||
"source": "https://github.com/DASPRiD/Enum/tree/1.0.4"
|
||||
},
|
||||
"time": "2023-03-01T18:44:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dflydev/dot-access-data",
|
||||
"version": "v3.0.2",
|
||||
@ -1024,6 +1128,69 @@
|
||||
],
|
||||
"time": "2021-10-07T12:57:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/fortify",
|
||||
"version": "v1.16.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/fortify.git",
|
||||
"reference": "e626fc70fcd940d01326c6c44512398cccc3113c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/fortify/zipball/e626fc70fcd940d01326c6c44512398cccc3113c",
|
||||
"reference": "e626fc70fcd940d01326c6c44512398cccc3113c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"bacon/bacon-qr-code": "^2.0",
|
||||
"ext-json": "*",
|
||||
"illuminate/support": "^8.82|^9.0|^10.0",
|
||||
"php": "^7.3|^8.0",
|
||||
"pragmarx/google2fa": "^7.0|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.0",
|
||||
"orchestra/testbench": "^6.0|^7.0|^8.0",
|
||||
"phpunit/phpunit": "^9.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Laravel\\Fortify\\FortifyServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laravel\\Fortify\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "Backend controllers and scaffolding for Laravel authentication.",
|
||||
"keywords": [
|
||||
"auth",
|
||||
"laravel"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/fortify/issues",
|
||||
"source": "https://github.com/laravel/fortify"
|
||||
},
|
||||
"time": "2023-01-06T15:57:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v10.3.3",
|
||||
@ -2319,6 +2486,73 @@
|
||||
],
|
||||
"time": "2023-02-08T01:06:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/constant_time_encoding",
|
||||
"version": "v2.6.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paragonie/constant_time_encoding.git",
|
||||
"reference": "58c3f47f650c94ec05a151692652a868995d2938"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/58c3f47f650c94ec05a151692652a868995d2938",
|
||||
"reference": "58c3f47f650c94ec05a151692652a868995d2938",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7|^8"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^6|^7|^8|^9",
|
||||
"vimeo/psalm": "^1|^2|^3|^4"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ParagonIE\\ConstantTime\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paragon Initiative Enterprises",
|
||||
"email": "security@paragonie.com",
|
||||
"homepage": "https://paragonie.com",
|
||||
"role": "Maintainer"
|
||||
},
|
||||
{
|
||||
"name": "Steve 'Sc00bz' Thomas",
|
||||
"email": "steve@tobtu.com",
|
||||
"homepage": "https://www.tobtu.com",
|
||||
"role": "Original Developer"
|
||||
}
|
||||
],
|
||||
"description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
|
||||
"keywords": [
|
||||
"base16",
|
||||
"base32",
|
||||
"base32_decode",
|
||||
"base32_encode",
|
||||
"base64",
|
||||
"base64_decode",
|
||||
"base64_encode",
|
||||
"bin2hex",
|
||||
"encoding",
|
||||
"hex",
|
||||
"hex2bin",
|
||||
"rfc4648"
|
||||
],
|
||||
"support": {
|
||||
"email": "info@paragonie.com",
|
||||
"issues": "https://github.com/paragonie/constant_time_encoding/issues",
|
||||
"source": "https://github.com/paragonie/constant_time_encoding"
|
||||
},
|
||||
"time": "2022-06-14T06:56:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-common",
|
||||
"version": "2.2.0",
|
||||
@ -2603,6 +2837,58 @@
|
||||
},
|
||||
"time": "2021-10-28T11:13:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pragmarx/google2fa",
|
||||
"version": "v8.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/antonioribeiro/google2fa.git",
|
||||
"reference": "80c3d801b31fe165f8fe99ea085e0a37834e1be3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/80c3d801b31fe165f8fe99ea085e0a37834e1be3",
|
||||
"reference": "80c3d801b31fe165f8fe99ea085e0a37834e1be3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"paragonie/constant_time_encoding": "^1.0|^2.0",
|
||||
"php": "^7.1|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.18",
|
||||
"phpunit/phpunit": "^7.5.15|^8.5|^9.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PragmaRX\\Google2FA\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Antonio Carlos Ribeiro",
|
||||
"email": "acr@antoniocarlosribeiro.com",
|
||||
"role": "Creator & Designer"
|
||||
}
|
||||
],
|
||||
"description": "A One Time Password Authentication package, compatible with Google Authenticator.",
|
||||
"keywords": [
|
||||
"2fa",
|
||||
"Authentication",
|
||||
"Two Factor Authentication",
|
||||
"google2fa"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/antonioribeiro/google2fa/issues",
|
||||
"source": "https://github.com/antonioribeiro/google2fa/tree/v8.0.1"
|
||||
},
|
||||
"time": "2022-06-13T21:57:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
"version": "2.0.2",
|
||||
@ -6384,6 +6670,62 @@
|
||||
},
|
||||
"time": "2022-06-03T18:03:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "xaevik/cuid2",
|
||||
"version": "1.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "git@gitlab.com:xaevik/php-cuid2.git",
|
||||
"reference": "e435e5005b2e9e9e9d30b64025749c0b7aa5dcf7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://gitlab.com/api/v4/projects/xaevik%2Fphp-cuid2/repository/archive.zip?sha=e435e5005b2e9e9e9d30b64025749c0b7aa5dcf7",
|
||||
"reference": "e435e5005b2e9e9e9d30b64025749c0b7aa5dcf7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ergebnis/composer-normalize": "^2.29",
|
||||
"ext-ctype": "*",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.3",
|
||||
"phpstan/phpstan": "^1.9",
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"squizlabs/php_codesniffer": "^3.7",
|
||||
"vimeo/psalm": "^5.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gmp": "*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/compat.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Xaevik\\Cuid2\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alan Brault",
|
||||
"email": "alan.brault@visus.io"
|
||||
}
|
||||
],
|
||||
"description": "A PHP library for generating collision-resistant ids (CUIDs).",
|
||||
"keywords": [
|
||||
"cuid",
|
||||
"identifier"
|
||||
],
|
||||
"abandoned": "visus/cuid2",
|
||||
"time": "2023-02-21T14:01:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "zbateson/mail-mime-parser",
|
||||
"version": "2.4.0",
|
||||
|
@ -190,6 +190,7 @@
|
||||
* Application Service Providers...
|
||||
*/
|
||||
App\Providers\AppServiceProvider::class,
|
||||
App\Providers\FortifyServiceProvider::class,
|
||||
App\Providers\AuthServiceProvider::class,
|
||||
// App\Providers\BroadcastServiceProvider::class,
|
||||
App\Providers\EventServiceProvider::class,
|
||||
|
147
config/fortify.php
Normal file
147
config/fortify.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
use App\Providers\RouteServiceProvider;
|
||||
use Laravel\Fortify\Features;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Fortify Guard
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which authentication guard Fortify will use while
|
||||
| authenticating users. This value should correspond with one of your
|
||||
| guards that is already present in your "auth" configuration file.
|
||||
|
|
||||
*/
|
||||
|
||||
'guard' => 'web',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Fortify Password Broker
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which password broker Fortify can use when a user
|
||||
| is resetting their password. This configured value should match one
|
||||
| of your password brokers setup in your "auth" configuration file.
|
||||
|
|
||||
*/
|
||||
|
||||
'passwords' => 'users',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Username / Email
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value defines which model attribute should be considered as your
|
||||
| application's "username" field. Typically, this might be the email
|
||||
| address of the users but you are free to change this value here.
|
||||
|
|
||||
| Out of the box, Fortify expects forgot password and reset password
|
||||
| requests to have a field named 'email'. If the application uses
|
||||
| another name for the field you may define it below as needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'username' => 'email',
|
||||
|
||||
'email' => 'email',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Home Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the path where users will get redirected during
|
||||
| authentication or password reset when the operations are successful
|
||||
| and the user is authenticated. You are free to change this value.
|
||||
|
|
||||
*/
|
||||
|
||||
'home' => RouteServiceProvider::HOME,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Fortify Routes Prefix / Subdomain
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which prefix Fortify will assign to all the routes
|
||||
| that it registers with the application. If necessary, you may change
|
||||
| subdomain under which all of the Fortify routes will be available.
|
||||
|
|
||||
*/
|
||||
|
||||
'prefix' => '',
|
||||
|
||||
'domain' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Fortify Routes Middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which middleware Fortify will assign to the routes
|
||||
| that it registers with the application. If necessary, you may change
|
||||
| these middleware but typically this provided default is preferred.
|
||||
|
|
||||
*/
|
||||
|
||||
'middleware' => ['web'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Rate Limiting
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default, Fortify will throttle logins to five requests per minute for
|
||||
| every email and IP address combination. However, if you would like to
|
||||
| specify a custom rate limiter to call then you may specify it here.
|
||||
|
|
||||
*/
|
||||
|
||||
'limiters' => [
|
||||
'login' => 'login',
|
||||
'two-factor' => 'two-factor',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register View Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify if the routes returning views should be disabled as
|
||||
| you may not need them when building your own application. This may be
|
||||
| especially true if you're writing a custom single-page application.
|
||||
|
|
||||
*/
|
||||
|
||||
'views' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Features
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Some of the Fortify features are optional. You may disable the features
|
||||
| by removing them from this array. You're free to only remove some of
|
||||
| these features or you can even remove all of these if you need to.
|
||||
|
|
||||
*/
|
||||
|
||||
'features' => [
|
||||
Features::registration(),
|
||||
Features::resetPasswords(),
|
||||
// Features::emailVerification(),
|
||||
Features::updateProfileInformation(),
|
||||
Features::updatePasswords(),
|
||||
Features::twoFactorAuthentication([
|
||||
'confirm' => true,
|
||||
'confirmPassword' => true,
|
||||
// 'window' => 0,
|
||||
]),
|
||||
],
|
||||
|
||||
];
|
@ -13,6 +13,8 @@ public function up(): void
|
||||
{
|
||||
Schema::create('users', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uuid')->unique();
|
||||
$table->boolean('is_root_user')->default(false);
|
||||
$table->string('name');
|
||||
$table->string('email')->unique();
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
|
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Laravel\Fortify\Fortify;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->text('two_factor_secret')
|
||||
->after('password')
|
||||
->nullable();
|
||||
|
||||
$table->text('two_factor_recovery_codes')
|
||||
->after('two_factor_secret')
|
||||
->nullable();
|
||||
|
||||
if (Fortify::confirmsTwoFactorAuthentication()) {
|
||||
$table->timestamp('two_factor_confirmed_at')
|
||||
->after('two_factor_recovery_codes')
|
||||
->nullable();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn(array_merge([
|
||||
'two_factor_secret',
|
||||
'two_factor_recovery_codes',
|
||||
], Fortify::confirmsTwoFactorAuthentication() ? [
|
||||
'two_factor_confirmed_at',
|
||||
] : []));
|
||||
});
|
||||
}
|
||||
};
|
@ -16,6 +16,7 @@ public function up(): void
|
||||
$table->morphs('tokenable');
|
||||
$table->string('name');
|
||||
$table->string('token', 64)->unique();
|
||||
$table->string('team_id');
|
||||
$table->text('abilities')->nullable();
|
||||
$table->timestamp('last_used_at')->nullable();
|
||||
$table->timestamp('expires_at')->nullable();
|
||||
|
30
database/migrations/2023_03_20_112811_create_teams_table.php
Normal file
30
database/migrations/2023_03_20_112811_create_teams_table.php
Normal file
@ -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
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('teams', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uuid')->unique();
|
||||
$table->string('name');
|
||||
$table->boolean('personal_team')->default(false);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('teams');
|
||||
}
|
||||
};
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('team_user', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('team_id');
|
||||
$table->foreignId('user_id');
|
||||
$table->string('role')->nullable();
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['team_id', 'user_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('team_user');
|
||||
}
|
||||
};
|
@ -2,21 +2,17 @@
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed the application's database.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
// \App\Models\User::factory(10)->create();
|
||||
|
||||
// \App\Models\User::factory()->create([
|
||||
// 'name' => 'Test User',
|
||||
// 'email' => 'test@example.com',
|
||||
// ]);
|
||||
if (env('APP_ENV') === 'local') {
|
||||
$this->call([
|
||||
UserSeeder::class,
|
||||
TeamSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
45
database/seeders/TeamSeeder.php
Normal file
45
database/seeders/TeamSeeder.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class TeamSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
$root_user = User::find(1);
|
||||
$normal_user = User::find(2);
|
||||
|
||||
$root_user_personal_team = Team::create([
|
||||
'name' => "Root Team",
|
||||
'personal_team' => true,
|
||||
]);
|
||||
$root_user_other_team = Team::create([
|
||||
'name' => "Root User's Other Team",
|
||||
'personal_team' => false,
|
||||
]);
|
||||
$normal_user_personal_team = Team::create([
|
||||
'name' => 'Normal Team',
|
||||
'personal_team' => true,
|
||||
]);
|
||||
DB::table('team_user')->insert([
|
||||
'team_id' => $root_user_personal_team->id,
|
||||
'user_id' => $root_user->id,
|
||||
'role' => 'admin',
|
||||
]);
|
||||
DB::table('team_user')->insert([
|
||||
'team_id' => $root_user_other_team->id,
|
||||
'user_id' => $root_user->id,
|
||||
'role' => 'admin',
|
||||
]);
|
||||
DB::table('team_user')->insert([
|
||||
'team_id' => $normal_user_personal_team->id,
|
||||
'user_id' => $normal_user->id,
|
||||
'role' => 'admin',
|
||||
]);
|
||||
}
|
||||
}
|
26
database/seeders/UserSeeder.php
Normal file
26
database/seeders/UserSeeder.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class UserSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
User::factory()->create([
|
||||
'id' => 1,
|
||||
'name' => 'Root User',
|
||||
'email' => 'test@example.com',
|
||||
'is_root_user' => true,
|
||||
]);
|
||||
User::factory()->create([
|
||||
'id' => 2,
|
||||
'name' => 'Normal User',
|
||||
'email' => 'test2@example.com',
|
||||
]);
|
||||
}
|
||||
}
|
20
resources/views/auth/login.blade.php
Normal file
20
resources/views/auth/login.blade.php
Normal file
@ -0,0 +1,20 @@
|
||||
<x-layout>
|
||||
<div>
|
||||
<form action="/login" method="POST">
|
||||
@csrf
|
||||
<input type="text" name="email" placeholder="email" @env('local') value="test@example.com" @endenv
|
||||
autofocus />
|
||||
<input type="password" name="password" placeho lder="Password" @env('local') value="password" @endenv />
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</x-layout>
|
20
resources/views/auth/register.blade.php
Normal file
20
resources/views/auth/register.blade.php
Normal file
@ -0,0 +1,20 @@
|
||||
<x-layout>
|
||||
<form action="/register" method="POST">
|
||||
@csrf
|
||||
<input type="text" name="name" placeholder="name" @env('local') value="Andras Bacsai" @endenv />
|
||||
<input type="text" name="email" placeholder="email" @env('local') value="andras@bacsai.com" @endenv />
|
||||
<input type="password" name="password" placeholder="Password" @env('local') value="password" @endenv />
|
||||
<input type="password" name="password_confirmation" placeholder="Password"
|
||||
@env('local') value="password" @endenv />
|
||||
<button type="submit">Register</button>
|
||||
</form>
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul>
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
</x-layout>
|
@ -1,3 +0,0 @@
|
||||
<button wire:loading.remove {{ $attributes }} class="btn btn-primary rounded-none btn-xs no-animation"> {{ $slot }} </button>
|
||||
|
||||
<button wire:loading class="btn btn-disabled rounded-none btn-xs no-animation"> {{ $slot }}</button>
|
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" data-theme="light" class="h-full">
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
@ -10,11 +10,9 @@
|
||||
@livewireStyles
|
||||
</head>
|
||||
|
||||
<body class="h-full">
|
||||
@auth
|
||||
<x-navbar />
|
||||
@endauth
|
||||
<main class="h-full pt-10 p-4">
|
||||
<body>
|
||||
<x-navbar />
|
||||
<main>
|
||||
{{ $slot }}
|
||||
</main>
|
||||
|
||||
|
@ -1,15 +1,15 @@
|
||||
<nav class="flex space-x-4 p-2 fixed right-0">
|
||||
@env('local')
|
||||
<a href="/run-command">Run command</a>
|
||||
{{-- <livewire:create-token /> --}}
|
||||
<a href="/debug">Debug</a>
|
||||
<a href="/debug/logs" target="_blank">Debug Logs</a>
|
||||
{{-- <a href="/debug/inertia">Debug(inertia)</a> --}}
|
||||
@endenv
|
||||
<a href="/">Dashboard</a>
|
||||
<a href="/profile">Profile</a>
|
||||
<form action="/logout" method="POST">
|
||||
@csrf
|
||||
<button type="submit">Logout</button>
|
||||
</form>
|
||||
<nav>
|
||||
<a href="/">Home</a>
|
||||
@guest
|
||||
<a href="/login">Login</a>
|
||||
<a href="/register">Register</a>
|
||||
@endguest
|
||||
@auth
|
||||
<a href="/demo">Demo</a>
|
||||
<a href="/profile">Profile</a>
|
||||
<form action="/logout" method="POST">
|
||||
@csrf
|
||||
<button type="submit">Logout</button>
|
||||
</form>
|
||||
@endauth
|
||||
</nav>
|
||||
|
@ -1,5 +1,3 @@
|
||||
<x-layout>
|
||||
|
||||
<livewire:run-command />
|
||||
|
||||
</x-layout>
|
||||
|
10
resources/views/home.blade.php
Normal file
10
resources/views/home.blade.php
Normal file
@ -0,0 +1,10 @@
|
||||
<x-layout>
|
||||
<h1>
|
||||
Coolify v4 🎉
|
||||
</h1>
|
||||
@guest
|
||||
<p>
|
||||
To see the demo, please <a href='/login'>login<a> or <a href='/register'>register<a>.
|
||||
</p>
|
||||
@endguest
|
||||
</x-layout>
|
@ -1,7 +1,8 @@
|
||||
<div>
|
||||
<div>
|
||||
<label for="command">
|
||||
<input class="py-2 rounded ring-1" id="command" wire:model="command" type="text" />
|
||||
<input autofocus class="py-2 rounded ring-1" id="command" wire:model="command" type="text"
|
||||
wire:keydown.enter="runCommand" />
|
||||
</label>
|
||||
<button wire:click="runCommand">Run command</button>
|
||||
|
||||
@ -20,8 +21,7 @@
|
||||
<div>
|
||||
Activity: <span>{{ $activity?->id ?? 'waiting' }}</span>
|
||||
</div>
|
||||
<pre style="width: 100%;overflow-y: scroll;"
|
||||
@if ($isKeepAliveOn || $manualKeepAlive) wire:poll.750ms="polling" @endif>{{ data_get($activity, 'description') }}</pre>
|
||||
<pre style="width: 100%;overflow-y: scroll;" @if ($isKeepAliveOn || $manualKeepAlive) wire:poll.750ms="polling" @endif>{{ data_get($activity, 'description') }}</pre>
|
||||
<div>
|
||||
<div>Details:</div>
|
||||
<pre style="width: 100%;overflow-y: scroll;">{{ json_encode(data_get($activity, 'properties'), JSON_PRETTY_PRINT) }}</pre>
|
||||
|
6
resources/views/livewire/switch-team.blade.php
Normal file
6
resources/views/livewire/switch-team.blade.php
Normal file
@ -0,0 +1,6 @@
|
||||
<div>
|
||||
@foreach (auth()->user()->otherTeams() as $team)
|
||||
<button wire:key="{{ $team->id }}" wire:click="switch_to('{{ $team->id }}')">Switch to:
|
||||
{{ $team->name }}</button>
|
||||
@endforeach
|
||||
</div>
|
17
resources/views/profile.blade.php
Normal file
17
resources/views/profile.blade.php
Normal file
@ -0,0 +1,17 @@
|
||||
<x-layout>
|
||||
<div>
|
||||
<div>
|
||||
<h3>User</h3>
|
||||
<p>Name: {{ auth()->user()->name }}</p>
|
||||
<p>Id: {{ auth()->user()->id }}</p>
|
||||
<p>Uuid: {{ auth()->user()->uuid }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Current Team</h3>
|
||||
<p>Name: {{ session('currentTeam')->name }}</p>
|
||||
<p>Id: {{ session('currentTeam')->id }}</p>
|
||||
<p>Uuid: {{ session('currentTeam')->uuid }}</p>
|
||||
</div>
|
||||
<livewire:switch-team>
|
||||
</div>
|
||||
</x-layout>
|
@ -1,22 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{ $title ?? 'Coolify' }}</title>
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
@vite(['resources/js/app.js', 'resources/css/app.css'])
|
||||
</head>
|
||||
|
||||
<body class="antialiased">
|
||||
<h1 class="text-3xl font-bold">
|
||||
Coolify v4
|
||||
</h1>
|
||||
|
||||
<p class="mt-4">
|
||||
<a href="/demo"> See demo </a>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -14,7 +14,14 @@
|
||||
*/
|
||||
|
||||
Route::get('/', function () {
|
||||
return view('welcome');
|
||||
return view('home');
|
||||
});
|
||||
|
||||
Route::view('/demo', 'demo');
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/profile', function () {
|
||||
return view('profile');
|
||||
});
|
||||
Route::get('/demo', function () {
|
||||
return view('demo');
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user