mirror of
https://github.com/snipe/snipe-it.git
synced 2026-02-04 17:15:38 +00:00
Merge pull request #18302 from grokability/preflight-quickstart-cleanup
Preflight quickstart cleanup
This commit is contained in:
@ -6,38 +6,31 @@ use App\Helpers\Helper;
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Requests\SettingsSamlRequest;
|
||||
use App\Http\Requests\SetupUserRequest;
|
||||
use App\Http\Requests\StoreLabelSettings;
|
||||
use App\Http\Requests\StoreLdapSettings;
|
||||
use App\Http\Requests\StoreLocalizationSettings;
|
||||
use App\Http\Requests\StoreNotificationSettings;
|
||||
use App\Http\Requests\StoreLabelSettings;
|
||||
use App\Http\Requests\StoreSecuritySettings;
|
||||
use App\Models\Asset;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Group;
|
||||
use App\Models\Labels\Label as LabelModel;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Asset;
|
||||
use App\Models\User;
|
||||
use App\Notifications\FirstAdminNotification;
|
||||
use App\Notifications\MailTest;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Settings for
|
||||
@ -47,224 +40,6 @@ use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
*/
|
||||
class SettingsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Checks to see whether or not the database has a migrations table
|
||||
* and a user, otherwise display the setup view.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*
|
||||
* @since [v3.0]
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View | \Illuminate\Http\Response
|
||||
*/
|
||||
public function getSetupIndex() : View
|
||||
{
|
||||
$start_settings['php_version_min'] = false;
|
||||
|
||||
if (version_compare(PHP_VERSION, config('app.min_php'), '<')) {
|
||||
return response('<center><h1>This software requires PHP version '.config('app.min_php').' or greater. This server is running '.PHP_VERSION.'. </h1><h2>Please upgrade PHP on this server and try again. </h2></center>', 500);
|
||||
}
|
||||
|
||||
try {
|
||||
$conn = DB::select('select 2 + 2');
|
||||
$start_settings['db_conn'] = true;
|
||||
$start_settings['db_name'] = DB::connection()->getDatabaseName();
|
||||
$start_settings['db_error'] = null;
|
||||
} catch (\PDOException $e) {
|
||||
$start_settings['db_conn'] = false;
|
||||
$start_settings['db_name'] = config('database.connections.mysql.database');
|
||||
$start_settings['db_error'] = $e->getMessage();
|
||||
}
|
||||
|
||||
$start_settings['url_config'] = trim(config('app.url'), '/'). '/setup';
|
||||
$start_settings['real_url'] = request()->url();
|
||||
$start_settings['url_valid'] = $start_settings['url_config'] === $start_settings['real_url'];
|
||||
$start_settings['php_version_min'] = true;
|
||||
|
||||
// Curl the .env file to make sure it's not accessible via a browser
|
||||
$start_settings['env_exposed'] = $this->dotEnvFileIsExposed();
|
||||
|
||||
if (App::Environment('production') && (true == config('app.debug'))) {
|
||||
$start_settings['debug_exposed'] = true;
|
||||
} else {
|
||||
$start_settings['debug_exposed'] = false;
|
||||
}
|
||||
|
||||
$environment = app()->environment();
|
||||
if ('production' != $environment) {
|
||||
$start_settings['env'] = $environment;
|
||||
$start_settings['prod'] = false;
|
||||
} else {
|
||||
$start_settings['env'] = $environment;
|
||||
$start_settings['prod'] = true;
|
||||
}
|
||||
|
||||
$start_settings['owner'] = '';
|
||||
|
||||
if (function_exists('posix_getpwuid')) { // Probably Linux
|
||||
$owner = posix_getpwuid(fileowner($_SERVER['SCRIPT_FILENAME']));
|
||||
// This *should* be an array, but we've seen this return a bool in some chrooted environments
|
||||
if (is_array($owner)) {
|
||||
$start_settings['owner'] = $owner['name'];
|
||||
}
|
||||
}
|
||||
|
||||
if (($start_settings['owner'] === 'root') || ($start_settings['owner'] === '0')) {
|
||||
$start_settings['owner_is_admin'] = true;
|
||||
} else {
|
||||
$start_settings['owner_is_admin'] = false;
|
||||
}
|
||||
|
||||
$start_settings['writable'] = $this->storagePathIsWritable();
|
||||
|
||||
$start_settings['gd'] = extension_loaded('gd');
|
||||
|
||||
return view('setup/index')
|
||||
->with('step', 1)
|
||||
->with('start_settings', $start_settings)
|
||||
->with('section', 'Pre-Flight Check');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the .env file accessible via a browser.
|
||||
*
|
||||
* @return bool This method will return true when exceptions (such as curl exception) is thrown.
|
||||
* Check the log files to see more details about the exception.
|
||||
*/
|
||||
protected function dotEnvFileIsExposed() : bool
|
||||
{
|
||||
try {
|
||||
return Http::withoutVerifying()->timeout(10)
|
||||
->accept('*/*')
|
||||
->get(URL::to('.env'))
|
||||
->successful();
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e->getMessage());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the app storage path is writable.
|
||||
*/
|
||||
protected function storagePathIsWritable(): bool
|
||||
{
|
||||
return File::isWritable(storage_path()) &&
|
||||
File::isWritable(storage_path('framework')) &&
|
||||
File::isWritable(storage_path('framework/cache')) &&
|
||||
File::isWritable(storage_path('framework/sessions')) &&
|
||||
File::isWritable(storage_path('framework/views')) &&
|
||||
File::isWritable(storage_path('logs'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the first admin user from Setup.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
*
|
||||
*/
|
||||
public function postSaveFirstAdmin(SetupUserRequest $request) : RedirectResponse
|
||||
{
|
||||
|
||||
$user = new User();
|
||||
$user->first_name = $data['first_name'] = $request->input('first_name');
|
||||
$user->last_name = $request->input('last_name');
|
||||
$user->email = $data['email'] = $request->input('email');
|
||||
$user->activated = 1;
|
||||
$permissions = ['superuser' => 1];
|
||||
$user->permissions = json_encode($permissions);
|
||||
$user->username = $data['username'] = $request->input('username');
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
$data['password'] = $request->input('password');
|
||||
|
||||
$settings = new Setting();
|
||||
$settings->full_multiple_companies_support = $request->input('full_multiple_companies_support', 0);
|
||||
$settings->site_name = $request->input('site_name');
|
||||
$settings->alert_email = $request->input('email');
|
||||
$settings->alerts_enabled = 1;
|
||||
$settings->pwd_secure_min = 10;
|
||||
$settings->brand = 1;
|
||||
$settings->locale = $request->input('locale', 'en-US');
|
||||
$settings->default_currency = $request->input('default_currency', 'USD');
|
||||
$settings->created_by = 1;
|
||||
$settings->email_domain = $request->input('email_domain');
|
||||
$settings->email_format = $request->input('email_format');
|
||||
$settings->next_auto_tag_base = 1;
|
||||
$settings->auto_increment_assets = $request->input('auto_increment_assets', 0);
|
||||
$settings->auto_increment_prefix = $request->input('auto_increment_prefix');
|
||||
$settings->zerofill_count = $request->input('zerofill_count') ?: 0;
|
||||
|
||||
if ((! $user->isValid()) || (! $settings->isValid())) {
|
||||
return redirect()->back()->withInput()->withErrors($user->getErrors())->withErrors($settings->getErrors());
|
||||
} else {
|
||||
$user->save();
|
||||
Auth::login($user, true);
|
||||
$settings->save();
|
||||
|
||||
if ($request->input('email_creds') == '1') {
|
||||
$data = [];
|
||||
$data['email'] = $user->email;
|
||||
$data['username'] = $user->username;
|
||||
$data['first_name'] = $user->first_name;
|
||||
$data['last_name'] = $user->last_name;
|
||||
$data['password'] = $request->input('password');
|
||||
$user->notify(new FirstAdminNotification($data));
|
||||
}
|
||||
|
||||
return redirect()->route('setup.done');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the admin user creation form in Setup.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*
|
||||
* @since [v3.0]
|
||||
*/
|
||||
public function getSetupUser() : View
|
||||
{
|
||||
return view('setup/user')
|
||||
->with('step', 3)
|
||||
->with('section', 'Create a User');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the view that tells the user that the Setup is done.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*
|
||||
* @since [v3.0]
|
||||
*/
|
||||
public function getSetupDone() : View
|
||||
{
|
||||
return view('setup/done')
|
||||
->with('step', 4)
|
||||
->with('section', 'Done!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate the database tables, and return the output
|
||||
* to a view for Setup.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*
|
||||
* @since [v3.0]
|
||||
*/
|
||||
public function getSetupMigrate() : View
|
||||
{
|
||||
Artisan::call('migrate', ['--force' => true]);
|
||||
if ((! file_exists(storage_path().'/oauth-private.key')) || (! file_exists(storage_path().'/oauth-public.key'))) {
|
||||
Artisan::call('migrate', ['--path' => 'vendor/laravel/passport/database/migrations', '--force' => true]);
|
||||
Artisan::call('passport:install', ['--no-interaction' => true]);
|
||||
}
|
||||
|
||||
return view('setup/migrate')
|
||||
->with('output', 'Databases installed!')
|
||||
->with('step', 2)
|
||||
->with('section', 'Create Database Tables');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a view that shows some of the key settings.
|
||||
|
||||
270
app/Http/Controllers/SetupController.php
Normal file
270
app/Http/Controllers/SetupController.php
Normal file
@ -0,0 +1,270 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\SetupUserRequest;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Notifications\FirstAdminNotification;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Settings for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class SetupController extends Controller
|
||||
{
|
||||
/**
|
||||
* Checks to see whether or not the database has a migrations table
|
||||
* and a user, otherwise display the setup view.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*
|
||||
* @since [v3.0]
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View | \Illuminate\Http\Response
|
||||
*/
|
||||
public function getSetupIndex() : View
|
||||
{
|
||||
$start_settings['php_version_min'] = false;
|
||||
|
||||
if (version_compare(PHP_VERSION, config('app.min_php'), '<')) {
|
||||
return response('<center><h1>This software requires PHP version '.config('app.min_php').' or greater. This server is running '.PHP_VERSION.'. </h1><h2>Please upgrade PHP on this server and try again. </h2></center>', 500);
|
||||
}
|
||||
|
||||
try {
|
||||
$conn = DB::select('select 2 + 2');
|
||||
$start_settings['db_conn'] = true;
|
||||
$start_settings['db_name'] = DB::connection()->getDatabaseName();
|
||||
$start_settings['db_error'] = null;
|
||||
} catch (\PDOException $e) {
|
||||
$start_settings['db_conn'] = false;
|
||||
$start_settings['db_name'] = config('database.connections.mysql.database');
|
||||
$start_settings['db_error'] = $e->getMessage();
|
||||
}
|
||||
|
||||
$start_settings['url_config'] = trim(config('app.url'), '/'). '/setup';
|
||||
$start_settings['real_url'] = request()->url();
|
||||
$start_settings['url_valid'] = $start_settings['url_config'] === $start_settings['real_url'];
|
||||
$start_settings['php_version_min'] = true;
|
||||
|
||||
// Curl the .env file to make sure it's not accessible via a browser
|
||||
$start_settings['env_exposed'] = $this->dotEnvFileIsExposed();
|
||||
|
||||
if (App::Environment('production') && (true == config('app.debug'))) {
|
||||
$start_settings['debug_exposed'] = true;
|
||||
} else {
|
||||
$start_settings['debug_exposed'] = false;
|
||||
}
|
||||
|
||||
$environment = app()->environment();
|
||||
if ('production' != $environment) {
|
||||
$start_settings['env'] = $environment;
|
||||
$start_settings['prod'] = false;
|
||||
} else {
|
||||
$start_settings['env'] = $environment;
|
||||
$start_settings['prod'] = true;
|
||||
}
|
||||
|
||||
$start_settings['owner'] = '';
|
||||
|
||||
if (function_exists('posix_getpwuid')) { // Probably Linux
|
||||
$owner = posix_getpwuid(fileowner($_SERVER['SCRIPT_FILENAME']));
|
||||
// This *should* be an array, but we've seen this return a bool in some chrooted environments
|
||||
if (is_array($owner)) {
|
||||
$start_settings['owner'] = $owner['name'];
|
||||
}
|
||||
}
|
||||
|
||||
if (($start_settings['owner'] === 'root') || ($start_settings['owner'] === '0')) {
|
||||
$start_settings['owner_is_admin'] = true;
|
||||
} else {
|
||||
$start_settings['owner_is_admin'] = false;
|
||||
}
|
||||
|
||||
$start_settings['writable'] = $this->storagePathIsWritable();
|
||||
|
||||
$start_settings['gd'] = extension_loaded('gd');
|
||||
|
||||
return view('setup/index')
|
||||
->with('step', 1)
|
||||
->with('start_settings', $start_settings)
|
||||
->with('section', trans('general.setup_config_check'))
|
||||
->with('icon', 'fa-regular fa-rectangle-list');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the .env file accessible via a browser.
|
||||
*
|
||||
* @return bool This method will return true when exceptions (such as curl exception) is thrown.
|
||||
* Check the log files to see more details about the exception.
|
||||
*/
|
||||
protected function dotEnvFileIsExposed() : bool
|
||||
{
|
||||
try {
|
||||
return Http::withoutVerifying()->timeout(10)
|
||||
->accept('*/*')
|
||||
->get(URL::to('.env'))
|
||||
->successful();
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e->getMessage());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the app storage path is writable.
|
||||
*/
|
||||
protected function storagePathIsWritable(): bool
|
||||
{
|
||||
return File::isWritable(storage_path()) &&
|
||||
File::isWritable(storage_path('framework')) &&
|
||||
File::isWritable(storage_path('framework/cache')) &&
|
||||
File::isWritable(storage_path('framework/sessions')) &&
|
||||
File::isWritable(storage_path('framework/views')) &&
|
||||
File::isWritable(storage_path('logs'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the first admin user from Setup.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
*
|
||||
*/
|
||||
public function postSaveFirstAdmin(SetupUserRequest $request) : RedirectResponse
|
||||
{
|
||||
|
||||
$user = new User();
|
||||
$user->first_name = $data['first_name'] = $request->input('first_name');
|
||||
$user->last_name = $request->input('last_name');
|
||||
$user->email = $data['email'] = $request->input('email');
|
||||
$user->activated = 1;
|
||||
$permissions = ['superuser' => 1];
|
||||
$user->permissions = json_encode($permissions);
|
||||
$user->username = $data['username'] = $request->input('username');
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
$data['password'] = $request->input('password');
|
||||
|
||||
$settings = new Setting();
|
||||
$settings->full_multiple_companies_support = $request->input('full_multiple_companies_support', 0);
|
||||
$settings->site_name = $request->input('site_name');
|
||||
$settings->alert_email = $request->input('email');
|
||||
$settings->alerts_enabled = 1;
|
||||
$settings->pwd_secure_min = 10;
|
||||
$settings->brand = 1;
|
||||
$settings->link_light_color = $request->input('link_light_color', '#296282');
|
||||
$settings->link_dark_color = $request->input('link_dark_color', '#296282');
|
||||
$settings->nav_link_color = $request->input('nav_link_color', '#FFFFFF');
|
||||
$settings->locale = $request->input('locale', 'en-US');
|
||||
$settings->default_currency = $request->input('default_currency', 'USD');
|
||||
$settings->created_by = 1;
|
||||
$settings->email_domain = $request->input('email_domain');
|
||||
$settings->email_format = $request->input('email_format');
|
||||
$settings->next_auto_tag_base = 1;
|
||||
$settings->auto_increment_assets = $request->input('auto_increment_assets', 0);
|
||||
$settings->auto_increment_prefix = $request->input('auto_increment_prefix');
|
||||
$settings->zerofill_count = $request->input('zerofill_count') ?: 0;
|
||||
|
||||
if ((! $user->isValid()) || (! $settings->isValid())) {
|
||||
return redirect()->back()->withInput()->withErrors($user->getErrors())->withErrors($settings->getErrors());
|
||||
} else {
|
||||
$user->save();
|
||||
Auth::login($user, true);
|
||||
$settings->save();
|
||||
|
||||
if ($request->input('email_creds') == '1') {
|
||||
$data = [];
|
||||
$data['email'] = $user->email;
|
||||
$data['username'] = $user->username;
|
||||
$data['first_name'] = $user->first_name;
|
||||
$data['last_name'] = $user->last_name;
|
||||
$data['password'] = $request->input('password');
|
||||
$user->notify(new FirstAdminNotification($data));
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->route('setup.done')
|
||||
->with('section', trans('general.setup_create_admin'))
|
||||
->with('icon', 'fa-solid fa-champagne-glasses')
|
||||
->with('success', trans('admin/settings/general.create_admin_success'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the admin user creation form in Setup.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*
|
||||
* @since [v3.0]
|
||||
*/
|
||||
public function getSetupUser() : View
|
||||
{
|
||||
return view('setup/user')
|
||||
->with('step', 3)
|
||||
->with('section', trans('general.setup_create_admin'))
|
||||
->with('icon', 'fa-solid fa-user-plus');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the view that tells the user that the Setup is done.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*
|
||||
* @since [v3.0]
|
||||
*/
|
||||
public function getSetupDone() : View
|
||||
{
|
||||
return view('setup/done')
|
||||
->with('success', trans('general.create_admin_success'))
|
||||
->with('step', 4)
|
||||
->with('icon', 'fa-solid fa-champagne-glasses fa-shake')
|
||||
->with('section', trans('general.setup_done'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Migrate the database tables, and return the output
|
||||
* to a view for Setup.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*
|
||||
* @since [v3.0]
|
||||
*/
|
||||
public function setupMigrate()
|
||||
{
|
||||
Artisan::call('migrate', ['--force' => true]);
|
||||
$output = Artisan::output();
|
||||
if ((! file_exists(storage_path().'/oauth-private.key')) || (! file_exists(storage_path().'/oauth-public.key'))) {
|
||||
Artisan::call('migrate', ['--path' => 'vendor/laravel/passport/database/migrations', '--force' => true]);
|
||||
Artisan::call('passport:install', ['--no-interaction' => true]);
|
||||
}
|
||||
|
||||
return view('setup/migrate')
|
||||
->with('success', trans('general.create_admin_success'))
|
||||
->with('output', trim($output))
|
||||
->with('step', 2)
|
||||
->with('section', trans('general.setup_create_database'))
|
||||
->with('icon', 'fa-solid fa-database');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -28,7 +28,6 @@ class SetupUserRequest extends Request
|
||||
'username' => 'required|string|min:2|unique:users,username,NULL,deleted_at',
|
||||
'email' => 'email|unique:users,email',
|
||||
'password' => 'required|min:8|confirmed',
|
||||
'email_domain' => 'required|min:4',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -366,13 +366,14 @@ return [
|
||||
'employee_number' => 'Employee Number',
|
||||
'create_admin_user' => 'Create a User ::',
|
||||
'create_admin_success' => 'Success! Your admin user has been added!',
|
||||
'create_admin_redirect' => 'Click here to go to your app login!',
|
||||
'create_admin_redirect' => 'Go To Dashboard',
|
||||
'setup_migrations' => 'Database Migrations ::',
|
||||
'setup_no_migrations' => 'There was nothing to migrate. Your database tables were already set up!',
|
||||
'setup_successful_migrations' => 'Your database tables have been created',
|
||||
'setup_migration_output' => 'Migration output:',
|
||||
'setup_migration_create_user' => 'Next: Create User',
|
||||
'setup_migration_create_user' => 'Save User and Finish',
|
||||
'ldap_settings_link' => 'LDAP Settings Page',
|
||||
'setup_create_user_page_explanation' => 'Here you will create your first superadmin user and set some basic application setting defaults. (These can always be changed later in the Admin Settings section.) ',
|
||||
'slack_test' => 'Test <i class="fab fa-slack"></i> Integration',
|
||||
'status_label_name' => 'Status Label Name',
|
||||
'super_admin_only' => 'Super Admin Only',
|
||||
|
||||
@ -384,9 +384,10 @@ return [
|
||||
'setup_step_3' => 'Step 3',
|
||||
'setup_step_4' => 'Step 4',
|
||||
'setup_config_check' => 'Configuration Check',
|
||||
'setup_create_database' => 'Create database tables',
|
||||
'setup_create_admin' => 'Create an admin user',
|
||||
'setup_done' => 'Finished!',
|
||||
'setup_create_database' => 'Create Database Tables',
|
||||
'setup_create_admin' => 'Create an Admin User',
|
||||
'setup_next' => 'Next',
|
||||
'setup_done' => 'Setup Complete!',
|
||||
'bulk_edit_about_to' => 'You are about to edit the following: ',
|
||||
'checked_out' => 'Checked Out',
|
||||
'checked_out_to' => 'Checked out to',
|
||||
|
||||
@ -31,7 +31,10 @@
|
||||
}
|
||||
|
||||
.preflight-error {
|
||||
color: red;
|
||||
color: #b60707;
|
||||
}
|
||||
.preflight-info {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.preflight-warning {
|
||||
@ -50,7 +53,26 @@
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #ecf0f5;
|
||||
}
|
||||
|
||||
.bs-wizard-info {
|
||||
color: #959495 !important;
|
||||
}
|
||||
|
||||
h4 {
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
p, li {
|
||||
font-size: 15px;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
li {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
@ -58,9 +80,9 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-10 col-lg-offset-1">
|
||||
<h1 class="page-header">Snipe-IT {{ trans('general.pre_flight') }}</h1>
|
||||
<h1 class="page-header"><img src="../img/logo.png" style="height: 65px;" alt="Snipe-IT logo"> {{ trans('general.pre_flight') }}</h1>
|
||||
</div>
|
||||
<div class="col-lg-11 col-lg-offset-1">
|
||||
<div class="col-lg-12">
|
||||
|
||||
<div class="row bs-wizard" style="border-bottom:0;">
|
||||
|
||||
@ -68,13 +90,13 @@
|
||||
<div class="text-center bs-wizard-stepnum">{{ trans('general.setup_step_1') }}</div>
|
||||
<div class="progress"><div class="progress-bar"></div></div>
|
||||
<a href="{{ route('setup') }}" class="bs-wizard-dot"></a>
|
||||
<div class="bs-wizard-info text-center">{{ trans('general.setup_config_check') }}</div>
|
||||
<div class="bs-wizard-info text-center" style="padding-left: 90px;">{{ trans('general.setup_config_check') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-3 bs-wizard-step {{ ($step == 2) ? 'active': (($step < 2) ? 'disabled' : 'complete') }}"><!-- complete -->
|
||||
<div class="text-center bs-wizard-stepnum">{{ trans('general.setup_step_2') }}</div>
|
||||
<div class="progress"><div class="progress-bar"></div></div>
|
||||
<a href="{{ route('setup.migrate') }}" class="bs-wizard-dot"></a>
|
||||
<a href="#" class="bs-wizard-dot"></a>
|
||||
<div class="bs-wizard-info text-center">{{ trans('general.setup_create_database') }}</div>
|
||||
</div>
|
||||
|
||||
@ -94,25 +116,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-10 col-lg-offset-1" style="padding-top: 50px;">
|
||||
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{{ $section }}
|
||||
<div class="box box-default">
|
||||
<div class="box-header with-border">
|
||||
<h4><i class="{{ $icon ?? '' }}" style="--fa-animation-duration: 10s; --fa-animation-iteration-count: 3;"></i> {{ $section }}</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="box-body">
|
||||
|
||||
@include('notifications')
|
||||
|
||||
|
||||
<!-- Content -->
|
||||
@yield('content')
|
||||
</div>
|
||||
<div class="panel-footer text-right">
|
||||
<div class="box-footer text-right">
|
||||
@section('button')
|
||||
@show
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<strong>Snipe-IT {{ trans('general.version') }}</strong> {{ config('version.app_version') }} -
|
||||
{{ trans('general.build') }} {{ config('version.build_version') }} ({{ config('version.branch') }})
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -7,13 +7,104 @@
|
||||
|
||||
{{-- Page content --}}
|
||||
@section('content')
|
||||
<div class="col-lg-12" style="padding-top: 20px;">
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-warning">
|
||||
<i class="fas fa-check"></i>
|
||||
{{ trans('general.create_admin_success') }}
|
||||
|
||||
<style>
|
||||
.well-warning {
|
||||
color: #8a6d3b;
|
||||
background-color: #fcf8e3;
|
||||
border-color: #faebcc;
|
||||
}
|
||||
</style>
|
||||
<!-- Notifications -->
|
||||
<div class="col-md-12">
|
||||
|
||||
<p>
|
||||
If you're already familiar with Snipe-IT, you can get started right away by <strong><a href="{{ config('app.url') }}">heading right to your dashboard</a></strong>, or if it's your first time using Snipe-IT, you can check out some of the useful resources below:
|
||||
</p>
|
||||
<div class="well well-sm">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<ul>
|
||||
<li><i class="fa-solid fa-book fa-fw"></i> <a href="https://snipe-it.readme.io/docs/overview#/" target="_blank">Overview <x-icon type="external-link" /></a></li>
|
||||
<li><i class="fa-solid fa-book fa-fw"></i> <a href="https://snipe-it.readme.io/docs/getting-started#/" target="_blank">Getting Started <x-icon type="external-link" /></a></li>
|
||||
<li><i class="fa-solid fa-book fa-fw"></i> <a href="https://snipe-it.readme.io/reference/api-overview#/" target="_blank">API Documentation <x-icon type="external-link" /></a></li>
|
||||
<li><i class="fa-solid fa-book fa-fw"></i> <a href="https://snipe-it.readme.io/docs/importing-users#/" target="_blank">Importing Users <x-icon type="external-link" /></a></li>
|
||||
<li><i class="fa-solid fa-book fa-fw"></i> <a href="https://snipe-it.readme.io/docs/importing-assets#/" target="_blank">Importing Assets <x-icon type="external-link" /></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<ul>
|
||||
<li><i class="fa-solid fa-book fa-fw"></i> <a href="https://snipe-it.readme.io/reference/api-overview#/" target="_blank">API Documentation <x-icon type="external-link" /></a></li>
|
||||
<li><i class="fa-solid fa-book fa-fw"></i> <a href="https://snipe-it.readme.io/docs/saml#/" target="_blank">SAML Authentication<x-icon type="external-link" /></a></li>
|
||||
<li><i class="fa-solid fa-book fa-fw"></i> <a href="https://snipe-it.readme.io/docs/scim#/" target="_blank">SCIM <x-icon type="external-link" /></a></li>
|
||||
<li><i class="fa-solid fa-book fa-fw"></i> <a href="https://snipe-it.readme.io/docs/ldap-sync-login#/" target="_blank">LDAP Sync & Login <x-icon type="external-link" /></a></li>
|
||||
<li><i class="fa-solid fa-book fa-fw"></i> <a href="https://snipe-it.readme.io/docs/webhook-integration#/" target="_blank">Webhooks <x-icon type="external-link" /></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="well well-sm well-warning">
|
||||
|
||||
<p>
|
||||
<x-icon type="tip" /> <strong>Important Note Syncing Users via SCIM or LDAP</strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you plan on using SCIM or LDAP syncing to keep your user lists up to date with your directory services,
|
||||
make sure the username format for any users imported via CSV matches your directory service username format to avoid duplicating users in Snipe-IT.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Don't forget to join our communities! You can find us on:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><i class="fa-brands fa-github fa-fw"></i> <a href="https://github.com/grokability/snipe-it" target="_blank">Github <x-icon type="external-link" /></a></li>
|
||||
<li><i class="fa-brands fa-discord fa-fw"></i> <a href="https://discord.gg/yZFtShAcKk" target="_blank">Discord <x-icon type="external-link" /></a></li>
|
||||
<li><i class="fa-brands fa-bluesky fa-fw"></i> <a href="https://bsky.app/profile/snipeitapp.com" target="_blank">Bluesky <x-icon type="external-link" /></a></li>
|
||||
<li><i class="fa-brands fa-mastodon fa-fw"></i> <a href="https://hachyderm.io/@grokability" target="_blank">Mastodon <x-icon type="external-link" /></a></li>
|
||||
<li><i class="fa-solid fa-square-rss fa-fw"></i> Our blog at <a href="https://grokstar.dev" target="_blank">Grokstar.Dev <x-icon type="external-link" /></a></li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Subscribe on Github for notifications about new releases. (We recommend selecting "Releases Only" for most users - the repo can get noisy.)
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<p>{{ trans('general.create_admin_redirect') }} <a href="{{ config('app.url') }}">{{ config('app.url') }}</a></p>
|
||||
</div>
|
||||
|
||||
@stop
|
||||
|
||||
@section('button')
|
||||
<a class="btn btn-primary" href="{{ config('app.url') }}">{{ trans('admin/settings/general.create_admin_redirect') }}
|
||||
<i class="fa-solid fa-angles-right"></i>
|
||||
</a>
|
||||
@parent
|
||||
@stop
|
||||
|
||||
<script>
|
||||
var duration = 2000;
|
||||
var animationEnd = Date.now() + duration;
|
||||
var defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 };
|
||||
|
||||
function randomInRange(min, max) {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
|
||||
var interval = setInterval(function() {
|
||||
var timeLeft = animationEnd - Date.now();
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
return clearInterval(interval);
|
||||
}
|
||||
|
||||
var particleCount = 50 * (timeLeft / duration);
|
||||
// since particles fall down, start a bit higher than random
|
||||
confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 } });
|
||||
confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 } });
|
||||
}, 250);
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ Create a User ::
|
||||
{{-- Page content --}}
|
||||
@section('content')
|
||||
|
||||
<p>This page will do a system check to make sure your configuration looks correct. We'll add your first user on the next page. </p>
|
||||
<h4> First let's do a quick system check to make sure your configuration looks correct. </h4>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
@ -162,7 +162,7 @@ Create a User ::
|
||||
@if (!$start_settings['debug_exposed'])
|
||||
Awesomesauce. Debug is either turned off, or you're running this in a non-production environment. (Don't forget to turn it off when you're ready to go live.)
|
||||
@else
|
||||
Yikes! You should turn off debug mode unless you encounter any issues. Please update your <code>APP_DEBUG</code> settings in your <code>.env</code> file
|
||||
<p>Yikes! You should turn off debug mode unless you encounter any issues. Please update your <code>APP_DEBUG</code> settings in your <code>.env</code> file</p>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@ -178,29 +178,22 @@ Create a User ::
|
||||
</td>
|
||||
<td>
|
||||
@if ($start_settings['gd'])
|
||||
GD is installed. Go you!
|
||||
<p>GD is installed. Go you!</p>
|
||||
@else
|
||||
The GD library isn't installed. While this won't prevent the system from working, you won't be able to generate labels or upload images.
|
||||
<p>The GD library isn't installed. While this won't prevent the system from working, you won't be able to generate labels or upload images.</p>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr id="mailtestrow" class="warning">
|
||||
<tr id="mailtestrow" class="info">
|
||||
<td>Email</td>
|
||||
<td>
|
||||
<a class="btn btn-default btn-sm pull-left" id="mailtest" style="margin-right: 10px;">
|
||||
Send Test</a>
|
||||
<span id="mailtesticon"></span>
|
||||
</td>
|
||||
<td>
|
||||
<span id="mailtesticon"></span>
|
||||
<span id="mailtestresult"></span>
|
||||
<span id="mailteststatus"></span>
|
||||
<div class="col-md-12">
|
||||
<div id="mailteststatus-error" class="text-danger"></div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<p class="help-block">This will attempt to send a test mail to {{ config('mail.from.address') }}.</p>
|
||||
</div>
|
||||
<p>This will attempt to send a test mail to {{ config('mail.from.address') }}.</p>
|
||||
<a class="btn btn-default btn-sm pull-left" id="mailtest" style="margin-right: 10px;">Send Test</a>
|
||||
<div id="mailteststatus-text" class="text-danger"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -209,9 +202,14 @@ Create a User ::
|
||||
@stop
|
||||
|
||||
@section('button')
|
||||
<form action="{{ route('setup.migrate') }}" method="GET">
|
||||
<button class="btn btn-primary">Next: Create Database Tables</button>
|
||||
<form action="{{ route('setup.migrate') }}" method="POST">
|
||||
@csrf
|
||||
<button class="btn btn-primary">
|
||||
{{ trans('general.setup_next') }}: {{ trans('general.setup_create_database') }}
|
||||
<i class="fa-solid fa-angles-right"></i>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@parent
|
||||
@stop
|
||||
|
||||
@ -223,12 +221,11 @@ Create a User ::
|
||||
|
||||
$("#mailtest").click(function(){
|
||||
|
||||
$("#mailtestrow").removeClass('success').removeClass('danger').removeClass('warning');
|
||||
$("#mailtestrow").addClass('info');
|
||||
$("#mailtestrow").removeClass('success').removeClass('danger').removeClass('warning').addClass('info');
|
||||
$("#mailtesticon").html('');
|
||||
$("#mailteststatus").html('');
|
||||
$("#mailteststatus").html('Sending Test Email...');
|
||||
$('#mailteststatus-error').html('');
|
||||
$("#mailtesticon").html('<i class="fas fa-spinner spin"></i> Sending Test Email...');
|
||||
$("#mailtesticon").html('<i class="fas fa-spinner fa-spin text-info"></i>');
|
||||
|
||||
$.ajax({
|
||||
url: "{{ route('setup.mailtest') }}",
|
||||
@ -237,12 +234,12 @@ Create a User ::
|
||||
if (result.status == 'success') {
|
||||
$("#mailtestrow").removeClass('info').removeClass('danger').removeClass('warning');
|
||||
$("#mailtestrow").addClass('success');
|
||||
$("#mailtesticon").html('');
|
||||
$("#mailtesticon").html('<i class="fas fa-check preflight-success"></i>');
|
||||
$("#mailteststatus").html('');
|
||||
$('#mailteststatus-error').html('');
|
||||
$("#mailteststatus").removeClass('text-danger');
|
||||
$("#mailteststatus").addClass('text-success');
|
||||
$("#mailteststatus").html('<i class="fas fa-check text-success"></i> Mail sent to {{ config('mail.from.address') }}!');
|
||||
$("#mailteststatus-text").removeClass('text-danger');
|
||||
$("#mailteststatus-text").addClass('text-success');
|
||||
$("#mailteststatus-text").html('Mail sent to {{ config('mail.from.address') }}!');
|
||||
} else {
|
||||
$("#mailtestrow").removeClass('success').removeClass('info').removeClass('warning');
|
||||
$("#mailtestrow").addClass('danger');
|
||||
@ -257,12 +254,12 @@ Create a User ::
|
||||
$("#mailtestrow").removeClass('success').removeClass('info').removeClass('warning');
|
||||
$("#mailtestrow").addClass('danger');
|
||||
$("#mailtesticon").html('');
|
||||
$("#mailteststatus").html('');
|
||||
$("#mailteststatus-text").html('');
|
||||
$('#mailteststatus-error').html('');
|
||||
$("#mailteststatus").removeClass('text-success');
|
||||
$("#mailteststatus").addClass('text-danger');
|
||||
$("#mailteststatus-text").removeClass('text-success');
|
||||
$("#mailteststatus-text").addClass('text-danger');
|
||||
$("#mailtesticon").html('<i class="fas fa-exclamation-triangle text-danger"></i>');
|
||||
$('#mailteststatus').html('Mail could not be sent.');
|
||||
$('#mailteststatus-text').html('Mail could not be sent.');
|
||||
if (result.responseJSON) {
|
||||
$('#mailteststatus-error').html('Error: ' + result.responseJSON.messages);
|
||||
} else {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
@extends('layouts/setup')
|
||||
{{-- Page title --}}
|
||||
@section('title')
|
||||
{{ trans('general.setup_migrations') }}
|
||||
{{ trans('admin/settings/general.setup_migrations') }}
|
||||
@parent
|
||||
@stop
|
||||
|
||||
@ -15,13 +15,6 @@
|
||||
{{ trans('general.setup_no_migrations') }}
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-success">
|
||||
<i class="fas fa-check"></i>
|
||||
{{ trans('general.setup_successful_migrations') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
|
||||
@ -31,8 +24,11 @@
|
||||
@stop
|
||||
|
||||
@section('button')
|
||||
<form action="{{ route('setup.user') }}" method="GET">
|
||||
<button class="btn btn-primary">{{ trans('general.setup_migration_create_user') }}</button>
|
||||
</form>
|
||||
|
||||
<a href="{{ route('setup.user') }}" class="btn btn-primary">
|
||||
{{ trans('general.setup_next') }}:
|
||||
{{ trans('general.setup_create_admin') }}
|
||||
<i class="fa-solid fa-angles-right"></i>
|
||||
</a>
|
||||
@parent
|
||||
@stop
|
||||
|
||||
@ -8,7 +8,11 @@
|
||||
{{-- Page content --}}
|
||||
@section('content')
|
||||
|
||||
<p>{{ trans('admin/users/general.create_user_page_explanation') }}</p>
|
||||
|
||||
<div class="col-md-12">
|
||||
<h4>{{ trans('admin/settings/general.setup_create_user_page_explanation') }}</h4>
|
||||
</div>
|
||||
|
||||
|
||||
<form action="{{ route('setup.user.save') }}" method="POST">
|
||||
{{ csrf_field() }}
|
||||
@ -27,7 +31,103 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- Name -->
|
||||
<div class="row">
|
||||
<!-- first name -->
|
||||
<div class="form-group col-lg-6">
|
||||
<label for="first_name">{{ trans('general.first_name') }}</label>
|
||||
<input class="form-control" placeholder="Jane" required="" name="first_name" type="text" id="first_name" value="{{ old('first_name') }}">
|
||||
{!! $errors->first('first_name', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
|
||||
<!-- last name -->
|
||||
<div class="form-group col-lg-6 required {{ $errors->has('last_name') ? 'error' : '' }}">
|
||||
<label for="last_name">{{ trans('general.last_name') }}</label>
|
||||
<input class="form-control" placeholder="Smith" required="" name="last_name" type="text" id="last_name" value="{{ old('last_name') }}">
|
||||
{!! $errors->first('last_name', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- email-->
|
||||
<div class="form-group col-lg-6{{ $errors->has('email') ? ' error' : '' }}">
|
||||
<label for="email">{{ trans('admin/users/table.email') }}</label>
|
||||
<input class="form-control" type="email" name="email" id="email" value="{{ old('email', config('mail.from.address')) }}" placeholder="you@example.com" required>
|
||||
{!! $errors->first('email', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
|
||||
<!-- username -->
|
||||
<div class="form-group col-lg-6 {{ $errors->has('username') ? 'error' : '' }}">
|
||||
<label for="username">{{ trans('admin/users/table.username') }}</label>
|
||||
<input class="form-control" placeholder="jsmith" required="" name="username" type="text" id="username" value="{{ old('username') }}" required>
|
||||
{!! $errors->first('username', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- password -->
|
||||
<div class="form-group col-lg-6{{ (Helper::checkIfRequired(\App\Models\User::class, 'password')) ? ' required' : '' }} {{ $errors->has('password') ? 'error' : '' }}">
|
||||
<label for="password">{{ trans('admin/users/table.password') }}</label>
|
||||
<input class="form-control" type="password" name="password" id="password" value="" required>
|
||||
{!! $errors->first('password', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
|
||||
<!-- password confirm -->
|
||||
<div class="form-group col-lg-6{{ (Helper::checkIfRequired(\App\Models\User::class, 'password')) ? ' required' : '' }} {{ $errors->has('password_confirm') ? 'error' : '' }}">
|
||||
<label for="password_confirmation">{{ trans('admin/users/table.password_confirm') }}</label>
|
||||
<input class="form-control" type="password" name="password_confirmation" id="password_confirmation" value="" required>
|
||||
{!! $errors->first('password_confirmation', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
|
||||
<!-- Email credentials -->
|
||||
<div class="form-group col-lg-12">
|
||||
<label class="form-control form-control">
|
||||
<input type="checkbox" value="1" name="email_creds">{{ trans('admin/users/general.email_credentials_text') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="form-group col-lg-6{{ $errors->has('auto_increment_prefix') ? ' error' : '' }}">
|
||||
<label for="auto_increment_prefix">{{ trans('admin/settings/general.auto_increment_prefix') }}</label>
|
||||
<input class="form-control" name="auto_increment_prefix" type="text" id="auto_increment_prefix" value="{{ old('auto_increment_prefix') }}">
|
||||
|
||||
{!! $errors->first('auto_increment_prefix', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-lg-6{{ $errors->has('zerofill_count') ? ' error' : '' }}">
|
||||
<label for="zerofill_count">{{ trans('admin/settings/general.zerofill_count') }}</label>
|
||||
<input class="form-control" name="zerofill_count" type="text" value="{{ old('zerofill_count', 5) }}" id="zerofill_count">
|
||||
|
||||
{!! $errors->first('zerofill_count', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="form-group col-lg-6">
|
||||
<label class="form-control form-control">
|
||||
<input type="checkbox" value="1" name="auto_increment_assets">{{trans('admin/settings/general.auto_increment_assets')}}
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Multi Company Support -->
|
||||
<div class="form-group col-lg-6">
|
||||
<label class="form-control form-control">
|
||||
<input type="checkbox" value="1" name="full_multiple_companies_support"> {{ trans('admin/settings/general.full_multiple_companies_support_text') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="row">
|
||||
|
||||
<!-- Language -->
|
||||
<div class="form-group col-lg-6{{$errors->has('default_language') ? ' error' : ''}}">
|
||||
@ -48,122 +148,20 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="form-group col-lg-6">
|
||||
|
||||
<label class="form-control form-control">
|
||||
<input type="checkbox" value="1" name="auto_increment_assets">{{trans('admin/settings/general.auto_increment_assets')}}
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Multi Company Support -->
|
||||
<div class="form-group col-lg-6">
|
||||
<label class="form-control form-control">
|
||||
<input type="checkbox" value="1" name="full_multiple_companies_support"> {{ trans('admin/settings/general.full_multiple_companies_support_text') }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="form-group col-lg-6{{ $errors->has('auto_increment_prefix') ? ' error' : '' }}">
|
||||
<label for="auto_increment_prefix">{{ trans('admin/settings/general.auto_increment_prefix') }}</label>
|
||||
<input class="form-control" name="auto_increment_prefix" type="text" id="auto_increment_prefix" value="{{ old('auto_increment_prefix') }}">
|
||||
|
||||
{!! $errors->first('auto_increment_prefix', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
|
||||
<div class="form-group col-lg-6{{ $errors->has('zerofill_count') ? ' error' : '' }}">
|
||||
<label for="zerofill_count">{{ trans('admin/settings/general.zerofill_count') }}</label>
|
||||
<input class="form-control" name="zerofill_count" type="text" value="{{ old('zerofill_count', 5) }}" id="zerofill_count">
|
||||
|
||||
{!! $errors->first('zerofill_count', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- email domain -->
|
||||
<div class="row">
|
||||
<div class="form-group col-lg-6 required {{ $errors->has('email_domain') ? 'error' : '' }}">
|
||||
<label for="email_domain">{{ trans('general.email_domain') }}</label>
|
||||
<input class="form-control" placeholder="example.com" required="" name="email_domain" type="text" id="email_domain" value="{{ old('email_domain') }}">
|
||||
<span class="help-block">{{ trans('general.email_domain_help') }}</span>
|
||||
|
||||
{!! $errors->first('email_domain', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
|
||||
<!-- email format -->
|
||||
<div class="form-group col-lg-6 {{ $errors->has('email_format') ? 'error' : '' }}">
|
||||
<label for="email_format">{{ trans('admin/settings/general.email_formats.email_format') }}</label>
|
||||
{!! Form::username_format('email_format', old('email_format', 'filastname'), 'select2') !!}
|
||||
{!! $errors->first('email_format', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Name -->
|
||||
<div class="row">
|
||||
<!-- first name -->
|
||||
<div class="form-group col-lg-6">
|
||||
<label for="first_name">{{ trans('general.first_name') }}</label>
|
||||
<input class="form-control" placeholder="Jane" required="" name="first_name" type="text" id="first_name" value="{{ old('first_name') }}">
|
||||
{!! $errors->first('first_name', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
|
||||
<!-- last name -->
|
||||
<div class="form-group col-lg-6 required {{ $errors->has('last_name') ? 'error' : '' }}">
|
||||
<label for="last_name">{{ trans('general.last_name') }}</label>
|
||||
<input class="form-control" placeholder="Smith" required="" name="last_name" type="text" id="last_name" value="{{ old('last_name') }}">
|
||||
{!! $errors->first('last_name', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- email-->
|
||||
<div class="form-group col-lg-6{{ $errors->has('email') ? 'error' : '' }}">
|
||||
<label for="email">{{ trans('admin/users/table.email') }}</label>
|
||||
<input class="form-control" type="email" name="email" id="email" value="{{ old('email', config('mail.from.address')) }}" placeholder="you@example.com" required>
|
||||
{!! $errors->first('email', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
|
||||
<!-- username -->
|
||||
<div class="form-group col-lg-6{{ (Helper::checkIfRequired(\App\Models\User::class, 'username')) ? ' required' : '' }} {{ $errors->has('username') ? 'error' : '' }}">
|
||||
<label for="username">{{ trans('admin/users/table.username') }}</label>
|
||||
<input class="form-control" placeholder="jsmith" required="" name="username" type="text" id="username" value="{{ old('username') }}">
|
||||
{!! $errors->first('username', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- password -->
|
||||
<div class="form-group col-lg-6{{ (Helper::checkIfRequired(\App\Models\User::class, 'password')) ? ' required' : '' }} {{ $errors->has('password') ? 'error' : '' }}">
|
||||
<label for="password">{{ trans('admin/users/table.password') }}</label>
|
||||
<input class="form-control" type="password" name="password" id="password" value="" required>
|
||||
{!! $errors->first('password', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
|
||||
<!-- password confirm -->
|
||||
<div class="form-group col-lg-6{{ (Helper::checkIfRequired(\App\Models\User::class, 'password')) ? ' required' : '' }} {{ $errors->has('password_confirm') ? 'error' : '' }}">
|
||||
<label for="password_confirmation">{{ trans('admin/users/table.password_confirm') }}</label>
|
||||
<input class="form-control" type="password" name="password_confirmation" id="password_confirmation" value="" required>
|
||||
{!! $errors->first('password_confirmation', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Email credentials -->
|
||||
<div class="form-group col-lg-12">
|
||||
<label class="form-control form-control">
|
||||
<input type="checkbox" value="1" name="email_creds">{{ trans('admin/users/general.email_credentials_text') }}
|
||||
</label>
|
||||
</div>
|
||||
</div> <!--/.COL-LG-12-->
|
||||
@stop
|
||||
|
||||
@section('button')
|
||||
<button class="btn btn-primary">{{ trans('admin/users/general.next_save_user') }}</button>
|
||||
<button class="btn btn-primary">
|
||||
{{ trans('general.setup_next') }}: {{ trans('admin/settings/general.setup_migration_create_user') }}
|
||||
<i class="fa-solid fa-angles-right"></i>
|
||||
</button>
|
||||
</form>
|
||||
@parent
|
||||
@stop
|
||||
|
||||
@ -24,6 +24,7 @@ use App\Http\Controllers\ProfileController;
|
||||
use App\Http\Controllers\ReportTemplatesController;
|
||||
use App\Http\Controllers\ReportsController;
|
||||
use App\Http\Controllers\SettingsController;
|
||||
use App\Http\Controllers\SetupController;
|
||||
use App\Http\Controllers\StatuslabelsController;
|
||||
use App\Http\Controllers\SuppliersController;
|
||||
use App\Http\Controllers\ViewAssetsController;
|
||||
@ -48,7 +49,7 @@ Route::group(['middleware' => 'auth'], function () {
|
||||
]);
|
||||
|
||||
Route::post('categories/bulk/delete', [BulkCategoriesController::class, 'destroy'])->name('categories.bulk.delete');
|
||||
|
||||
|
||||
/*
|
||||
* Labels
|
||||
*/
|
||||
@ -285,15 +286,15 @@ Route::group(['prefix' => 'admin', 'middleware' => ['auth', 'authorize:superuser
|
||||
Route::delete('delete/{filename}',
|
||||
[SettingsController::class, 'deleteFile'])->name('settings.backups.destroy');
|
||||
|
||||
Route::post('/',
|
||||
Route::post('/',
|
||||
[SettingsController::class, 'postBackups']
|
||||
)->name('settings.backups.create');
|
||||
|
||||
Route::post('/restore/{filename}',
|
||||
Route::post('/restore/{filename}',
|
||||
[SettingsController::class, 'postRestore']
|
||||
)->name('settings.backups.restore');
|
||||
|
||||
Route::post('/upload',
|
||||
Route::post('/upload',
|
||||
[SettingsController::class, 'postUploadBackup']
|
||||
)->name('settings.backups.upload');
|
||||
|
||||
@ -415,7 +416,7 @@ Route::group(['prefix' => 'account', 'middleware' => ['auth']], function () {
|
||||
'display-sig/{filename}',
|
||||
[ProfileController::class, 'displaySig']
|
||||
)->name('profile.signature.view');
|
||||
|
||||
|
||||
Route::get(
|
||||
'stored-eula-file/{filename}',
|
||||
[ProfileController::class, 'getStoredEula']
|
||||
@ -604,23 +605,24 @@ Route::get(
|
||||
Route::group(['prefix' => 'setup', 'middleware' => 'web'], function () {
|
||||
Route::get(
|
||||
'user',
|
||||
[SettingsController::class, 'getSetupUser']
|
||||
[SetupController::class, 'getSetupUser']
|
||||
)->name('setup.user');
|
||||
|
||||
Route::post(
|
||||
'user',
|
||||
[SettingsController::class, 'postSaveFirstAdmin']
|
||||
[SetupController::class, 'postSaveFirstAdmin']
|
||||
)->name('setup.user.save');
|
||||
|
||||
|
||||
Route::get(
|
||||
Route::post(
|
||||
'migrate',
|
||||
[SettingsController::class, 'getSetupMigrate']
|
||||
[SetupController::class, 'SetupMigrate']
|
||||
)->name('setup.migrate');
|
||||
|
||||
|
||||
Route::get(
|
||||
'done',
|
||||
[SettingsController::class, 'getSetupDone']
|
||||
[SetupController::class, 'getSetupDone']
|
||||
)->name('setup.done');
|
||||
|
||||
Route::get(
|
||||
@ -630,7 +632,7 @@ Route::group(['prefix' => 'setup', 'middleware' => 'web'], function () {
|
||||
|
||||
Route::get(
|
||||
'/',
|
||||
[SettingsController::class, 'getSetupIndex']
|
||||
[SetupController::class, 'getSetupIndex']
|
||||
)->name('setup');
|
||||
});
|
||||
|
||||
|
||||
85
tests/Feature/Setup/Ui/IndexSetupTest.php
Normal file
85
tests/Feature/Setup/Ui/IndexSetupTest.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Setup\Ui;
|
||||
|
||||
use App\Models\User;
|
||||
use Tests\TestCase;
|
||||
|
||||
class IndexSetupTest extends TestCase
|
||||
{
|
||||
public function testPageRenders()
|
||||
{
|
||||
$this->get(route('setup'))
|
||||
->assertOk();
|
||||
}
|
||||
|
||||
public function testPageRedirectsIfNoRecordsFound()
|
||||
{
|
||||
$this->assertDatabaseEmpty('users');
|
||||
|
||||
$this->get(route('home'))
|
||||
->assertStatus(302)
|
||||
->assertRedirectToRoute('setup');
|
||||
}
|
||||
|
||||
public function testPageRedirectsIfRecordsFound() {
|
||||
$this->actingAs(User::factory()->superuser()->create())
|
||||
->get(route('setup'))
|
||||
->assertStatus(302)
|
||||
->assertRedirectToRoute('home');
|
||||
}
|
||||
|
||||
public function testMigrationPageRenders() {
|
||||
|
||||
$this->assertDatabaseEmpty('users');
|
||||
|
||||
$this->post(route('setup.migrate'))
|
||||
->assertOk();
|
||||
|
||||
}
|
||||
|
||||
public function testCreateFirstUserPageRenders() {
|
||||
|
||||
$this->assertDatabaseEmpty('users');
|
||||
|
||||
$this->get(route('setup.user'))
|
||||
->assertOk();
|
||||
|
||||
}
|
||||
|
||||
public function testCreateFirstUserValidation() {
|
||||
|
||||
$this->assertDatabaseEmpty('users');
|
||||
|
||||
$response = $this->post(route('setup.user.save'))
|
||||
->assertStatus(302);
|
||||
|
||||
$this->followRedirects($response)->assertSee('error');
|
||||
$this->assertDatabaseCount('users', 0);
|
||||
|
||||
}
|
||||
|
||||
public function testCreateFirstUserSaved() {
|
||||
|
||||
$this->assertDatabaseEmpty('users');
|
||||
|
||||
$this->post(route('setup.user.save'),
|
||||
[
|
||||
'site_name' => 'Snipe-IT',
|
||||
'first_name' => 'First',
|
||||
'last_name' => 'Admin',
|
||||
'username' => 'AwesomeAdmin',
|
||||
'password' => '0834529!!*423',
|
||||
'password_confirmation' => '0834529!!*423',
|
||||
'email_domain' => 'example.org',
|
||||
])
|
||||
->assertRedirectToRoute('setup.done')
|
||||
->assertStatus(302)
|
||||
->assertSessionHas('success');
|
||||
|
||||
|
||||
|
||||
$this->assertDatabaseCount('users', 1);
|
||||
|
||||
}
|
||||
}
|
||||
@ -19,7 +19,7 @@ class Settings
|
||||
return new self();
|
||||
}
|
||||
|
||||
public function enableAlertEmail(string $email = 'notifications@afcrichmond.com'): Settings
|
||||
public function enableAlertEmail(string $email = 'notifications@example.org'): Settings
|
||||
{
|
||||
return $this->update([
|
||||
'alert_email' => $email,
|
||||
@ -46,7 +46,7 @@ class Settings
|
||||
]);
|
||||
}
|
||||
|
||||
public function enableAdminCC(string $email = 'cc@example.co'): Settings
|
||||
public function enableAdminCC(string $email = 'cc@example.org'): Settings
|
||||
{
|
||||
return $this->update([
|
||||
'admin_cc_email' => $email,
|
||||
|
||||
Reference in New Issue
Block a user