Introduzione procedura di inizializzazione

This commit is contained in:
Dasc3er 2021-02-19 14:39:39 +01:00
parent b93ee1a7f6
commit 2f2e59e325
73 changed files with 916 additions and 371 deletions

View File

@ -3,7 +3,7 @@ APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
APP_LOCALE =
APP_LOCALE=
LOG_CHANNEL=stack
LOG_LEVEL=debug

View File

@ -13,13 +13,11 @@ class Kernel extends ConsoleKernel
* @var array
*/
protected $commands = [
//
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)

View File

@ -14,7 +14,6 @@ class Handler extends ExceptionHandler
* @var array
*/
protected $dontReport = [
//
];
/**
@ -35,7 +34,6 @@ class Handler extends ExceptionHandler
public function register()
{
$this->reportable(function (Throwable $e) {
//
});
$this->renderable(function (NotFoundException $e, $request) {

View File

@ -6,5 +6,4 @@ use Exception;
class LegacyExitException extends Exception
{
}

View File

@ -7,7 +7,7 @@ use Throwable;
class LegacyRedirectException extends Exception
{
public function __construct($message = "", $code = 0, Throwable $previous = null)
public function __construct($message = '', $code = 0, Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}

View File

@ -23,7 +23,6 @@ class AuthenticatedSessionController extends Controller
/**
* Handle an incoming authentication request.
*
* @param \App\Http\Requests\Auth\LoginRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(LoginRequest $request)
@ -38,7 +37,6 @@ class AuthenticatedSessionController extends Controller
/**
* Destroy an authenticated session.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Request $request)

View File

@ -13,7 +13,6 @@ class ConfirmablePasswordController extends Controller
/**
* Show the confirm password view.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\View\View
*/
public function show(Request $request)
@ -24,18 +23,15 @@ class ConfirmablePasswordController extends Controller
/**
* Confirm the user's password.
*
* @param \Illuminate\Http\Request $request
* @return mixed
*/
public function store(Request $request)
{
if (! Auth::guard('web')->validate([
if (!Auth::guard('web')->validate([
'usernamen' => $request->user()->usernamen,
'password' => $request->password,
])) {
throw ValidationException::withMessages([
'password' => tr('auth.password'),
]);
throw ValidationException::withMessages(['password' => tr('auth.password')]);
}
$request->session()->put('auth.password_confirmed_at', time());

View File

@ -11,7 +11,6 @@ class EmailVerificationNotificationController extends Controller
/**
* Send a new email verification notification.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)

View File

@ -11,7 +11,6 @@ class EmailVerificationPromptController extends Controller
/**
* Display the email verification prompt.
*
* @param \Illuminate\Http\Request $request
* @return mixed
*/
public function __invoke(Request $request)

View File

@ -24,10 +24,9 @@ class NewPasswordController extends Controller
/**
* Handle an incoming new password request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*
* @throws \Illuminate\Validation\ValidationException
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
{

View File

@ -21,10 +21,9 @@ class PasswordResetLinkController extends Controller
/**
* Handle an incoming password reset link request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*
* @throws \Illuminate\Validation\ValidationException
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
{

View File

@ -25,10 +25,9 @@ class RegisteredUserController extends Controller
/**
* Handle an incoming registration request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*
* @throws \Illuminate\Validation\ValidationException
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
{

View File

@ -12,7 +12,6 @@ class VerifyEmailController extends Controller
/**
* Mark the authenticated user's email address as verified.
*
* @param \Illuminate\Foundation\Auth\EmailVerificationRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function __invoke(EmailVerificationRequest $request)

View File

@ -7,7 +7,7 @@ use Illuminate\Support\Facades\DB;
class ConfigurationController extends Controller
{
public static function isConfigCompleted()
public static function isConfigured()
{
try {
$connection = DB::connection();

View File

@ -9,5 +9,7 @@ use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
use AuthorizesRequests;
use DispatchesJobs;
use ValidatesRequests;
}

View File

@ -2,8 +2,6 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class InfoController extends Controller
{
/** @var int Lunghezza minima della password */

View File

@ -0,0 +1,165 @@
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Models\Group;
use Models\Setting;
use Models\Upload;
class InitializationController extends Controller
{
protected static $init;
public static function isInitialized()
{
$values = self::getInitValues();
return $values['has_user'] && $values['has_azienda'] && $values['has_settings'];
}
public static function getInitValues()
{
if (!isset(self::$init)) {
$database = database();
$has_azienda = $database->fetchNum("SELECT `an_anagrafiche`.`idanagrafica`
FROM `an_anagrafiche`
LEFT JOIN `an_tipianagrafiche_anagrafiche` ON `an_anagrafiche`.`idanagrafica`=`an_tipianagrafiche_anagrafiche`.`idanagrafica`
LEFT JOIN `an_tipianagrafiche` ON `an_tipianagrafiche`.`idtipoanagrafica`=`an_tipianagrafiche_anagrafiche`.`idtipoanagrafica`
WHERE `an_tipianagrafiche`.`descrizione` = 'Azienda' AND `an_anagrafiche`.`deleted_at` IS NULL") != 0;
$has_user = $database->fetchNum('SELECT `id` FROM `zz_users`') != 0;
$settings = [
'Regime Fiscale' => true,
'Tipo Cassa Previdenziale' => false,
'Conto predefinito fatture di vendita' => true,
'Conto predefinito fatture di acquisto' => true,
"Percentuale ritenuta d'acconto" => false,
"Causale ritenuta d'acconto" => false,
'Valuta' => true,
];
if (!empty(setting("Percentuale ritenuta d'acconto"))) {
$settings["Causale ritenuta d'acconto"] = true;
}
$has_settings = true;
foreach ($settings as $setting => $required) {
if (empty(setting($setting)) && $required) {
$has_settings = false;
break;
}
}
self::$init = [
'has_user' => $has_user,
'has_azienda' => $has_azienda,
'has_settings' => $has_settings,
'settings' => $settings,
];
}
return self::$init;
}
public function index(Request $request)
{
$database = database();
$values = self::getInitValues();
$settings = [];
foreach ($values['settings'] as $setting => $required) {
if (empty(setting($setting))) {
$settings[] = Setting::pool($setting)->input($required);
}
}
// Form dell'anagrafica Azienda
ob_start();
$module_id = module('Anagrafiche')->id;
$idtipoanagrafica = $database->fetchOne("SELECT idtipoanagrafica AS id FROM an_tipianagrafiche WHERE descrizione='Azienda'")['id'];
$readonly_tipo = true;
$skip_permissions = true;
include base_path('legacy').'/modules/anagrafiche/add.php';
$anagrafica = ob_get_clean();
$form = str_replace('</form>', '', $anagrafica);
$args = [
'has_user' => $values['has_user'],
'has_azienda' => $values['has_azienda'],
'has_settings' => $values['has_settings'],
'settings' => $settings,
'azienda_form' => $form,
];
return view('config.initialization', $args);
}
public function save(Request $request)
{
$database = database();
$values = self::getInitValues();
$has_user = $values['has_user'];
$has_azienda = $values['has_azienda'];
$has_settings = $values['has_settings'];
$settings = $values['settings'];
// Azienda predefinita
if (!$has_azienda) {
$this->saveAnagrafica();
}
// Utente amministratore
if (!$has_user) {
// Creazione utente Amministratore
$gruppo = Group::where('nome', '=', 'Amministratori')->first();
$username = $request->input('admin_username');
$password = $request->input('admin_password');
$email = $request->input('admin_email');
$user = User::build($gruppo, $username, $email, $password);
$id_record = $database->selectOne('an_anagrafiche', ['idanagrafica'])['idanagrafica'];
$user->idanagrafica = isset($id_record) ? $id_record : 0;
$user->save();
}
if (!$has_settings) {
foreach ($settings as $setting => $required) {
$setting = Setting::pool($setting);
$value = $request->input('setting.'.$setting['id']);
if (!empty($value)) {
Setting::pool($setting['nome'])->setValue($value);
}
}
}
return redirect(route('initialization'));
}
protected function saveAnagrafica()
{
$dbo = $database = database();
$this->filter->set('post', 'op', 'add');
$id_module = module('Anagrafiche')['id'];
include base_path('legacy').'/modules/anagrafiche/actions.php';
// Logo stampe
if (!empty($_FILES) && !empty($_FILES['blob']['name'])) {
$file = Upload::build($_FILES['blob'], [
'name' => 'Logo stampe',
'id_module' => $id_module,
'id_record' => $id_record,
]);
Setting::pool('Logo stampe')->setValue($file);
}
}
}

View File

@ -12,7 +12,7 @@ class LegacyController extends Controller
{
public function index($path = 'index.php')
{
$base_path = base_path('legacy/');
$base_path = base_path('legacy');
$file = realpath($base_path.'/'.$path);
if (strpos($file, $base_path) === false) {
throw new NotFoundHttpException();
@ -28,6 +28,13 @@ class LegacyController extends Controller
$output = ob_get_clean();
return new Response($output);
$response = response($output);
// Fix content-type per contenuti non HTML
if (ends_with($path, '.js')) {
$response = $response->header('Content-Type', 'application/javascript');
}
return $response;
}
}

View File

@ -2,12 +2,9 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class Test extends Controller
{
//
public function index(){
public function index()
{
}
}

View File

@ -12,6 +12,5 @@ class EncryptCookies extends Middleware
* @var array
*/
protected $except = [
//
];
}

View File

@ -10,8 +10,6 @@ class EnsureCalendarPeriod
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)

View File

@ -3,6 +3,7 @@
namespace App\Http\Middleware;
use App\Http\Controllers\ConfigurationController;
use App\Http\Controllers\InitializationController;
use Closure;
use Illuminate\Http\Request;
@ -20,9 +21,32 @@ class EnsureConfiguration
return $next($request);
}
// Test della connessione al database
$result = $this->checkConfiguration($route);
if ($result !== null) {
return $result;
}
// Verifiche sullo stato delle migrazioni
$result = $this->checkMigrations($route);
if ($result !== null) {
return $result;
}
// Verifiche sullo stato delle impostazioni obbligatorie
$result = $this->checkInitialization($route);
if ($result !== null) {
return $result;
}
return $next($request);
}
protected function checkConfiguration($route)
{
// Test della connessione al database
$configuration_paths = ['configuration', 'configuration-save', 'configuration-test'];
$configuration_completed = ConfigurationController::isConfigCompleted();
$configuration_completed = ConfigurationController::isConfigured();
if ($configuration_completed) {
// Redirect nel caso in cui la configurazione sia correttamente funzionante
@ -36,10 +60,31 @@ class EnsureConfiguration
}
}
// Verifiche sullo stato delle migrazioni
return null;
}
// Verifiche sullo stato delle impostazioni obbligatorie
protected function checkInitialization($route)
{
$initialization_paths = ['initialization', 'initialization-save'];
$initialization_completed = InitializationController::isInitialized();
return $next($request);
if ($initialization_completed) {
// Redirect nel caso in cui la configurazione sia correttamente funzionante
if (in_array($route->getName(), $initialization_paths)) {
return redirect(route('login'));
}
} else {
// Redirect per configurazione mancante
if (!in_array($route->getName(), $initialization_paths)) {
return redirect(route('initialization'));
}
}
return null;
}
protected function checkMigrations($route)
{
return null;
}
}

View File

@ -23,10 +23,8 @@ class EnsureEnvFile
if (!file_exists($env_file)) {
return response('Missing .env file');
}
}
// Generazione automatica delle key Laravel
if (empty(env('APP_KEY'))) {
// Generazione automatica delle key Laravel
Artisan::call('key:generate');
header('Refresh: 0;');

View File

@ -12,6 +12,5 @@ class PreventRequestsDuringMaintenance extends Middleware
* @var array
*/
protected $except = [
//
];
}

View File

@ -12,9 +12,8 @@ class RedirectIfAuthenticated
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null ...$guards
* @param string|null ...$guards
*
* @return mixed
*/
public function handle(Request $request, Closure $next, ...$guards)

View File

@ -12,6 +12,6 @@ class VerifyCsrfToken extends Middleware
* @var array
*/
protected $except = [
'legacy'
'legacy',
];
}

View File

@ -37,20 +37,18 @@ class LoginRequest extends FormRequest
/**
* Attempt to authenticate the request's credentials.
*
* @return void
*
* @throws \Illuminate\Validation\ValidationException
*
* @return void
*/
public function authenticate()
{
$this->ensureIsNotRateLimited();
if (! Auth::attempt($this->only('username', 'password'), $this->filled('remember'))) {
if (!Auth::attempt($this->only('username', 'password'), $this->filled('remember'))) {
RateLimiter::hit($this->throttleKey());
throw ValidationException::withMessages([
'username' => tr('auth.failed'),
]);
throw ValidationException::withMessages(['username' => tr('auth.failed')]);
}
RateLimiter::clear($this->throttleKey());
@ -59,13 +57,13 @@ class LoginRequest extends FormRequest
/**
* Ensure the login request is not rate limited.
*
* @return void
*
* @throws \Illuminate\Validation\ValidationException
*
* @return void
*/
public function ensureIsNotRateLimited()
{
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
if (!RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
return;
}
@ -73,12 +71,7 @@ class LoginRequest extends FormRequest
$seconds = RateLimiter::availableIn($this->throttleKey());
throw ValidationException::withMessages([
'username' => trans('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
]),
]);
throw ValidationException::withMessages(['username' => trans('auth.throttle', ['seconds' => $seconds, 'minutes' => ceil($seconds / 60)])]);
}
/**

View File

@ -6,6 +6,7 @@ use Common\SimpleModelTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Hash;
use Intervention\Image\ImageManagerStatic;
use Models\Group;
use Models\Log;
@ -136,7 +137,7 @@ class User extends Authenticatable
public function setPasswordAttribute($value)
{
$this->attributes['password'] = \auth()->hashPassword($value);
$this->attributes['password'] = Hash::make($value);
}
public function getPhotoAttribute()

View File

@ -13,7 +13,6 @@ class AppServiceProvider extends ServiceProvider
*/
public function register()
{
//
}
/**
@ -23,6 +22,5 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot()
{
//
}
}

View File

@ -3,7 +3,6 @@
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
@ -24,7 +23,5 @@ class AuthServiceProvider extends ServiceProvider
public function boot()
{
$this->registerPolicies();
//
}
}

View File

@ -27,6 +27,5 @@ class EventServiceProvider extends ServiceProvider
*/
public function boot()
{
//
}
}

View File

@ -17,7 +17,7 @@ class RouteServiceProvider extends ServiceProvider
*
* @var string
*/
public const HOME = '/home';
public const HOME = '/';
/**
* The controller namespace for the application.

View File

@ -44,6 +44,7 @@
"league/csv": "^8.2",
"mpdf/mpdf": "^v8.0.7",
"mpociot/vat-calculator": "^2.3",
"nwidart/laravel-modules": "^8.2",
"owasp/csrf-protector-php": "^1.0",
"phpmailer/phpmailer": "^6.0",
"respect/validation": "^1.1",

View File

@ -12,7 +12,7 @@ return [
|
*/
'name' => env('APP_NAME', 'Laravel'),
'name' => env('APP_NAME', 'OpenSTAManager'),
/*
|--------------------------------------------------------------------------

View File

@ -1,7 +1,6 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
@ -113,5 +112,4 @@ return [
*/
'password_timeout' => 10800,
];

View File

@ -1,7 +1,6 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Broadcaster
@ -29,7 +28,6 @@ return [
*/
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
@ -58,7 +56,5 @@ return [
'null' => [
'driver' => 'null',
],
],
];

View File

@ -3,7 +3,6 @@
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Cache Store
@ -32,7 +31,6 @@ return [
*/
'stores' => [
'apc' => [
'driver' => 'apc',
],
@ -85,7 +83,6 @@ return [
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
'endpoint' => env('DYNAMODB_ENDPOINT'),
],
],
/*
@ -100,5 +97,4 @@ return [
*/
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'),
];

View File

@ -1,7 +1,6 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
@ -30,5 +29,4 @@ return [
'max_age' => 0,
'supports_credentials' => false,
];

View File

@ -3,7 +3,6 @@
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Database Connection Name
@ -80,7 +79,6 @@ return [
*/
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
@ -103,7 +101,5 @@ return [
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_CACHE_DB', '1'),
],
],
];

View File

@ -1,7 +1,6 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Debugbar Settings
@ -33,13 +32,13 @@ return [
|
*/
'storage' => [
'enabled' => true,
'driver' => 'file', // redis, file, pdo, socket, custom
'path' => storage_path('debugbar'), // For file driver
'enabled' => true,
'driver' => 'file', // redis, file, pdo, socket, custom
'path' => storage_path('debugbar'), // For file driver
'connection' => null, // Leave null for default connection (Redis/PDO)
'provider' => '', // Instance of StorageInterface for custom driver
'hostname' => '127.0.0.1', // Hostname to use with the "socket" driver
'port' => 2304, // Port to use with the "socket" driver
'provider' => '', // Instance of StorageInterface for custom driver
'hostname' => '127.0.0.1', // Hostname to use with the "socket" driver
'port' => 2304, // Port to use with the "socket" driver
],
/*
@ -104,29 +103,29 @@ return [
*/
'collectors' => [
'phpinfo' => true, // Php version
'messages' => true, // Messages
'time' => true, // Time Datalogger
'memory' => true, // Memory usage
'exceptions' => true, // Exception displayer
'log' => true, // Logs from Monolog (merged in messages if enabled)
'db' => true, // Show database (PDO) queries and bindings
'views' => true, // Views with their data
'route' => true, // Current route information
'auth' => false, // Display Laravel authentication status
'gate' => true, // Display Laravel Gate checks
'session' => true, // Display session data
'phpinfo' => true, // Php version
'messages' => true, // Messages
'time' => true, // Time Datalogger
'memory' => true, // Memory usage
'exceptions' => true, // Exception displayer
'log' => true, // Logs from Monolog (merged in messages if enabled)
'db' => true, // Show database (PDO) queries and bindings
'views' => true, // Views with their data
'route' => true, // Current route information
'auth' => false, // Display Laravel authentication status
'gate' => true, // Display Laravel Gate checks
'session' => true, // Display session data
'symfony_request' => true, // Only one can be enabled..
'mail' => true, // Catch mail messages
'laravel' => false, // Laravel version and environment
'events' => false, // All events fired
'mail' => true, // Catch mail messages
'laravel' => false, // Laravel version and environment
'events' => false, // All events fired
'default_request' => false, // Regular or special Symfony request logger
'logs' => false, // Add the latest log messages
'files' => false, // Show the included files
'config' => false, // Display config settings
'cache' => false, // Display cache events
'models' => true, // Display models
'livewire' => true, // Display Livewire (when available)
'logs' => false, // Add the latest log messages
'files' => false, // Show the included files
'config' => false, // Display config settings
'cache' => false, // Display cache events
'models' => true, // Display models
'livewire' => true, // Display Livewire (when available)
],
/*
@ -143,16 +142,16 @@ return [
'show_name' => true, // Also show the users name/email in the debugbar
],
'db' => [
'with_params' => true, // Render SQL with the parameters substituted
'backtrace' => true, // Use a backtrace to find the origin of the query in your files.
'with_params' => true, // Render SQL with the parameters substituted
'backtrace' => true, // Use a backtrace to find the origin of the query in your files.
'backtrace_exclude_paths' => [], // Paths to exclude from backtrace. (in addition to defaults)
'timeline' => false, // Add the queries to the timeline
'timeline' => false, // Add the queries to the timeline
'explain' => [ // Show EXPLAIN output on queries
'enabled' => false,
'types' => ['SELECT'], // Deprecated setting, is always only SELECT
],
'hints' => false, // Show hints for common mistakes
'show_copy' => false, // Show copy button next to the query
'hints' => false, // Show hints for common mistakes
'show_copy' => false, // Show copy button next to the query
],
'mail' => [
'full_log' => false,

View File

@ -1,7 +1,6 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Filesystem Disk
@ -29,7 +28,6 @@ return [
*/
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
@ -51,7 +49,6 @@ return [
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
],
],
/*
@ -68,5 +65,4 @@ return [
'links' => [
public_path('storage') => storage_path('app/public'),
],
];

View File

@ -1,7 +1,6 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Hash Driver
@ -48,5 +47,4 @@ return [
'threads' => 2,
'time' => 2,
],
];

View File

@ -1,7 +1,6 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Image Driver
@ -15,6 +14,5 @@ return [
|
*/
'driver' => 'gd'
'driver' => 'gd',
];

View File

@ -5,7 +5,6 @@ use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler;
return [
/*
|--------------------------------------------------------------------------
| Default Log Channel
@ -100,5 +99,4 @@ return [
'path' => storage_path('logs/laravel.log'),
],
],
];

View File

@ -1,7 +1,6 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Mailer
@ -106,5 +105,4 @@ return [
resource_path('views/vendor/mail'),
],
],
];

View File

@ -3,7 +3,6 @@
use Nwidart\Modules\Activators\FileActivator;
return [
/*
|--------------------------------------------------------------------------
| Module Namespace
@ -26,7 +25,7 @@ return [
'stubs' => [
'enabled' => false,
'path' => base_path() . '/vendor/nwidart/laravel-modules/src/Commands/stubs',
'path' => base_path().'/vendor/nwidart/laravel-modules/src/Commands/stubs',
'files' => [
'routes/web' => 'Routes/web.php',
'routes/api' => 'Routes/api.php',
@ -241,7 +240,7 @@ return [
*/
'register' => [
'translations' => true,
/**
/*
* load files on boot or register method
*
* Note: boot not compatible with asgardcms

View File

@ -1,7 +1,6 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Queue Connection Name
@ -29,7 +28,6 @@ return [
*/
'connections' => [
'sync' => [
'driver' => 'sync',
],
@ -66,7 +64,6 @@ return [
'retry_after' => 90,
'block_for' => null,
],
],
/*
@ -85,5 +82,4 @@ return [
'database' => env('DB_CONNECTION', 'mysql'),
'table' => 'failed_jobs',
],
];

View File

@ -1,7 +1,6 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Third Party Services
@ -29,5 +28,4 @@ return [
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
];

View File

@ -3,7 +3,6 @@
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Session Driver
@ -197,5 +196,4 @@ return [
*/
'same_site' => 'lax',
];

View File

@ -1,7 +1,6 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Console Commands
@ -29,7 +28,6 @@ return [
*/
'alias' => [
//
],
/*
@ -46,5 +44,4 @@ return [
'dont_alias' => [
'App\Nova',
],
];

View File

@ -1,7 +1,6 @@
<?php
return [
/*
* Set trusted proxy IP addresses.
*
@ -46,5 +45,4 @@ return [
* @link https://symfony.com/doc/current/deployment/proxies.html
*/
'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_ALL,
];

View File

@ -7,7 +7,6 @@
*/
return [
/*
|--------------------------------------------------------------------------
| VAT rules

View File

@ -1,7 +1,6 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| View Storage Paths
@ -32,5 +31,4 @@ return [
'VIEW_COMPILED_PATH',
realpath(storage_path('framework/views'))
),
];

View File

@ -7,7 +7,7 @@
</x-slot>
<div class="mb-4 text-sm text-gray-600">
{{ __('This is a secure area of the application. Please confirm your password before continuing.') }}
{{ tr('This is a secure area of the application. Please confirm your password before continuing.') }}
</div>
<!-- Validation Errors -->
@ -18,7 +18,7 @@
<!-- Password -->
<div>
<x-label for="password" :value="__('Password')" />
<x-label for="password" :value="tr('Password')" />
<x-input id="password" class="block mt-1 w-full"
type="password"
@ -28,7 +28,7 @@
<div class="flex justify-end mt-4">
<x-button>
{{ __('Confirm') }}
{{ tr('Confirm') }}
</x-button>
</div>
</form>

View File

@ -7,7 +7,7 @@
</x-slot>
<div class="mb-4 text-sm text-gray-600">
{{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
{{ tr('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
</div>
<!-- Session Status -->
@ -21,14 +21,14 @@
<!-- Email Address -->
<div>
<x-label for="email" :value="__('Email')" />
<x-label for="email" :value="tr('Email')" />
<x-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
</div>
<div class="flex items-center justify-end mt-4">
<x-button>
{{ __('Email Password Reset Link') }}
{{ tr('Email Password Reset Link') }}
</x-button>
</div>
</form>

View File

@ -1,7 +1,7 @@
@extends('layouts.base')
@section('body_class', 'hold-transition login-page')
@section('title', __("Login"))
@section('body_class', 'bg-light')
@section('title', tr("Login"))
@section('body')
<div class="login-box">
@ -16,23 +16,23 @@
<div class="box">
<div class="box-body login-box-body">
<h4 class="login-box-msg">{{ __('Accedi') }}</h4>
<h4 class="login-box-msg">{{ tr('Accedi') }}</h4>
{[ "type": "text", "name": "username", "autocomplete": "username", "placeholder": "{{ __('Username') }}", "value": "{{ old('username') }}", "icon-before": "<i class=\"fa fa-user\"></i>", "required": 1 ]}
{[ "type": "text", "name": "username", "autocomplete": "username", "placeholder": "{{ tr('Username') }}", "value": "{{ old('username') }}", "icon-before": "<i class=\"fa fa-user\"></i>", "required": 1 ]}
<div class="mb-3" style="margin-bottom: 1rem !important;"></div>
{[ "type": "password", "name": "password", "autocomplete": "current-password", "placeholder": "{{ __('Password') }}", "icon-before": "<i class=\"fa fa-lock\"></i>" ]}
{[ "type": "password", "name": "password", "autocomplete": "current-password", "placeholder": "{{ tr('Password') }}", "icon-before": "<i class=\"fa fa-lock\"></i>" ]}
<div class="mb-3" style="margin-bottom: 1rem !important;"></div>
@if (Route::has('password.request'))
<div class="text-right">
<a href="{{ route('password.request') }}">{{ __('Dimenticata la password?') }}</a>
<a href="{{ route('password.request') }}">{{ tr('Dimenticata la password?') }}</a>
</div>
@endif
</div>
<div class="box-footer">
<button type="submit" class="btn btn-warning btn-block">{{ __('Accedi') }}</button>
<button type="submit" class="btn btn-warning btn-block">{{ tr('Accedi') }}</button>
</div>
</div>
</form>
@ -43,7 +43,7 @@
@if (Update::isBeta())
<div class="clearfix">&nbsp;</div>
<div class="alert alert-warning alert-dismissable col-md-6 col-md-push-3 text-center fade in">
<i class="fa fa-warning"></i> <b>{{ __('Attenzione!') }}</b> {{ __('Stai utilizzando una versione <b>non stabile</b> di OSM.') }}
<i class="fa fa-warning"></i> <b>{{ tr('Attenzione!') }}</b> {!! tr('Stai utilizzando una versione <b>non stabile</b> di OSM.') !!}
<button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
</div>
@ -52,12 +52,12 @@
@if (false)
<div class="box box-outline box-danger box-center" id="brute">
<div class="box-header text-center">
<h3 class="box-title">{{ __('Attenzione') }}</h3>
<h3 class="box-title">{{ tr('Attenzione') }}</h3>
</div>
<div class="box-body text-center">
<p>{{ __('Sono stati effettuati troppi tentativi di accesso consecutivi!') }}</p>
<p>{{ __('Tempo rimanente (in secondi)') }}: <span id="brute-timeout">{{ brute.timeout + 1 }}</span></p>
<p>{{ tr('Sono stati effettuati troppi tentativi di accesso consecutivi!') }}</p>
<p>{{ tr('Tempo rimanente (in secondi)') }}: <span id="brute-timeout">{{ brute.timeout + 1 }}</span></p>
</div>
</div>
<script>

View File

@ -17,21 +17,21 @@
<!-- Email Address -->
<div>
<x-label for="email" :value="__('Email')" />
<x-label for="email" :value="tr('Email')" />
<x-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email', $request->email)" required autofocus />
</div>
<!-- Password -->
<div class="mt-4">
<x-label for="password" :value="__('Password')" />
<x-label for="password" :value="tr('Password')" />
<x-input id="password" class="block mt-1 w-full" type="password" name="password" required />
</div>
<!-- Confirm Password -->
<div class="mt-4">
<x-label for="password_confirmation" :value="__('Confirm Password')" />
<x-label for="password_confirmation" :value="tr('Confirm Password')" />
<x-input id="password_confirmation" class="block mt-1 w-full"
type="password"
@ -40,7 +40,7 @@
<div class="flex items-center justify-end mt-4">
<x-button>
{{ __('Reset Password') }}
{{ tr('Reset Password') }}
</x-button>
</div>
</form>

View File

@ -7,12 +7,12 @@
</x-slot>
<div class="mb-4 text-sm text-gray-600">
{{ __('Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }}
{{ tr('Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }}
</div>
@if (session('status') == 'verification-link-sent')
<div class="mb-4 font-medium text-sm text-green-600">
{{ __('A new verification link has been sent to the email address you provided during registration.') }}
{{ tr('A new verification link has been sent to the email address you provided during registration.') }}
</div>
@endif
@ -22,7 +22,7 @@
<div>
<x-button>
{{ __('Resend Verification Email') }}
{{ tr('Resend Verification Email') }}
</x-button>
</div>
</form>
@ -31,7 +31,7 @@
@csrf
<button type="submit" class="underline text-sm text-gray-600 hover:text-gray-900">
{{ __('Logout') }}
{{ tr('Logout') }}
</button>
</form>
</div>

View File

@ -4,9 +4,9 @@
@section('title', tr("Configurazione"))
@section('body')
<div class="container bg-light pb-5">
<form action="" method="post" id="config-form">
<input type="hidden" name="lang" value="{{ app()->getLocale() }}">
<div class="container pb-5">
<form action="{{ route('configuration-save') }}" method="post" id="config-form">
@csrf
<div class="py-5 text-center">
<img class="d-block mx-auto mb-4" src="{{ base_url() }}/assets/img/full_logo.png" alt="{{ tr('Logo OpenSTAManager') }}">
@ -19,7 +19,7 @@
<div class="row">
<div class="col-md-4 col-md-push-8 mb-4">
<h4 class="d-flex justify-content-between align-items-center mb-3 text-muted">{{ tr('Lingua') }}</h4>
<select class="form-control hidden" id="language" required="1">
<select class="form-control hidden" id="language" name="language" required="1">
@foreach($languages as $code => $language)
<option data-country="{{ $language['flag'] }}" value="{{ $code }}">{{ $language['title'] }}</option>
@endforeach
@ -136,6 +136,17 @@
$(document).ready(function() {
init();
$.ajax({
url: flag_link.replace("|flag|", "it"),
success: function(){
initLanguage(true);
},
error: function(){
initLanguage(false);
},
timeout: 500
});
$("#install").on("click", function() {
if ($(this).closest("form").parsley().validate()) {
let restore = buttonLoading("#install");
@ -155,7 +166,7 @@
data: {
test: 1,
},
type: "post",
type: "get",
success: function (data) {
data = parseFloat(data.trim());
@ -176,17 +187,6 @@
});
}
});
$.ajax({
url: flag_link.replace("|flag|", "it"),
success: function(){
initLanguage(true);
},
error: function(){
initLanguage(false);
},
timeout: 500
});
});
function languageFlag(item) {
@ -210,10 +210,11 @@
}
function initLanguage() {
$("#language").removeClass("hidden");
let language = $("#language");
language.removeClass("hidden");
$("#language-info").addClass("hidden");
$("#language").select2({
language.select2({
theme: "bootstrap",
templateResult: languageFlag,
templateSelection:languageFlag,
@ -221,18 +222,18 @@
// Preselezione lingua
if (globals.full_locale) {
$("#language").selectSet(globals.full_locale);
language.selectSet(globals.full_locale);
}
$("#language").on("change", function(){
language.on("change", function(){
if ($(this).val()) {
var location = window.location;
var url = location.protocol + "//" + location.host + "" + location.pathname;
let location = window.location;
let url = location.protocol + "//" + location.host + "" + location.pathname;
var parameters = getUrlVars();
let parameters = getUrlVars();
parameters.lang = $(this).val();
redirect(url, parameters);
redirect_legacy(url, parameters);
}
});
}

View File

@ -0,0 +1,133 @@
@extends('layouts.base')
@section('body_class', 'bg-light')
@section('title', tr("Inizializzazione"))
@section('body')
<div class="container pb-5">
<div class="py-5 text-center">
<img class="d-block mx-auto mb-4" src="{{ base_url() }}/assets/img/full_logo.png" alt="{{ tr('Logo OpenSTAManager') }}">
<h2>{!! tr('Inizializzazione di _NAME_!', ['_NAME_' => '<strong>'.tr('OpenSTAManager').'</strong>']) !!}</h2>
<p class="lead">{{ tr("Completa la configurazione del gestionale inserendo le ultime informazioni di base") }}. </p>
</div>
<!-- Visualizzazione dell'interfaccia di impostazione iniziale, nel caso il file di configurazione sia mancante oppure i paramentri non siano sufficienti -->
<form action="" method="post" id="init-form" enctype="multipart/form-data">
@csrf
<input type="hidden" name="action" value="init">
@if(!$has_user)
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">{{ tr('Amministrazione') }}</h3>
</div>
<div class="box-body">
<div class="row">
<div class="col-md-6">
{[ "type": "text", "label": "{{ tr('Username') }}", "name": "admin_username", "placeholder": "{{ tr("Digita l'username dell'amministratore") }}", "required": 1 ]}
</div>
<div class="col-md-6">
{[ "type": "password", "label": "{{ tr('Password') }}", "id": "password", "name": "admin_password", "placeholder": "{{ tr("Digita la password dell'amministratore") }}", "required": 1, "icon-after": "<i onclick=\"togglePassword(this)\" title=\"{{ tr('Visualizza password') }}\" class=\"fa fa-eye clickable\"></i>" ]}
</div>
<div class="col-md-6">
{[ "type": "email", "label": "{{ tr('Email') }}", "name": "admin_email", "placeholder": "{{ tr("Digita l'indirizzo email dell'amministratore") }}" ]}
</div>
</div>
</div>
</div>
<script>
function togglePassword(btn) {
let button = $(btn);
if (button.hasClass("fa-eye")) {
$("#password").attr("type", "text");
button.removeClass("fa-eye").addClass("fa-eye-slash");
button.attr("title", "Nascondi password");
} else {
$("#password").attr("type", "password");
button.removeClass("fa-eye-slash").addClass("fa-eye");
button.attr("title", "Visualizza password");
}
}
</script>
@endif
@if(!$has_azienda)
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">{{ tr('Azienda predefinita') }}</h3>
</div>
<div class="box-body">
{!! azienda_form !!}
<div class="box box-outline box-success collapsed-box">
<div class="box-header with-border">
<h3 class="box-title">{{ tr('Logo stampe') }}</h3>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
<div class="box-body">
<div class="col-md-12">
{[ "type": "file", "placeholder": "{{ tr('File') }}", "name": "blob" ]}
</div>
<p>&nbsp;</p><div class="col-md-12 alert alert-info text-center">{{ tr('Per impostare il logo delle stampe, caricare un file ".jpg". Risoluzione consigliata 302x111 pixel') }}.</div>
</div>
</div>
</div>
</div>
@endif
@if(!$has_settings)
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">{{ tr('Impostazioni di base') }}</h3>
</div>
<div class="box-body row">
@foreach($settings as $setting)
<div class="col-md-6">
{!! $setting !!}
</div>
@endforeach
</div>
</div>
@endif
<!-- PULSANTI -->
<div class="row">
<div class="col-md-4">
<span>*<small><small>{{ tr('Campi obbligatori') }}</small></small></span>
</div>
<div class="col-md-4 text-right">
<button type="submit" id="config" class="btn btn-success btn-block">
<i class="fa fa-cog"></i> {{ tr('Configura') }}
</button>
</div>
</div>
</form>
<script>
$(document).ready(function(){
init();
$("button[type=submit]").not("#config").remove();
});
</script>
</div>
@endsection

View File

@ -9,7 +9,7 @@
@section('error_info', tr('Non siamo riusciti a trovare la pagina che stavi cercando'))
@section('js')
@if(!auth()->check())
@if(\App\Http\Controllers\ConfigurationController::isConfigured() && !auth()->check())
<script>
location.href = "{{ route('login') }}";
</script>

View File

@ -0,0 +1,145 @@
@extends('layouts.app')
@section('title', tr("Informazioni"))
@section('content')
<h3>{{ tr('Informazioni sul software') }}</h3>
<div class="row">
<div class="col-md-12">
<p>{{ tr("Il gestionale OpenSTAManager è un software open-source e web based, sviluppato dall'azienda informatica DevCode di Este per gestire ed archiviare il servizio di assistenza tecnica e la relativa fatturazione") }}. {{ tr("Il nome del progetto deriva dalla parziale traduzione in inglese degli elementi principali che lo compongono: la natura open-source e il suo obiettivo quale Gestore del Servizio Tecnico di Assistenza") }}.</p>
</div>
</div>
<div class="row text-center">
<div class="col-md-4">
<p><b>{{ tr('Sito web') }}:</b> <a href="https://www.openstamanager.com" target="_blank">www.openstamanager.com</a></p>
</div>
<div class="col-md-4">
<p><b>{{ tr('Versione') }}:</b> {{ Update::getVersion() }} <small class="text-muted">({{ Update::getRevision() ?: tr('In sviluppo') }})</small></p>
</div>
<div class="col-md-4">
<p><b>{{ tr('Licenza') }}:</b> <a href="http://www.gnu.org/licenses/gpl-3.0.txt" target="_blank" title="{{ tr('Vai al sito per leggere la licenza') }}">GPLv3</a></p>
</div>
</div>
<hr>
<div class="row">
<div class="col-md-6">
<div class="box box-outline box-primary">
<div class="box-header">
<h3 class="box-title text-uppercase"><i class="fa fa-globe"></i> {{ tr('Perchè software libero') }}</h3>
</div>
<div class="box-body">
<p>{{ tr("Il progetto è software libero perchè permette a tutti di conoscere come funziona avendo il codice sorgente del programma e fornisce così la possibilità di studiare come funziona, modificarlo, adattarlo alle proprie esigenze e, in ambito commerciale, non obbliga l'utilizzatore ad essere legato allo stesso fornitore di assistenza") }}.</p>
<p>{{ tr("E' altrettanto importante sapere come funziona per conoscere come vengono trattati i VOSTRI dati, proteggendo così la vostra <b>privacy</b>") }}.</p>
<p>{{ tr('OpenSTAManager è inoltre stato progettato utilizzando altro software libero, tra cui principalmente') }}:</p>
<ul>
<li><a href="http://www.php.net" target="_blank"><i class="fa fa-circle-o-notch"></i> PHP</a></li>
<li><a href="http://www.mysql.com" target="_blank"><i class="fa fa-circle-o-notch"></i> MySQL</a></li>
<li><a href="http://jquery.com" target="_blank"><i class="fa fa-circle-o-notch"></i> JQuery</a></li>
<li><a href="http://getbootstrap.com" target="_blank"><i class="fa fa-circle-o-notch"></i> Bootstrap</a></li>
<li><a href="http://fortawesome.github.io/Font-Awesome" target="_blank"><i class="fa fa-circle-o-notch"></i> FontAwesome</a></li>
</ul>
</div>
</div>
</div>
<div class="col-md-6">
<div class="box box-outline box-danger">
<div class="box-header">
<h3 class="box-title text-uppercase"><i class="fa fa-group"></i> {{ tr('Community') }}</h3>
</div>
<div class="box-body">
<p>{{ tr('La community è un componente importante in un progetto open-source perchè mette in contatto le persone tra di loro, utenti e programmatori') }}.</p>
<p>{{ tr('Con OpenSTAManager siamo presenti su') }}:</p>
<div class="well">
<div class="row">
<div class="col-xs-3 text-center">
<a href="https://github.com/devcode-it/openstamanager" target="_blank">
<i class="fa fa-2x fa-github"></i><br>
{{ tr('GitHub') }}
</a>
</div>
<div class="col-xs-3 text-center">
<a href="http://www.openstamanager.com/forum/" target="_blank">
<i class="fa fa-2x fa-edit"></i><br>
{{ tr('Forum') }}
</a>
</div>
<div class="col-xs-3 text-center">
<a href="http://eepurl.com/8MFgH" target="_blank">
<i class="fa fa-2x fa-envelope"></i><br>
{{ tr('Newsletter') }}
</a>
</div>
<div class="col-xs-3 text-center">
<a href="https://www.facebook.com/openstamanager" target="_blank">
<i class="fa fa-2x fa-facebook-square"></i><br>
{{ tr('Facebook') }}
</a>
</div>
</div>
</div>
</div>
</div>
<div class="box box-outline box-default">
<div class="box-header">
<h3 class="box-title text-uppercase"><i class="fa fa-download"></i> {{ tr('Aggiornamenti e nuove versioni') }}</h3>
</div>
<div class="box-body">
<p>{{ tr("Tutti gli aggiornamenti e le nuove versioni sono disponibili all'indirizzo") }}:</p>
<a href="http://www.openstamanager.com/downloads/" target="_blank"><i class="fa fa-external-link"></i> www.openstamanager.com/downloads/</a>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="box box-outline box-warning">
<div class="box-header">
<h3 class="box-title text-uppercase"><i class="fa fa-money"></i> {{ tr('Supporta il progetto') }}</h3>
</div>
<div class="box-body">
<p>{{ tr('OpenSTAManager è software libero ed è nato e cresciuto con il lavoro volontario di alcuni programmatori') }}.</p>
<p>{{ tr('La filosofia del software libero fa sì che il progetto sia <b>accessibile a tutti</b> e nel nostro caso specifico lo è, anche dal punto di vista della gratuità') }}.</p>
<p>{{ tr('Offriamo supporto a pagamento professionale a chi fosse interessato, ma a chi non interessa il supporto a pagamento e sta comunque utilizzando il software chiediamo una donazione per il lavoro svolto finora e per la possibilità di continuare questo progetto con lo stesso spirito con cui è nato') }}. {{ tr('Le donazioni non ci rendono ricchi, ma sono un <b>grande simbolo di apprezzamento</b>') }}.</p>
<a href="http://sourceforge.net/donate/index.php?group_id=236538" class="btn btn-lg btn-success btn-block" target="_blank"><i class="fa fa-usd"></i> {{ tr('Supporta questo progetto') }}</a>
</div>
</div>
</div>
<div class="col-md-6">
<div class="box box-outline box-success">
<div class="box-header">
<h3 class="box-title text-uppercase"><i class="fa fa-euro"></i> {{ tr('Servizi a pagamento') }}</h3>
</div>
<div class="box-body">
<p>{{ tr('Per le aziende che hanno necessità di essere seguite da <b>supporto professionale</b> è disponibile un servizio di assistenza e supporto a pagamento') }}.</p>
<p>{{ tr("E' disponibile anche un <b>servizio cloud</b> su cui poter installare OpenSTAManager, in modo da non doverti più preoccupare di backup e gestione dei dati") }}.</p>
<p><a href="http://www.openstamanager.com/per-le-aziende/" class="btn btn-lg btn-info btn-block" target="_blank"><i class="fa fa-thumbs-up"></i> {{ tr('Ottieni supporto professionale') }}</a></p>
</div>
</div>
</div>
</div>
@endsection(

View File

@ -45,7 +45,7 @@
decimals: "{{ formatter()->getNumberSeparators()['decimals'] }}",
thousands: "{{ formatter()->getNumberSeparators()['thousands'] }}",
locale: '{{ app()->getLocale() }}',
locale: '{{ substr(app()->getLocale(), 0, strpos(app()->getLocale(), "_")) }}',
full_locale: '{{ app()->getLocale() }}',
translations: {

View File

@ -1,132 +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>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
<!-- Styles -->
<style>
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}a{background-color:transparent}[hidden]{display:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}a{color:inherit;text-decoration:inherit}svg,video{display:block;vertical-align:middle}video{max-width:100%;height:auto}.bg-white{--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity))}.bg-gray-100{--bg-opacity:1;background-color:#f7fafc;background-color:rgba(247,250,252,var(--bg-opacity))}.border-gray-200{--border-opacity:1;border-color:#edf2f7;border-color:rgba(237,242,247,var(--border-opacity))}.border-t{border-top-width:1px}.flex{display:flex}.grid{display:grid}.hidden{display:none}.items-center{align-items:center}.justify-center{justify-content:center}.font-semibold{font-weight:600}.h-5{height:1.25rem}.h-8{height:2rem}.h-16{height:4rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.leading-7{line-height:1.75rem}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mt-4{margin-top:1rem}.ml-4{margin-left:1rem}.mt-8{margin-top:2rem}.ml-12{margin-left:3rem}.-mt-px{margin-top:-1px}.max-w-6xl{max-width:72rem}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.p-6{padding:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-8{padding-top:2rem}.fixed{position:fixed}.relative{position:relative}.top-0{top:0}.right-0{right:0}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.text-center{text-align:center}.text-gray-200{--text-opacity:1;color:#edf2f7;color:rgba(237,242,247,var(--text-opacity))}.text-gray-300{--text-opacity:1;color:#e2e8f0;color:rgba(226,232,240,var(--text-opacity))}.text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.text-gray-500{--text-opacity:1;color:#a0aec0;color:rgba(160,174,192,var(--text-opacity))}.text-gray-600{--text-opacity:1;color:#718096;color:rgba(113,128,150,var(--text-opacity))}.text-gray-700{--text-opacity:1;color:#4a5568;color:rgba(74,85,104,var(--text-opacity))}.text-gray-900{--text-opacity:1;color:#1a202c;color:rgba(26,32,44,var(--text-opacity))}.underline{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w-5{width:1.25rem}.w-8{width:2rem}.w-auto{width:auto}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:items-center{align-items:center}.sm\:justify-start{justify-content:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:h-20{height:5rem}.sm\:ml-0{margin-left:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}@media (min-width:768px){.md\:border-t-0{border-top-width:0}.md\:border-l{border-left-width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (prefers-color-scheme:dark){.dark\:bg-gray-800{--bg-opacity:1;background-color:#2d3748;background-color:rgba(45,55,72,var(--bg-opacity))}.dark\:bg-gray-900{--bg-opacity:1;background-color:#1a202c;background-color:rgba(26,32,44,var(--bg-opacity))}.dark\:border-gray-700{--border-opacity:1;border-color:#4a5568;border-color:rgba(74,85,104,var(--border-opacity))}.dark\:text-white{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.dark\:text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}}
</style>
<style>
body {
font-family: 'Nunito';
}
</style>
</head>
<body class="antialiased">
<div class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0">
@if (Route::has('login'))
<div class="hidden fixed top-0 right-0 px-6 py-4 sm:block">
@auth
<a href="{{ url('/home') }}" class="text-sm text-gray-700 underline">Home</a>
@else
<a href="{{ route('login') }}" class="text-sm text-gray-700 underline">Login</a>
@if (Route::has('register'))
<a href="{{ route('register') }}" class="ml-4 text-sm text-gray-700 underline">Register</a>
@endif
@endauth
</div>
@endif
<div class="max-w-6xl mx-auto sm:px-6 lg:px-8">
<div class="flex justify-center pt-8 sm:justify-start sm:pt-0">
<svg viewBox="0 0 651 192" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-16 w-auto text-gray-700 sm:h-20">
<g clip-path="url(#clip0)" fill="#EF3B2D">
<path d="M248.032 44.676h-16.466v100.23h47.394v-14.748h-30.928V44.676zM337.091 87.202c-2.101-3.341-5.083-5.965-8.949-7.875-3.865-1.909-7.756-2.864-11.669-2.864-5.062 0-9.69.931-13.89 2.792-4.201 1.861-7.804 4.417-10.811 7.661-3.007 3.246-5.347 6.993-7.016 11.239-1.672 4.249-2.506 8.713-2.506 13.389 0 4.774.834 9.26 2.506 13.459 1.669 4.202 4.009 7.925 7.016 11.169 3.007 3.246 6.609 5.799 10.811 7.66 4.199 1.861 8.828 2.792 13.89 2.792 3.913 0 7.804-.955 11.669-2.863 3.866-1.908 6.849-4.533 8.949-7.875v9.021h15.607V78.182h-15.607v9.02zm-1.431 32.503c-.955 2.578-2.291 4.821-4.009 6.73-1.719 1.91-3.795 3.437-6.229 4.582-2.435 1.146-5.133 1.718-8.091 1.718-2.96 0-5.633-.572-8.019-1.718-2.387-1.146-4.438-2.672-6.156-4.582-1.719-1.909-3.032-4.152-3.938-6.73-.909-2.577-1.36-5.298-1.36-8.161 0-2.864.451-5.585 1.36-8.162.905-2.577 2.219-4.819 3.938-6.729 1.718-1.908 3.77-3.437 6.156-4.582 2.386-1.146 5.059-1.718 8.019-1.718 2.958 0 5.656.572 8.091 1.718 2.434 1.146 4.51 2.674 6.229 4.582 1.718 1.91 3.054 4.152 4.009 6.729.953 2.577 1.432 5.298 1.432 8.162-.001 2.863-.479 5.584-1.432 8.161zM463.954 87.202c-2.101-3.341-5.083-5.965-8.949-7.875-3.865-1.909-7.756-2.864-11.669-2.864-5.062 0-9.69.931-13.89 2.792-4.201 1.861-7.804 4.417-10.811 7.661-3.007 3.246-5.347 6.993-7.016 11.239-1.672 4.249-2.506 8.713-2.506 13.389 0 4.774.834 9.26 2.506 13.459 1.669 4.202 4.009 7.925 7.016 11.169 3.007 3.246 6.609 5.799 10.811 7.66 4.199 1.861 8.828 2.792 13.89 2.792 3.913 0 7.804-.955 11.669-2.863 3.866-1.908 6.849-4.533 8.949-7.875v9.021h15.607V78.182h-15.607v9.02zm-1.432 32.503c-.955 2.578-2.291 4.821-4.009 6.73-1.719 1.91-3.795 3.437-6.229 4.582-2.435 1.146-5.133 1.718-8.091 1.718-2.96 0-5.633-.572-8.019-1.718-2.387-1.146-4.438-2.672-6.156-4.582-1.719-1.909-3.032-4.152-3.938-6.73-.909-2.577-1.36-5.298-1.36-8.161 0-2.864.451-5.585 1.36-8.162.905-2.577 2.219-4.819 3.938-6.729 1.718-1.908 3.77-3.437 6.156-4.582 2.386-1.146 5.059-1.718 8.019-1.718 2.958 0 5.656.572 8.091 1.718 2.434 1.146 4.51 2.674 6.229 4.582 1.718 1.91 3.054 4.152 4.009 6.729.953 2.577 1.432 5.298 1.432 8.162 0 2.863-.479 5.584-1.432 8.161zM650.772 44.676h-15.606v100.23h15.606V44.676zM365.013 144.906h15.607V93.538h26.776V78.182h-42.383v66.724zM542.133 78.182l-19.616 51.096-19.616-51.096h-15.808l25.617 66.724h19.614l25.617-66.724h-15.808zM591.98 76.466c-19.112 0-34.239 15.706-34.239 35.079 0 21.416 14.641 35.079 36.239 35.079 12.088 0 19.806-4.622 29.234-14.688l-10.544-8.158c-.006.008-7.958 10.449-19.832 10.449-13.802 0-19.612-11.127-19.612-16.884h51.777c2.72-22.043-11.772-40.877-33.023-40.877zm-18.713 29.28c.12-1.284 1.917-16.884 18.589-16.884 16.671 0 18.697 15.598 18.813 16.884h-37.402zM184.068 43.892c-.024-.088-.073-.165-.104-.25-.058-.157-.108-.316-.191-.46-.056-.097-.137-.176-.203-.265-.087-.117-.161-.242-.265-.345-.085-.086-.194-.148-.29-.223-.109-.085-.206-.182-.327-.252l-.002-.001-.002-.002-35.648-20.524a2.971 2.971 0 00-2.964 0l-35.647 20.522-.002.002-.002.001c-.121.07-.219.167-.327.252-.096.075-.205.138-.29.223-.103.103-.178.228-.265.345-.066.089-.147.169-.203.265-.083.144-.133.304-.191.46-.031.085-.08.162-.104.25-.067.249-.103.51-.103.776v38.979l-29.706 17.103V24.493a3 3 0 00-.103-.776c-.024-.088-.073-.165-.104-.25-.058-.157-.108-.316-.191-.46-.056-.097-.137-.176-.203-.265-.087-.117-.161-.242-.265-.345-.085-.086-.194-.148-.29-.223-.109-.085-.206-.182-.327-.252l-.002-.001-.002-.002L40.098 1.396a2.971 2.971 0 00-2.964 0L1.487 21.919l-.002.002-.002.001c-.121.07-.219.167-.327.252-.096.075-.205.138-.29.223-.103.103-.178.228-.265.345-.066.089-.147.169-.203.265-.083.144-.133.304-.191.46-.031.085-.08.162-.104.25-.067.249-.103.51-.103.776v122.09c0 1.063.568 2.044 1.489 2.575l71.293 41.045c.156.089.324.143.49.202.078.028.15.074.23.095a2.98 2.98 0 001.524 0c.069-.018.132-.059.2-.083.176-.061.354-.119.519-.214l71.293-41.045a2.971 2.971 0 001.489-2.575v-38.979l34.158-19.666a2.971 2.971 0 001.489-2.575V44.666a3.075 3.075 0 00-.106-.774zM74.255 143.167l-29.648-16.779 31.136-17.926.001-.001 34.164-19.669 29.674 17.084-21.772 12.428-43.555 24.863zm68.329-76.259v33.841l-12.475-7.182-17.231-9.92V49.806l12.475 7.182 17.231 9.92zm2.97-39.335l29.693 17.095-29.693 17.095-29.693-17.095 29.693-17.095zM54.06 114.089l-12.475 7.182V46.733l17.231-9.92 12.475-7.182v74.537l-17.231 9.921zM38.614 7.398l29.693 17.095-29.693 17.095L8.921 24.493 38.614 7.398zM5.938 29.632l12.475 7.182 17.231 9.92v79.676l.001.005-.001.006c0 .114.032.221.045.333.017.146.021.294.059.434l.002.007c.032.117.094.222.14.334.051.124.088.255.156.371a.036.036 0 00.004.009c.061.105.149.191.222.288.081.105.149.22.244.314l.008.01c.084.083.19.142.284.215.106.083.202.178.32.247l.013.005.011.008 34.139 19.321v34.175L5.939 144.867V29.632h-.001zm136.646 115.235l-65.352 37.625V148.31l48.399-27.628 16.953-9.677v33.862zm35.646-61.22l-29.706 17.102V66.908l17.231-9.92 12.475-7.182v33.841z"/>
</g>
</svg>
</div>
<div class="mt-8 bg-white dark:bg-gray-800 overflow-hidden shadow sm:rounded-lg">
<div class="grid grid-cols-1 md:grid-cols-2">
<div class="p-6">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold"><a href="https://laravel.com/docs" class="underline text-gray-900 dark:text-white">Documentation</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel has wonderful, thorough documentation covering every aspect of the framework. Whether you are new to the framework or have previous experience with Laravel, we recommend reading all of the documentation from beginning to end.
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700 md:border-t-0 md:border-l">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"></path><path d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold"><a href="https://laracasts.com" class="underline text-gray-900 dark:text-white">Laracasts</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laracasts offers thousands of video tutorials on Laravel, PHP, and JavaScript development. Check them out, see for yourself, and massively level up your development skills in the process.
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold"><a href="https://laravel-news.com/" class="underline text-gray-900 dark:text-white">Laravel News</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel News is a community driven portal and newsletter aggregating all of the latest and most important news in the Laravel ecosystem, including new package releases and tutorials.
</div>
</div>
</div>
<div class="p-6 border-t border-gray-200 dark:border-gray-700 md:border-l">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
<div class="ml-4 text-lg leading-7 font-semibold text-gray-900 dark:text-white">Vibrant Ecosystem</div>
</div>
<div class="ml-12">
<div class="mt-2 text-gray-600 dark:text-gray-400 text-sm">
Laravel's robust library of first-party tools and libraries, such as <a href="https://forge.laravel.com" class="underline">Forge</a>, <a href="https://vapor.laravel.com" class="underline">Vapor</a>, <a href="https://nova.laravel.com" class="underline">Nova</a>, and <a href="https://envoyer.io" class="underline">Envoyer</a> help you take your projects to the next level. Pair them with powerful open source libraries like <a href="https://laravel.com/docs/billing" class="underline">Cashier</a>, <a href="https://laravel.com/docs/dusk" class="underline">Dusk</a>, <a href="https://laravel.com/docs/broadcasting" class="underline">Echo</a>, <a href="https://laravel.com/docs/horizon" class="underline">Horizon</a>, <a href="https://laravel.com/docs/sanctum" class="underline">Sanctum</a>, <a href="https://laravel.com/docs/telescope" class="underline">Telescope</a>, and more.
</div>
</div>
</div>
</div>
</div>
<div class="flex justify-center mt-4 sm:items-center sm:justify-between">
<div class="text-center text-sm text-gray-500 sm:text-left">
<div class="flex items-center">
<svg fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" stroke="currentColor" class="-mt-px w-5 h-5 text-gray-400">
<path d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"></path>
</svg>
<a href="https://laravel.bigcartel.com" class="ml-1 underline">
Shop
</a>
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="ml-4 -mt-px w-5 h-5 text-gray-400">
<path d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path>
</svg>
<a href="https://github.com/sponsors/taylorotwell" class="ml-1 underline">
Sponsor
</a>
</div>
</div>
<div class="ml-4 text-center text-sm text-gray-500 sm:text-right sm:ml-0">
Laravel v{{ Illuminate\Foundation\Application::VERSION }} (PHP v{{ PHP_VERSION }})
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -10,47 +10,47 @@ use App\Http\Controllers\Auth\VerifyEmailController;
use Illuminate\Support\Facades\Route;
Route::get('/login', [AuthenticatedSessionController::class, 'create'])
->middleware('guest')
->name('login');
->middleware('guest')
->name('login');
Route::post('/login', [AuthenticatedSessionController::class, 'store'])
->middleware('guest');
->middleware('guest');
Route::get('/forgot-password', [PasswordResetLinkController::class, 'create'])
->middleware('guest')
->name('password.request');
->middleware('guest')
->name('password.request');
Route::post('/forgot-password', [PasswordResetLinkController::class, 'store'])
->middleware('guest')
->name('password.email');
->middleware('guest')
->name('password.email');
Route::get('/reset-password/{token}', [NewPasswordController::class, 'create'])
->middleware('guest')
->name('password.reset');
->middleware('guest')
->name('password.reset');
Route::post('/reset-password', [NewPasswordController::class, 'store'])
->middleware('guest')
->name('password.update');
->middleware('guest')
->name('password.update');
Route::get('/verify-email', [EmailVerificationPromptController::class, '__invoke'])
->middleware('auth')
->name('verification.notice');
->middleware('auth')
->name('verification.notice');
Route::get('/verify-email/{id}/{hash}', [VerifyEmailController::class, '__invoke'])
->middleware(['auth', 'signed', 'throttle:6,1'])
->name('verification.verify');
->middleware(['auth', 'signed', 'throttle:6,1'])
->name('verification.verify');
Route::post('/email/verification-notification', [EmailVerificationNotificationController::class, 'store'])
->middleware(['auth', 'throttle:6,1'])
->name('verification.send');
->middleware(['auth', 'throttle:6,1'])
->name('verification.send');
Route::get('/confirm-password', [ConfirmablePasswordController::class, 'show'])
->middleware('auth')
->name('password.confirm');
->middleware('auth')
->name('password.confirm');
Route::post('/confirm-password', [ConfirmablePasswordController::class, 'store'])
->middleware('auth');
->middleware('auth');
Route::post('/logout', [AuthenticatedSessionController::class, 'destroy'])
->middleware('auth')
->name('logout');
->middleware('auth')
->name('logout');

View File

@ -2,6 +2,7 @@
use App\Http\Controllers\ConfigurationController;
use App\Http\Controllers\InfoController;
use App\Http\Controllers\InitializationController;
use App\Http\Controllers\Test;
use Illuminate\Support\Facades\Route;
@ -19,6 +20,14 @@ use Illuminate\Support\Facades\Route;
// Percorsi di autenticazione e gestione utenza
require __DIR__.'/auth.php';
// Redirect predefinito a seguito del login
Route::get('/', function (){
$module = module('Dashboard');
return redirect('controller.php?id_module='.$module->id);
})
->middleware('auth');
// Sezione di configurazione
Route::get('/config', [ConfigurationController::class, 'index'])
->name('configuration');
@ -27,6 +36,12 @@ Route::get('/config-test', [ConfigurationController::class, 'test'])
Route::post('/config', [ConfigurationController::class, 'save'])
->name('configuration-save');
// Inizializzazione del gestionale
Route::get('/init', [InitializationController::class, 'index'])
->name('initialization');
Route::post('/init', [InitializationController::class, 'save'])
->name('initialization-save');
// Messaggi flash
Route::get('/messages', [Test::class, 'index'])
->name('messages');
@ -91,7 +106,3 @@ Route::get('/user', [Test::class, 'index'])
Route::get('/password', [Test::class, 'index'])
->name('user-password');
Route::post('/password', [Test::class, 'index']);
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware(['auth'])->name('dashboard');

View File

@ -1,12 +1,10 @@
<?php
/**
* Laravel - A PHP Framework For Web Artisans
* Laravel - A PHP Framework For Web Artisans.
*
* @package Laravel
* @author Taylor Otwell <taylor@laravel.com>
*/
$uri = urldecode(
parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
);

View File

@ -0,0 +1,45 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class AuthenticationTest extends TestCase
{
use RefreshDatabase;
public function testLoginScreenCanBeRendered()
{
$response = $this->get('/login');
$response->assertStatus(200);
}
public function testUsersCanAuthenticateUsingTheLoginScreen()
{
$user = User::factory()->create();
$response = $this->post('/login', [
'email' => $user->email,
'password' => 'password',
]);
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
}
public function testUsersCanNotAuthenticateWithInvalidPassword()
{
$user = User::factory()->create();
$this->post('/login', [
'email' => $user->email,
'password' => 'wrong-password',
]);
$this->assertGuest();
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Verified;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\URL;
use Tests\TestCase;
class EmailVerificationTest extends TestCase
{
use RefreshDatabase;
public function testEmailVerificationScreenCanBeRendered()
{
$user = User::factory()->create([
'email_verified_at' => null,
]);
$response = $this->actingAs($user)->get('/verify-email');
$response->assertStatus(200);
}
public function testEmailCanBeVerified()
{
Event::fake();
$user = User::factory()->create([
'email_verified_at' => null,
]);
$verificationUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1($user->email)]
);
$response = $this->actingAs($user)->get($verificationUrl);
Event::assertDispatched(Verified::class);
$this->assertTrue($user->fresh()->hasVerifiedEmail());
$response->assertRedirect(RouteServiceProvider::HOME.'?verified=1');
}
public function testEmailIsNotVerifiedWithInvalidHash()
{
$user = User::factory()->create([
'email_verified_at' => null,
]);
$verificationUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1('wrong-email')]
);
$this->actingAs($user)->get($verificationUrl);
$this->assertFalse($user->fresh()->hasVerifiedEmail());
}
}

View File

@ -2,7 +2,6 @@
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase

View File

@ -0,0 +1,44 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class PasswordConfirmationTest extends TestCase
{
use RefreshDatabase;
public function testConfirmPasswordScreenCanBeRendered()
{
$user = User::factory()->create();
$response = $this->actingAs($user)->get('/confirm-password');
$response->assertStatus(200);
}
public function testPasswordCanBeConfirmed()
{
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/confirm-password', [
'password' => 'password',
]);
$response->assertRedirect();
$response->assertSessionHasNoErrors();
}
public function testPasswordIsNotConfirmedWithInvalidPassword()
{
$user = User::factory()->create();
$response = $this->actingAs($user)->post('/confirm-password', [
'password' => 'wrong-password',
]);
$response->assertSessionHasErrors();
}
}

View File

@ -0,0 +1,71 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
class PasswordResetTest extends TestCase
{
use RefreshDatabase;
public function testResetPasswordLinkScreenCanBeRendered()
{
$response = $this->get('/forgot-password');
$response->assertStatus(200);
}
public function testResetPasswordLinkCanBeRequested()
{
Notification::fake();
$user = User::factory()->create();
$this->post('/forgot-password', ['email' => $user->email]);
Notification::assertSentTo($user, ResetPassword::class);
}
public function testResetPasswordScreenCanBeRendered()
{
Notification::fake();
$user = User::factory()->create();
$this->post('/forgot-password', ['email' => $user->email]);
Notification::assertSentTo($user, ResetPassword::class, function ($notification) {
$response = $this->get('/reset-password/'.$notification->token);
$response->assertStatus(200);
return true;
});
}
public function testPasswordCanBeResetWithValidToken()
{
Notification::fake();
$user = User::factory()->create();
$this->post('/forgot-password', ['email' => $user->email]);
Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {
$response = $this->post('/reset-password', [
'token' => $notification->token,
'email' => $user->email,
'password' => 'password',
'password_confirmation' => 'password',
]);
$response->assertSessionHasNoErrors();
return true;
});
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Tests\Feature;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class RegistrationTest extends TestCase
{
use RefreshDatabase;
public function testRegistrationScreenCanBeRendered()
{
$response = $this->get('/register');
$response->assertStatus(200);
}
public function testNewUsersCanRegister()
{
$response = $this->post('/register', [
'name' => 'Test User',
'email' => 'test@example.com',
'password' => 'password',
'password_confirmation' => 'password',
]);
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
}
}