transition

This commit is contained in:
2024-08-14 22:04:34 +03:00
parent 1ab3f678b7
commit 1f3ebafe69
50 changed files with 924 additions and 172 deletions
+4 -8
View File
@@ -119,24 +119,20 @@ readonly class AuthService
}
/**
* @throws LucentException
*/
public
function sendLoginEmail(string $email): void
public function sendLoginEmail(string $email): void
{
$emailAddress = (new Email($email));
$user = $this->userRepo->findByEmail($emailAddress);
if ($user->isEmpty()) {
throw new LucentException("User not found");
return;
}
if ($user->get()->isRemoved()) {
throw new LucentException("Cannot reset email if the user is not active");
return;
}
$newToken = $this->userRepo->updateLoginToken($user->get()->id);
Mail::to($email)->send(
+16 -27
View File
@@ -13,11 +13,13 @@ use Lucent\Account\AuthService;
use Lucent\Channel\ChannelService;
use Lucent\LucentException;
use Lucent\Svelte\Svelte;
use Lucent\Util\Form\FormException;
use Lucent\Util\Form\ResponseFormError;
use function Lucent\Response\fail;
use function Lucent\Response\ok;
class AuthController extends Controller
class AuthController
{
public function __construct(
private readonly AuthService $authService,
@@ -65,52 +67,39 @@ class AuthController extends Controller
return ok();
}
public function login(): View|RedirectResponse
public function login()
{
if ($this->accountService->countUsers() == 0) {
return redirect($this->channelService->channel->lucentUrl . "/register");
}
return $this->svelte->render(
layout: "account",
view: "login",
title: "Log in"
);
return view("lucent::auth.login");
}
public function postLogin(Request $request): Response
public function postLogin(Request $request)
{
try {
$this->authService->sendLoginEmail($request->input("email"));
} catch (LucentException $th) {
return fail($th);
}
$this->authService->sendLoginEmail($request->input("email"));
return ok();
return view("lucent::auth.login-success");
}
public function verify(Request $request): View
{
return $this->svelte->render(
layout: "account",
view: "verify",
title: "Verify and enter",
data: [
"email" => $request->input("email"),
"token" => $request->input("token"),
]
);
return view("lucent::auth.verify", [
"email" => $request->input("email"),
"token" => $request->input("token"),
]);
}
public function postVerify(Request $request): Response
public function postVerify(Request $request)
{
try {
$this->authService->login($request->input("email"), $request->input("token"));
} catch (LucentException $th) {
return fail($th);
return ResponseFormError::fromException($th);
}
return ok();
return [];
}
+28 -6
View File
@@ -21,14 +21,36 @@ class HomeController extends Controller
{
}
public function home(): View
public function home(Request $request): View
{
$urlParams = $request->all();
$users = $this->accountService->all();
$sort = data_get($urlParams, "sort") ?? "-_sys.updatedAt";
$filter = data_get($urlParams, "filter") ?? [];
$arguments = array_merge([
"schema_in" => $this->accountService->currentReadableSchemas(),
"status_in" => ["draft", "published"]
], $filter);
$limit = 10;
$graph = $this->query
->filter($arguments)
->limit($limit)
->childrenDepth(1)
->parentsDepth(0)
->sort($sort)
->run();
return view("lucent::home", [
"users" => $users,
"records" => $graph->getRootRecords(),
"graph" => toArray($graph),
"modalUrl" => $request->fullUrl(),
]);
return $this->svelte->render(
layout: "channel",
view: "homeIndex",
title: "Records",
);
}
public function records(Request $request): Response
+9 -3
View File
@@ -4,15 +4,19 @@ namespace Lucent\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\View;
use Lucent\Account\AccountService;
use Lucent\Account\AuthService;
use Lucent\Channel\ChannelService;
use Lucent\ViewModel\ViewModel;
readonly class AuthMiddleware
{
public function __construct(
private AuthService $authService,
private ChannelService $channelService
private AccountService $accountService,
private ChannelService $channelService,
private ViewModel $viewModel
)
{
}
@@ -22,9 +26,11 @@ readonly class AuthMiddleware
if (!$this->authService->isLoggedIn()) {
return redirect($this->channelService->channel->lucentUrl . "/login");
}
$this->authService->refreshSession();
View::share("channel",$this->channelService->channel);
View::share("user",session("user"));
View::share("schemas",$this->channelService->channel->schemas->whereIn("name",$this->accountService->currentReadableSchemas())->values());
View::share("viewModel",$this->viewModel);
return $next($request);
}
+4 -1
View File
@@ -3,6 +3,7 @@
namespace Lucent;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
use Intervention\Image\ImageManager;
@@ -58,7 +59,7 @@ class LucentServiceProvider extends ServiceProvider
$router->aliasMiddleware('lucent.auth', \Lucent\Http\Middleware\AuthMiddleware::class);
$router->aliasMiddleware('lucent.guest', \Lucent\Http\Middleware\GuestMiddleware::class);
$this->loadViewsFrom(__DIR__ . '/Views', 'lucent');
$this->loadViewsFrom(__DIR__ . '/../front/views', 'lucent');
$this->loadRoutesFrom(__DIR__ . '/Http/web.php');
$this->loadRoutesFrom(__DIR__ . '/Http/api.php');
@@ -76,6 +77,7 @@ class LucentServiceProvider extends ServiceProvider
View::share('manifest', $manifest);
View::share('image', app()->make(ImageService::class));
View::share('file', app()->make(FileService::class));
Blade::anonymousComponentPath(__DIR__.'../front/views/components',"lucent");
$this->publishes([
__DIR__ . '/Config/main.php' => config_path('lucent.php'),
@@ -83,6 +85,7 @@ class LucentServiceProvider extends ServiceProvider
$this->publishes([
__DIR__ . '/../front/dist' => public_path('vendor/lucent/dist'),
__DIR__ . '/../front/public' => public_path('vendor/lucent/public'),
], 'lucent');
}
}
+17
View File
@@ -0,0 +1,17 @@
<?php
namespace Lucent\Util\Form;
use Exception;
final class FormException extends Exception
{
// Redefine the exception so message isn't optional
public function __construct(string $message, int $code = 0, Exception $previous = null)
{
// make sure everything is assigned properly
parent::__construct($message, $code, $previous);
}
}
+59
View File
@@ -0,0 +1,59 @@
<?php
namespace Lucent\Util\Form;
use Exception;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Response;
use Illuminate\Validation\Validator;
use Lucent\LucentException;
class ResponseFormError
{
/**
* @param $errors list<string>
*/
public static function render(array $errors): ResponseFactory|Application|Response
{
return response(view("lucent::forms.errors", ["errors" => $errors])->render(), 400);
}
/**
* @param Validator $validator
* @return ResponseFactory|Application|Response
*/
public static function fromValidator(Validator $validator): ResponseFactory|Application|Response
{
return self::render($validator->errors()->all());
}
/**
* @param array $errors
* @return ResponseFactory|Application|Response
*/
public static function fromArray(array $errors): ResponseFactory|Application|Response
{
return self::render($errors);
}
/**
* @param string $errorString
* @return ResponseFactory|Application|Response
*/
public static function fromMessage(string $errorString): ResponseFactory|Application|Response
{
return self::render([$errorString]);
}
/**
* @param LucentException|FormException $exception
* @return ResponseFactory|Application|Response
*/
public static function fromException(LucentException|FormException $exception): ResponseFactory|Application|Response
{
return self::render([$exception->getMessage()]);
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace Lucent\ViewModel;
use Lucent\Channel\ChannelService;
use Lucent\Record\QueryRecord;
use Lucent\Record\Status;
use Lucent\Schema\CollectionSchema;
use Lucent\Schema\FieldInterface;
use Lucent\Schema\FilesSchema;
use Mustache_Engine;
class ViewModel
{
public function __construct(
public ChannelService $channelService
)
{
}
public function getRecordName(QueryRecord $record): string
{
$schema = $this->channelService->getSchema($record->schema)->get();
if (empty($schema->titleTemplate)) {
$title = match (get_class($schema)) {
CollectionSchema::class => $record->data[$schema->fields->filter(fn(FieldInterface $f) => $f->info->name === "text")->first()->name],
FilesSchema::class => $record->_file->path,
};
if (empty(trim($title))) {
return "~Untitled~";
}
return $title;
}
$m = new Mustache_Engine(array('entity_flags' => ENT_QUOTES));
return $m->render($schema->titleTemplate, $record->data);
}
}
-5
View File
@@ -1,5 +0,0 @@
Login to your Lucent account!
If you were not the one making this request, please ignore this email.
{{ $url }}/verify?email={{ $email }}&token={{ $token }}
-35
View File
@@ -1,35 +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">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title') - Lucent Data Platform</title>
@if(config("lucent.env") == "production")
<!-- if production -->
<link rel="stylesheet" href="/vendor/lucent/dist/{{ $manifest['main.css']["file"] }}"/>
<script type="module" src="/vendor/lucent/dist/{{ $manifest['main.js']["file"] }}"></script>
@else
<!-- if development -->
@php
echo '<script type="module" crossorigin src="http://127.0.0.1:5173/@vite/client"></script>';
@endphp
<script type="module" crossorigin src="http://127.0.0.1:5173/main.js"></script>
@endif
<link rel="icon" type="image/x-icon" href="/favicon.ico">
</head>
<body class="view-{{ $view }}">
<div class="mt-5">
@yield('content')
</div>
</body>
</html>
-30
View File
@@ -1,30 +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">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title') - Lucent Data Platform</title>
@if(config("lucent.env") == "production")
<!-- if production -->
<link rel="stylesheet" href="/vendor/lucent/dist/{{ $manifest['main.css']["file"] }}"/>
<script type="module" src="/vendor/lucent/dist/{{ $manifest['main.js']["file"] }}"></script>
@else
<!-- if development -->
@php
echo '<script type="module" crossorigin src="http://127.0.0.1:5173/@vite/client"></script>';
@endphp
<script type="module" crossorigin src="http://127.0.0.1:5173/main.js"></script>
@endif
<link rel="icon" type="image/x-icon" href="/favicon.ico">
</head>
<body class="view-{{ $view }}">
@yield('content')
</body>
</html>
-10
View File
@@ -1,10 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{$title}}</title>
<meta http-equiv="refresh" content="0; url='{{$to}}'"/>
</head>
<body>
<p>{{$message}}</p>
</body>
</html>
-7
View File
@@ -1,7 +0,0 @@
@extends('lucent::layouts.'.$layout)
@section('title')
{{ $title }}
@endsection
@section('content')
{!! $svelte !!}
@endsection