Файловый менеджер - Редактировать - /home/c7lekhnath/silverray.com.au/Modules/Language/database/seeders/68334/Installer.tar
Назад
lang/.gitkeep 0000644 00000000000 15012233070 0007075 0 ustar 00 lang/en/setup.php 0000644 00000001467 15012233070 0007741 0 ustar 00 <?php /** * This Language configs are used when running the setup wizard */ return [ 'php_version' => 'PHP version >= 8.1.0', 'extension_bcmath' => 'PHP Extension: BCMath', 'extension_ctype' => 'PHP Extension: Ctype', 'extension_json' => 'PHP Extension: JSON', 'extension_mbstring' => 'PHP Extension: Mbstring', 'extension_openssl' => 'PHP Extension: OpenSSL', 'extension_pdo_mysql' => 'PHP Extension: PDO', 'extension_tokenizer' => 'PHP Extension: Tokenizer', 'extension_xml' => 'PHP Extension: XML', 'extension_zip' => 'PHP Extension: ZIP', 'extension_php_intl' => 'PHP Extension: INTL', 'env_writable' => '.env file is present and writable', 'storage_writable' => '/storage and /storage/logs directories are writable', 'setup_database' => 'Setup Database', ]; module.json 0000644 00000000346 15012233070 0006720 0 ustar 00 { "name": "Installer", "alias": "installer", "description": "", "keywords": [], "priority": 0, "providers": [ "Modules\\Installer\\app\\Providers\\InstallerServiceProvider" ], "files": [] } tests/Unit/.gitkeep 0000644 00000000000 15012233070 0010235 0 ustar 00 tests/Feature/.gitkeep 0000644 00000000000 15012233070 0010711 0 ustar 00 vite.config.js 0000644 00000001310 15012233070 0007301 0 ustar 00 import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; export default defineConfig({ build: { outDir: '../../public/build-installer', emptyOutDir: true, manifest: true, }, plugins: [ laravel({ publicDirectory: '../../public', buildDirectory: 'build-installer', input: [ __dirname + '/resources/assets/sass/app.scss', __dirname + '/resources/assets/js/app.js' ], refresh: true, }), ], }); //export const paths = [ // 'Modules/$STUDLY_NAME$/resources/assets/sass/app.scss', // 'Modules/$STUDLY_NAME$/resources/assets/js/app.js', //]; wsus.json 0000644 00000000625 15012233070 0006434 0 ustar 00 { "name": "Installer Addon", "is_default": true, "description": "This is Installer Addon", "author": { "name": "Websolutionsus", "email": "websolutionus1@gmail.com", "website": "https://websolutionus.com" }, "license": "Proprietary", "url": "", "options" : { "route" : "home" }, "last_update": "2024-03-31", "version": "1.0.0" } routes/.gitkeep 0000644 00000000000 15012233070 0007475 0 ustar 00 routes/error_log 0000644 00000001112 15012233070 0007766 0 ustar 00 [07-May-2025 00:06:37 UTC] PHP Fatal error: Uncaught Error: Class "Illuminate\Support\Facades\Route" not found in /home/lekhnath/silverray.com.au/Modules/Installer/routes/web.php:10 Stack trace: #0 {main} thrown in /home/lekhnath/silverray.com.au/Modules/Installer/routes/web.php on line 10 [07-May-2025 04:04:22 UTC] PHP Fatal error: Uncaught Error: Class "Illuminate\Support\Facades\Route" not found in /home/lekhnath/silverray.com.au/Modules/Installer/routes/api.php:5 Stack trace: #0 {main} thrown in /home/lekhnath/silverray.com.au/Modules/Installer/routes/api.php on line 5 routes/web.php 0000644 00000003524 15012233070 0007350 0 ustar 00 <?php use Illuminate\Support\Facades\Route; use Modules\Installer\app\Http\Controllers\InstallerController; use Modules\Installer\app\Http\Controllers\PuchaseVerificationController; use Modules\Installer\app\Http\Middleware\PurchaseVerifyMiddleware; use Modules\Installer\app\Http\Middleware\SetupMiddleware; //all setup route Route::prefix('setup')->withoutMiddleware(PurchaseVerifyMiddleware::class)->group(function () { Route::controller(PuchaseVerificationController::class)->group(function () { Route::get('verify', 'index')->name('setup.verify'); Route::post('verify', 'validatePurchase')->name('setup.checkParchase'); }); Route::controller(InstallerController::class)->withoutMiddleware('demo')->group(function () { Route::get('requirements', 'requirements')->name('setup.requirements'); Route::get('database', 'database')->name('setup.database'); Route::post('database-submit', 'databaseSubmit')->name('setup.database.submit'); Route::get('account', 'account')->name('setup.account'); Route::post('account-submit', 'accountSubmit')->name('setup.account.submit'); Route::get('configuration', 'configuration')->name('setup.configuration'); Route::post('configuration-submit', 'configurationSubmit')->name('setup.configuration.submit'); Route::get('smtp', [InstallerController::class, 'smtp'])->name('setup.smtp'); Route::post('smtp', [InstallerController::class, 'smtpSetup'])->name('setup.smtp.update'); Route::post('smtp/skip', [InstallerController::class, 'smtpSkip'])->name('setup.smtp.skip'); Route::get('complete', 'setupComplete')->name('setup.complete'); }); Route::get('lunch/{type}', [InstallerController::class, 'launchWebsite'])->name('website.completed')->withoutMiddleware('demo')->withoutMiddleware(SetupMiddleware::class); }); routes/api.php 0000644 00000000214 15012233070 0007335 0 ustar 00 <?php use Illuminate\Support\Facades\Route; Route::middleware(['auth:sanctum'])->prefix('v1')->name('api.')->group(function () { }); composer.json 0000644 00000001311 15012233070 0007253 0 ustar 00 { "name": "nwidart/installer", "description": "", "authors": [ { "name": "Nicolas Widart", "email": "n.widart@gmail.com" } ], "extra": { "laravel": { "providers": [], "aliases": { } } }, "autoload": { "psr-4": { "Modules\\Installer\\": "", "Modules\\Installer\\App\\": "app/", "Modules\\Installer\\Database\\Factories\\": "database/factories/", "Modules\\Installer\\Database\\Seeders\\": "database/seeders/" } }, "autoload-dev": { "psr-4": { "Modules\\Installer\\Tests\\": "tests/" } } } config/config.php 0000644 00000000056 15012233070 0007761 0 ustar 00 <?php return [ 'name' => 'Installer', ]; config/.gitkeep 0000644 00000000000 15012233070 0007421 0 ustar 00 package.json 0000644 00000000410 15012233070 0007016 0 ustar 00 { "private": true, "type": "module", "scripts": { "dev": "vite", "build": "vite build" }, "devDependencies": { "axios": "^1.1.2", "laravel-vite-plugin": "^0.7.5", "sass": "^1.69.5", "postcss": "^8.3.7", "vite": "^4.0.0" } } app/Http/Controllers/InstallerController.php 0000644 00000032453 15012233070 0015263 0 ustar 00 <?php namespace Modules\Installer\app\Http\Controllers; use Closure; use Exception; use App\Models\Admin; use App\Enums\UserStatus; use Illuminate\Http\Request; use Spatie\Permission\Models\Role; use Illuminate\Support\Facades\Log; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Cache; use Modules\GlobalSetting\app\Models\Setting; use Modules\Installer\app\Enums\InstallerInfo; use Modules\Installer\app\Models\Configuration; use Modules\Installer\app\Traits\InstallerMethods; class InstallerController extends Controller { use InstallerMethods; public function __construct() { set_time_limit(8000000); $this->middleware(function (Request $request, Closure $next) { $data = purchaseVerificationHashed(InstallerInfo::getLicenseFilePath()); if (isset($data) && isset($data['success']) && $data['success']) { return $next($request); } else { if (strtolower(config('app.app_mode')) == 'demo') { return $next($request); } } return redirect()->route('setup.verify')->withInput()->withErrors(['errors' => isset($data) && isset($data['success']) && $data['message'] ? $data['message'] : 'License key not found']); }); } public function requirements() { [$checks, $success, $failedChecks] = $this->checkMinimumRequirements(); if ( $step = Configuration::stepExists( ) && $success) { if($step == 5){ return redirect()->route( 'setup.complete' ); } return redirect()->route( 'setup.account' ); } session()->put( 'step-2-complete', true ); return view( 'installer::requirements', compact( 'checks', 'success', 'failedChecks' ) ); } public function database() { if ($this->requirementsCompleteStatus()) { session()->put( 'requirements-complete', true ); if (Configuration::stepExists()) { return redirect()->route('setup.account'); } changeEnvValues('DB_DATABASE', ''); return view('installer::database', ['isLocalHost' => InstallerInfo::isRemoteLocal()]); } return redirect()->route('setup.requirements')->withInput()->withErrors(['errors' => 'Your server does not meet the minimum requirements.']); } public function databaseSubmit(Request $request) { if (! $this->requirementsCompleteStatus()) { return redirect()->route('setup.requirements')->withInput()->withErrors(['errors' => 'Your server does not meet the minimum requirements.']); } try { $request->validate([ 'host' => 'required|ip', 'port' => 'required|integer', 'database' => 'required', 'user' => 'required', ]); if (! InstallerInfo::isRemoteLocal()) { $request->validate([ 'password' => 'required', ]); } $databaseCreate = $this->createDatabaseConnection($request->all()); if ($databaseCreate !== true) { if ($databaseCreate == 'not-found') { return response()->json(['create_database' => true, 'message' => 'Database not found! Please create the database first.'], 200); } elseif ($databaseCreate == 'table-exist') { return response()->json(['reset_database' => true, 'message' => 'This database has tables already. Please create a new database or reset existing tables first to continue'], 200); } else { return response()->json(['success' => false, 'message' => $databaseCreate], 200); } } $deleteDummyData = false; if ($request->has('fresh_install') && $request->filled('fresh_install') && $request->fresh_install == 'on') { $deleteDummyData = true; Cache::put('fresh_install', true, now()->addMinutes(60)); $migration = $this->importDatabase( InstallerInfo::getFreshDatabaseFilePath() ); }else{ $migration = $this->importDatabase( InstallerInfo::getDummyDatabaseFilePath() ); } if ($migration !== true) { return response()->json(['success' => false, 'message' => $migration], 200); } $this->changeEnvDatabaseConfig($request->except('reset_database')); if ($migration == true && $deleteDummyData) { $this->removeDummyFiles(); } Cache::forget('fresh_install'); session()->put('step-3-complete', true); return response()->json(['success' => true, 'message' => 'Successfully setup the database'], 200); } catch (Exception $e) { Log::error($e->getMessage()); return response()->json(['success' => false, 'message' => 'Database connection failed! Look like you have entered wrong database credentials (host, port, database, user or password).'], 200); } } public function account() { $step = Configuration::stepExists(); if ( $step >= 1 && $step < 5 && $this->requirementsCompleteStatus()) { $admin = $step >= 2 ? Admin::select('name','email')->first() : null; return view( 'installer::account',compact('admin') ); } if($step == 5 || !$this->requirementsCompleteStatus()){ return redirect()->route( 'setup.requirements' ); } return redirect()->route( 'setup.database' ); } public function accountSubmit(Request $request) { try { $request->validate([ 'name' => 'required', 'email' => 'required|email', 'password' => 'required|same:confirm_password', ]); $role = Role::first(); if (! Admin::first()) { $admin = new Admin(); $admin->name = $request->name; $admin->email = $request->email; $admin->image = 'uploads/website-images/admin.jpg'; $admin->password = Hash::make($request->password); $admin->status = UserStatus::ACTIVE->value; $admin->save(); } else { $admin = Admin::first(); $admin->name = $request->name; $admin->email = $request->email; $admin->image = 'uploads/website-images/admin.jpg'; $admin->password = Hash::make($request->password); $admin->status = UserStatus::ACTIVE->value; $admin->save(); } $admin?->assignRole($role); Configuration::updateStep(2); session()->put('step-4-complete', true); return response()->json(['success' => true, 'message' => 'Admin Account Successfully Created'], 200); } catch (Exception $e) { Log::error($e); return response()->json(['success' => false, 'message' => 'Failed to Create Admin Account'], 200); } } public function configuration() { $step = Configuration::stepExists(); if($step == 5 || !$this->requirementsCompleteStatus()){ return redirect()->route( 'setup.requirements' ); } if ( $step < 2 ) { return redirect()->route( 'setup.account' ); } $app_name = $step >= 3 ? Setting::where('key', 'app_name')->first()->value : null; return view( 'installer::config',compact('app_name') ); } public function configurationSubmit(Request $request) { try { $request->validate([ 'config_app_name' => 'required|string', ]); Configuration::updateStep(3); Setting::where('key', 'app_name')->update(['value' => $request->config_app_name]); if (Cache::has('last_updated_at')) { Setting::where('key', 'last_update_date')->update(['value' => Cache::get('last_updated_at')]); Cache::forget('last_updated_at'); } Cache::forget('setting'); session()->put('step-5-complete', true); return response()->json(['success' => true, 'message' => 'Configuration Successfully Saved'], 200); } catch (Exception $e) { Log::error($e); return response()->json(['success' => false, 'message' => 'Configuration Failed'], 200); } } public function smtp() { $step = Configuration::stepExists(); if($step == 5 || !$this->requirementsCompleteStatus()){ return redirect()->route( 'setup.requirements' ); } if ( $step < 3 ) { return redirect()->route( 'setup.configuration' ); } $email = null; $setting_info = Cache::get('setting'); if($step >= 4 && ($setting_info->mail_username != 'mail_username' && $setting_info->mail_password != 'mail_password')){ $email = []; $email['mail_host'] = $setting_info->mail_host; $email['email'] = $setting_info->mail_sender_email; $email['smtp_username'] = $setting_info->mail_username; $email['smtp_password'] = $setting_info->mail_password; $email['mail_port'] = $setting_info->mail_port; $email['mail_encryption'] = $setting_info->mail_encryption; $email['mail_sender_name'] = $setting_info->mail_sender_name; $email = (object) $email; } return view( 'installer::smtp',compact('email') ); } public function smtpSetup( Request $request ) { try { $rules = [ 'mail_host' => 'required', 'email' => 'required', 'smtp_username' => 'required', 'smtp_password' => 'required', 'mail_port' => 'required', 'mail_encryption' => 'required', 'mail_sender_name' => 'required', ]; $customMessages = [ 'mail_host.required' => 'Mail host is required', 'email.required' => 'Email is required', 'smtp_username.required' => 'Smtp username is required', 'smtp_password.unique' => 'Smtp password is required', 'mail_port.required' => 'Mail port is required', 'mail_encryption.required' => 'Mail encryption is required', 'mail_sender_name.required' => 'Mail Sender Name is required', ]; $this->validate( $request, $rules, $customMessages ); Setting::where('key', 'mail_host')->update(['value' => $request->mail_host]); Setting::where('key', 'mail_sender_email')->update(['value' => $request->email]); Setting::where('key', 'mail_username')->update(['value' => $request->smtp_username]); Setting::where('key', 'mail_password')->update(['value' => $request->smtp_password]); Setting::where('key', 'mail_port')->update(['value' => $request->mail_port]); Setting::where('key', 'mail_encryption')->update(['value' => $request->mail_encryption]); Setting::where('key', 'mail_sender_name')->update(['value' => $request->mail_sender_name]); Configuration::updateStep( 4 ); session()->put( 'step-6-complete', true ); Cache::forget('setting'); return response()->json( ['success' => true, 'message' => 'Successfully setup mail SMTP'], 200 ); } catch ( Exception $e ) { Log::error($e->getMessage()); return response()->json( ['success' => false, 'message' => 'Failed to Setup SMTP'], 200 ); } } public function smtpSkip( ) { Configuration::updateStep( 4 ); session()->put( 'step-6-complete', true ); return redirect()->route( 'setup.complete' ); } public function setupComplete() { session()->put( 'step-7-complete', true ); if ( Configuration::setupStepCheck( 4 ) && $this->requirementsCompleteStatus() ) { $envContent = File::get( base_path( '.env' ) ); $envContent = preg_replace( ['/APP_ENV=(.*)\s/','/APP_DEBUG=(.*)\s/',], ['APP_ENV=' . 'production' . "\n",'APP_DEBUG=' . 'false' . "\n",], $envContent ); if ( $envContent !== null ) { File::put( base_path( '.env' ), $envContent ); } return view( 'installer::complete' ); } if ( Configuration::setupStepCheck( 5 ) && $this->requirementsCompleteStatus() ) { return $this->completedSetup( 'home' ); } if ( Configuration::stepExists() < 4 ) { return redirect()->route( 'setup.smtp' ); } return redirect()->back()->withInput()->withErrors( ['errors' => 'Setup Is Incomplete hh'] ); } public function launchWebsite( $type ) { if ( Configuration::setupStepCheck( 4 ) ) { Configuration::updateStep( 5 ); return $this->completedSetup( $type ); } elseif ( Configuration::setupStepCheck( 5 ) ) { return $this->completedSetup( $type ); } return redirect()->back()->withInput()->withErrors( ['errors' => 'Setup Is Incomplete'] ); } } app/Http/Controllers/.gitkeep 0000644 00000000000 15012233070 0012161 0 ustar 00 app/Http/Controllers/PuchaseVerificationController.php 0000644 00000003217 15012233070 0017255 0 ustar 00 <?php namespace Modules\Installer\app\Http\Controllers; use App\Http\Controllers\Controller; use Exception; use Illuminate\Http\Request; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; use Modules\Installer\app\Enums\InstallerInfo; class PuchaseVerificationController extends Controller { public function __construct() { set_time_limit(8000000); } public function index() { return view('installer::index'); } public function validatePurchase(Request $request) { session()->flush(); $request->validate([ 'purchase_code' => 'required|string', ]); try { $response = Http::post(InstallerInfo::VERIFICATION_URL->value, [ 'purchase_code' => $request->purchase_code, 'item_id' => InstallerInfo::ITEM_ID->value, 'incoming_url' => InstallerInfo::getHost(), 'incoming_ip' => InstallerInfo::getRemoteAddr(), ])->json(); session()->put('step-1-complete', true); if (InstallerInfo::rewriteHashedFile($response, $request->purchase_code)) { return response()->json(['success' => true, 'message' => $response['message']], 200); } return response()->json(['success' => false, 'message' => (is_array($response) && array_key_exists('message', $response)) && $response['message'] ? $response['message'] : 'Verification Failed'], 200); } catch (Exception $e) { Log::error($e->getMessage()); return response()->json(['success' => false, 'message' => 'Server Error'], 200); } } } app/Http/Requests/.gitkeep 0000644 00000000000 15012233070 0011466 0 ustar 00 app/Http/Middleware/.gitkeep 0000644 00000000000 15012233070 0011730 0 ustar 00 app/Http/Middleware/SetupMiddleware.php 0000644 00000001404 15012233070 0014117 0 ustar 00 <?php namespace Modules\Installer\app\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Artisan; class SetupMiddleware { /** * Handle an incoming request. */ public function handle(Request $request, Closure $next) { if (empty(config('app.key'))) { Artisan::call('key:generate'); Artisan::call('config:cache'); } $setupStatus = setupStatus(); if ($request->is('setup/*')) { if ($setupStatus) { return redirect()->route('home'); } return $next($request); } if (! $setupStatus) { return redirect()->route('setup.verify'); } return $next($request); } } app/Http/Middleware/PurchaseVerifyMiddleware.php 0000644 00000003513 15012233070 0015761 0 ustar 00 <?php namespace Modules\Installer\app\Http\Middleware; use Carbon\Carbon; use Closure; use Exception; use Illuminate\Http\Request; use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Session; use Modules\Installer\app\Enums\InstallerInfo; use Modules\Installer\app\Models\Configuration; class PurchaseVerifyMiddleware { /** * Handle an incoming request. */ public function handle(Request $request, Closure $next) { if (strtolower(config('app.app_mode')) == 'demo') { return $next($request); } if (InstallerInfo::licenseFileExist()) { $filepath = InstallerInfo::getLicenseFilePath(); if (! InstallerInfo::isRemoteLocal() && InstallerInfo::licenseFileDataHasLocalTrue()) { $response = purchaseVerificationHashed($filepath, true); if ($response && InstallerInfo::rewriteHashedFile($response)) { return $next($request); } else { InstallerInfo::deleteLicenseFile(); return $this->invalidHashed(); } } elseif (Carbon::now()->day == 1) { $response = purchaseVerificationHashed($filepath); if ($response && $response['success']) { return $next($request); } return $this->invalidHashed(); } return $next($request); } return $this->invalidHashed(); } private function invalidHashed() { try { Configuration::updateCompeteStatus(0); } catch (Exception $e) { Log::error($e->getMessage()); } Session::flush(); Artisan::call('cache:clear'); return redirect()->route('setup.verify'); } } app/Models/Configuration.php 0000644 00000003353 15012233070 0012064 0 ustar 00 <?php namespace Modules\Installer\app\Models; use Exception; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Log; class Configuration extends Model { use HasFactory; public $fillable = [ 'config', 'value', ]; public static function setupStepCheck($step) { try { $data = Configuration::where('config', 'setup_stage')->first(); if ($step == $data['value']) { return true; } return false; } catch (Exception $e) { Log::error($e->getMessage()); return false; } } public static function stepExists() { try { if ($data = Configuration::where('config', 'setup_stage')->first()) { return $data['value']; } return false; } catch (Exception $e) { Log::error($e->getMessage()); return false; } } public static function updateStep($step) { try { if (Configuration::where('config', 'setup_stage')->firstOrFail()->update(['value' => $step])) { return true; } return false; } catch (Exception $e) { Log::error($e->getMessage()); return false; } } public static function updateCompeteStatus($step) { try { if (Configuration::where('config', 'setup_complete')->firstOrFail()->update(['value' => $step])) { return true; } return false; } catch (Exception $e) { Log::error($e->getMessage()); return false; } } } app/Models/.gitkeep 0000644 00000000000 15012233070 0010157 0 ustar 00 app/Traits/InstallerMethods.php 0000644 00000021737 15012233070 0012567 0 ustar 00 <?php namespace Modules\Installer\app\Traits; use Exception; use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Session; use Modules\Installer\app\Models\Configuration; trait InstallerMethods { private function checkMinimumRequirements(): array { $checks = [ // Base requirements 'php_version' => [ 'check' => PHP_VERSION_ID >= 80100, 'message' => 'PHP version 8.1.0 or higher is required. Current version: '.PHP_VERSION, 'url' => 'https://www.php.net/releases/8.1/en.php', ], 'extension_bcmath' => [ 'check' => extension_loaded('bcmath'), 'message' => 'The "bcmath" extension is required.', 'url' => 'https://www.php.net/manual/en/book.bc.php', ], 'extension_ctype' => [ 'check' => extension_loaded('ctype'), 'message' => 'The "ctype" extension is required.', 'url' => 'https://www.php.net/manual/en/book.ctype.php', ], 'extension_json' => [ 'check' => extension_loaded('json'), 'message' => 'The "json" extension is required.', 'url' => 'https://www.php.net/manual/en/book.json.php', ], 'extension_mbstring' => [ 'check' => extension_loaded('mbstring'), 'message' => 'The "mbstring" extension is required.', 'url' => 'https://www.php.net/manual/en/book.mbstring.php', ], 'extension_openssl' => [ 'check' => extension_loaded('openssl'), 'message' => 'The "openssl" extension is required.', 'url' => 'https://www.php.net/manual/en/book.openssl.php', ], 'extension_pdo_mysql' => [ 'check' => extension_loaded('pdo_mysql'), 'message' => 'The "pdo_mysql" extension is required for MySQL database access.', 'url' => 'https://www.php.net/manual/en/ref.pdo-mysql.php', ], 'extension_tokenizer' => [ 'check' => extension_loaded('tokenizer'), 'message' => 'The "tokenizer" extension is required.', 'url' => 'https://www.php.net/manual/en/book.tokenizer.php', ], 'extension_xml' => [ 'check' => extension_loaded('xml'), 'message' => 'The "xml" extension is required.', 'url' => 'https://www.php.net/manual/en/book.simplexml.php', ], 'extension_zip' => [ 'check' => extension_loaded('zip'), 'message' => 'The "zip" extension is required.', 'url' => 'https://www.php.net/manual/en/book.zip.php', ], 'extension_php_intl' => [ 'check' => extension_loaded('intl'), 'message' => 'The "intl" extension is recommended for localization features.', 'url' => 'https://www.php.net/manual/en/book.intl.php', ], // File and directory permissions 'env_writable' => [ 'check' => File::isWritable(base_path('.env')), 'message' => 'The ".env" file must be writable.', ], 'storage_writable' => [ 'check' => File::isWritable(storage_path()) && File::isWritable(storage_path('logs')), 'message' => 'The "storage" and "storage/logs" directories must be writable.', ], ]; $failedChecks = []; foreach ($checks as $name => $check) { if (! $check['check']) { $failedChecks[$name] = [ 'message' => $check['message'], 'url' => isset($check['url']) ? $check['url'] : null, ]; } } $success = empty($failedChecks); return [$checks, $success, $failedChecks]; } private function requirementsCompleteStatus() { $success = $this->checkMinimumRequirements(); return $success[1]; } private function createDatabaseConnection($details) { try { Artisan::call('config:clear'); $defaultConnectionName = config('database.default'); Config::set("database.connections.$defaultConnectionName.host", $details['host']); Config::set("database.connections.$defaultConnectionName.port", $details['port']); Config::set("database.connections.$defaultConnectionName.database", null); Config::set("database.connections.$defaultConnectionName.username", $details['user']); Config::set("database.connections.$defaultConnectionName.password", $details['password']); $customDatabase = $details['database']; DB::reconnect($defaultConnectionName); $databaseExists = DB::connection()->select('SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?', [$customDatabase]); DB::purge($defaultConnectionName); if (empty($databaseExists)) { Config::set("database.connections.$defaultConnectionName.database", $customDatabase); DB::reconnect(); return 'not-found'; } Config::set("database.connections.$defaultConnectionName.database", $customDatabase); DB::reconnect(); if ( count( Schema::getAllTables() ) > 0 ) { if ( !empty( $details['reset_database'] ) && $details['reset_database'] == 'on' ) { Schema::dropAllTables(); return true; } return 'table-exist'; } return true; } catch (Exception $e) { Log::error($e); return 'Database connection failed! Look like you have entered wrong database credentials (host, port, database, user or password).'; } } private function runDatabaseMigration() { try { Artisan::call('migrate:fresh', [ '--force' => 'true', '--no-interaction' => true, '--seed' => true, ]); return true; } catch (Exception $e) { Log::error($e); return 'Migration failed! Something went wrong'; } } private function importDatabase( $database_path ) { if ( File::exists( $database_path ) ) { try { DB::unprepared( File::get( $database_path ) ); return true; } catch ( Exception $e ) { info( $e->getMessage() ); return 'Migration failed! Something went wrong'; } } else { return 'Something went wrong'; } } private function changeEnvDatabaseConfig($config) { $envContent = File::get( base_path( '.env' ) ); $lineBreak = "\n"; $envContent = preg_replace( [ '/DB_HOST=(.*)\s/', '/DB_PORT=(.*)\s/', '/DB_DATABASE=(.*)\s/', '/DB_USERNAME=(.*)\s/', '/DB_PASSWORD=(.*)\s/', ], [ 'DB_HOST=' . $config['host'] . $lineBreak, 'DB_PORT=' . $config['port'] . $lineBreak, 'DB_DATABASE=' . $config['database'] . $lineBreak, 'DB_USERNAME=' . $config['user'] . $lineBreak, 'DB_PASSWORD="' . $config['password'] . '"' . $lineBreak, ], $envContent ); if ( $envContent !== null ) { File::put( base_path( '.env' ), $envContent ); } } private function completedSetup($type) { Configuration::updateCompeteStatus(1); Session::flush(); Artisan::call('cache:clear'); if ($type == 'admin') { return redirect()->route('admin.login'); } else { return redirect()->route('home'); } } private function removeDummyFiles() { $dummyFolders = [ public_path('website/images/agent'), public_path('website/images/blog'), public_path('website/images/category'), public_path('website/images/city'), public_path('website/images/client'), public_path('website/images/details_slider'), public_path('website/images/listing'), ]; foreach ($dummyFolders as $folderPath) { $this->deleteFolderAndFiles($folderPath); } } private function deleteFolderAndFiles($folderPath) { if (file_exists($folderPath)) { $files = glob($folderPath.'/*'); foreach ($files as $file) { if (is_file($file)) { unlink($file); } } rmdir($folderPath); return true; } } } app/Enums/InstallerInfo.php 0000644 00000011406 15012233070 0011670 0 ustar 00 <?php namespace Modules\Installer\app\Enums; use Exception; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Log; enum InstallerInfo: string { const DUMMY_DATABASE_PATH = 'database/backup/dummy_database.sql'; const FRESH_DATABASE_PATH = 'database/backup/fresh_database.sql'; case LICENSE_FILE_PATH = 'app/license.json'; case VERIFICATION_URL = 'https://pcv.websolutionus.com/api/v1/validate'; case VERIFICATION_HASHED_URL = 'https://pcv.websolutionus.com/api/v1/validate/code'; case ITEM_ID = '36467538'; public static function getDummyDatabaseFilePath(): string { return base_path( self::DUMMY_DATABASE_PATH ); } public static function getFreshDatabaseFilePath(): string { return base_path( self::FRESH_DATABASE_PATH ); } public static function getLicenseFilePath(): string { return storage_path(self::LICENSE_FILE_PATH->value); } public static function getAllLocalIp(): array { return [ 'localhost', '127.0.0.1', '::1', '0:0:0:0:0:0:0:1', '::ffff:127.0.0.1', '0:0:0:0:0:0:127.0.0.1', '0.0.0.0', ]; } public static function isLocal($value): bool { return in_array($value, self::getAllLocalIp()); } public static function isRemoteLocal(): bool { return self::isLocal(self::getRemoteAddr()); } public static function getHost(): string { return parse_url(request()->root())['host']; } public static function getRemoteAddr(): string { return request()->server('REMOTE_ADDR'); } public static function licenseFileExist(): bool { return File::exists(self::getLicenseFilePath()); } public static function hasLocalInLicense(): bool { return self::isLocal(self::getHost()); } public static function getLicenseFileData($isJson = true): mixed { if (self::licenseFileExist()) { if ($isJson) { return json_decode(file_get_contents(self::getLicenseFilePath()), true); } return file_get_contents(self::getLicenseFilePath()); } return null; } public static function licenseFileDataHasLocalTrue(): bool { if ($data = self::getLicenseFileData() && ! is_null(self::getLicenseFileData())) { return isset($data['isLocal']) && ($data['isLocal'] == true) ? true : false; } return false; } public static function deleteLicenseFile(): void { if (self::licenseFileExist()) { File::delete(self::getLicenseFilePath()); } } public static function rewriteHashedFile($response, $purchaseCode = null): bool { if (is_array($response) && isset($response['last_updated_at']) && ! is_null($response['last_updated_at'])) { Cache::put('last_updated_at', $response['last_updated_at']); } if (is_array($response) && array_key_exists('success', $response) && $response['success'] && array_key_exists('isLocal', $response) && $response['isLocal'] == 'false') { try { file_put_contents(self::getLicenseFilePath(), json_encode(['verification_hashed' => $response['newHash']], JSON_PRETTY_PRINT)); return true; } catch (Exception $e) { Log::error($e->getMessage()); return false; } } elseif (is_array($response) && array_key_exists('success', $response) && $response['success']) { try { $data = []; if (! is_null($purchaseCode) && InstallerInfo::isRemoteLocal()) { $data['isLocal'] = true; $data['purchase_code'] = $purchaseCode; } $data['verification_hashed'] = $response['verification_hashed']; file_put_contents(InstallerInfo::getLicenseFilePath(), json_encode($data, JSON_PRETTY_PRINT)); return true; } catch (Exception $e) { Log::error($e->getMessage()); return false; } } return false; } public static function writeAssetUrl(): bool { try { $plainUrl = url('/'); $assetUrl = self::isRemoteLocal() ? $plainUrl : url('/public'); if (config('app.asset_url') !== $assetUrl) { changeEnvValues('ASSET_URL', $assetUrl); } if (config('app.url') !== $plainUrl) { changeEnvValues('APP_URL', $plainUrl); } return true; } catch (Exception $ex) { Log::error($ex->getMessage()); return false; } } } app/Providers/RouteServiceProvider.php 0000644 00000002673 15012233070 0014145 0 ustar 00 <?php namespace Modules\Installer\app\Providers; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Route; class RouteServiceProvider extends ServiceProvider { /** * The module namespace to assume when generating URLs to actions. */ protected string $moduleNamespace = 'Modules\Installer\app\Http\Controllers'; /** * Called before routes are registered. * * Register any model bindings or pattern based filters. */ public function boot(): void { parent::boot(); } /** * Define the routes for the application. */ public function map(): void { $this->mapApiRoutes(); $this->mapWebRoutes(); } /** * Define the "web" routes for the application. * * These routes all receive session state, CSRF protection, etc. */ protected function mapWebRoutes(): void { Route::middleware('web') ->namespace($this->moduleNamespace) ->group(module_path('Installer', '/routes/web.php')); } /** * Define the "api" routes for the application. * * These routes are typically stateless. */ protected function mapApiRoutes(): void { Route::prefix('api') ->middleware('api') ->namespace($this->moduleNamespace) ->group(module_path('Installer', '/routes/api.php')); } } app/Providers/InstallerServiceProvider.php 0000644 00000007310 15012233070 0014775 0 ustar 00 <?php namespace Modules\Installer\app\Providers; use Illuminate\Support\Facades\Blade; use Illuminate\Support\ServiceProvider; use Illuminate\Routing\Router; use Modules\Installer\app\Http\Middleware\PurchaseVerifyMiddleware; use Modules\Installer\app\Http\Middleware\SetupMiddleware; class InstallerServiceProvider extends ServiceProvider { protected string $moduleName = 'Installer'; protected string $moduleNameLower = 'installer'; /** * Boot the application events. */ public function boot(): void { $this->registerCommands(); $this->registerCommandSchedules(); $this->registerTranslations(); $this->registerConfig(); $this->registerViews(); $this->loadMigrationsFrom(module_path($this->moduleName, 'database/migrations')); // register installer middleware globally $router = $this->app->make(Router::class); $router->prependMiddlewareToGroup('web', PurchaseVerifyMiddleware::class); $router->pushMiddlewareToGroup('web', SetupMiddleware::class); } /** * Register the service provider. */ public function register(): void { $this->app->register(RouteServiceProvider::class); } /** * Register commands in the format of Command::class */ protected function registerCommands(): void { // $this->commands([]); } /** * Register command Schedules. */ protected function registerCommandSchedules(): void { // $this->app->booted(function () { // $schedule = $this->app->make(Schedule::class); // $schedule->command('inspire')->hourly(); // }); } /** * Register translations. */ public function registerTranslations(): void { $langPath = resource_path('lang/modules/'.$this->moduleNameLower); if (is_dir($langPath)) { $this->loadTranslationsFrom($langPath, $this->moduleNameLower); $this->loadJsonTranslationsFrom($langPath); } else { $this->loadTranslationsFrom(module_path($this->moduleName, 'lang'), $this->moduleNameLower); $this->loadJsonTranslationsFrom(module_path($this->moduleName, 'lang')); } } /** * Register config. */ protected function registerConfig(): void { $this->publishes([module_path($this->moduleName, 'config/config.php') => config_path($this->moduleNameLower.'.php')], 'config'); $this->mergeConfigFrom(module_path($this->moduleName, 'config/config.php'), $this->moduleNameLower); } /** * Register views. */ public function registerViews(): void { $viewPath = resource_path('views/modules/'.$this->moduleNameLower); $sourcePath = module_path($this->moduleName, 'resources/views'); $this->publishes([$sourcePath => $viewPath], ['views', $this->moduleNameLower.'-module-views']); $this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower); $componentNamespace = str_replace('/', '\\', config('modules.namespace').'\\'.$this->moduleName.'\\'.config('modules.paths.generator.component-class.path')); Blade::componentNamespace($componentNamespace, $this->moduleNameLower); } /** * Get the services provided by the provider. */ public function provides(): array { return []; } private function getPublishableViewPaths(): array { $paths = []; foreach (config('view.paths') as $path) { if (is_dir($path.'/modules/'.$this->moduleNameLower)) { $paths[] = $path.'/modules/'.$this->moduleNameLower; } } return $paths; } } app/Providers/.gitkeep 0000644 00000000000 15012233070 0010711 0 ustar 00 app/Helpers/helper.php 0000644 00000003730 15012233070 0010712 0 ustar 00 <?php use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; use Modules\Installer\app\Enums\InstallerInfo; use Modules\Installer\app\Models\Configuration; if (! function_exists('setup_complete_status')) { function setupStatus() { $cacheKey = 'setup_complete_status'; if (! Cache::has($cacheKey)) { try { Cache::rememberForever($cacheKey, function () { return Configuration::where('config', 'setup_complete')->first()?->value == 0 ? false : true; }); } catch (Exception $e) { Log::error($e->getMessage()); Cache::rememberForever($cacheKey, function () { return false; }); } } return Cache::get($cacheKey); } } if (! function_exists('purchaseVerificationHashed')) { function purchaseVerificationHashed($filepath, $isLocal = false) { if (file_exists($filepath)) { $licenseFile = InstallerInfo::getLicenseFileData(); $data = []; if ($isLocal) { $data['isLocal'] = InstallerInfo::licenseFileDataHasLocalTrue() ? 'false' : 'true'; $data['purchase_code'] = $licenseFile['purchase_code']; } $data['verification_hashed'] = $licenseFile['verification_hashed']; $data['incoming_url'] = InstallerInfo::getHost(); $data['incoming_ip'] = InstallerInfo::getRemoteAddr(); return Http::post(InstallerInfo::VERIFICATION_HASHED_URL->value, $data)->json(); } else { return false; } } } if (! function_exists('changeEnvValues')) { function changeEnvValues($key, $value) { file_put_contents(app()->environmentFilePath(), str_replace( $key.'='.env($key), $key.'='.$value, file_get_contents(app()->environmentFilePath()) )); } } database/factories/.gitkeep 0000644 00000000000 15012233070 0011677 0 ustar 00 database/migrations/2024_02_10_060044_create_configurations_table.php 0000644 00000001154 15012233070 0021000 0 ustar 00 <?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. */ public function up(): void { Schema::create('configurations', function (Blueprint $table) { $table->id(); $table->string('config'); $table->string('value'); $table->timestamps(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::dropIfExists('configurations'); } }; database/migrations/.gitkeep 0000644 00000000000 15012233070 0012074 0 ustar 00 database/seeders/InstallerDatabaseSeeder.php 0000644 00000000706 15012233070 0015161 0 ustar 00 <?php namespace Modules\Installer\database\seeders; use Illuminate\Database\Seeder; use Modules\Installer\app\Models\Configuration; class InstallerDatabaseSeeder extends Seeder { /** * Run the database seeds. */ public function run(): void { // $this->call([]); Configuration::create(['config' => 'setup_complete', 'value' => 0]); Configuration::create(['config' => 'setup_stage', 'value' => 1]); } } database/seeders/.gitkeep 0000644 00000000000 15012233070 0011352 0 ustar 00 resources/assets/.gitkeep 0000644 00000000000 15012233070 0011470 0 ustar 00 resources/assets/js/app.js 0000644 00000000000 15012233070 0011571 0 ustar 00 resources/assets/sass/app.scss 0000644 00000000000 15012233070 0012465 0 ustar 00 resources/views/.gitkeep 0000644 00000000000 15012233070 0011323 0 ustar 00 resources/views/app.blade.php 0000644 00000014431 15012233070 0012246 0 ustar 00 <!doctype html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>{{ config('app.name', 'Custom Installer') }} - Installer</title> <meta name="csrf-token" content="{{ csrf_token() }}"> <link rel="stylesheet" href="{{ asset('backend/css/bootstrap.min.css') }}"> <link rel="stylesheet" href="{{ asset('website/css/all.min.css') }}"> <link rel="stylesheet" href="{{ asset('global/toastr/toastr.min.css') }}"> <style> a{ text-decoration: none; } .progressbar { counter-reset: step; } .progressbar li { list-style-type: none; float: left; width: 14.2857142857%; position: relative; text-align: center; } .progressbar li:before { content: counter(step); counter-increment: step; width: 30px; height: 30px; line-height: 30px; border: 1px solid var(--bs-gray-500); display: block; text-align: center; margin: 0 auto 10px auto; border-radius: 50%; background-color: var(--bs-light); } .progressbar li:after { content: ''; position: absolute; width: 100%; height: 1px; background-color: var(--bs-gray-500); top: 15px; left: -50%; z-index: -1; } .progressbar li:first-child:after { content: none; } .progressbar li.active { color: var(--bs-primary); } .progressbar li.active:before { border-color: var(--bs-primary); } .progressbar li.active+li:after { background-color: var(--bs-primary); } @media screen and (max-width: 767px) { .progressbar li span { display: none; } } </style> @stack('styles') </head> <body> <main class="container mt-5 main"> <h1 class="text-center text-uppercase text-primary">Installer</h1> <div class="row"> <ul class="progressbar"> <ul class="progressbar"> <li class="@if (request()->routeIs('setup.verify') || (session()->has('step-1-complete') && session()->get('step-1-complete'))) active @endif"><a href="{{route('setup.verify')}}">Verification</a></li> <li class="@if (request()->routeIs('setup.requirements') || (session()->has('step-2-complete') && session()->get('step-2-complete'))) active @endif"><a href="@if ((session()->has('step-1-complete') && session()->get('step-1-complete'))) {{route('setup.requirements')}} @else # @endif" class="@if (!session()->has('step-1-complete')) text-muted @endif">Requirements</a></li> <li class="@if (request()->routeIs('setup.database') || (session()->has('step-3-complete') && session()->get('step-3-complete'))) active @endif"><a href="@if ((session()->has('step-2-complete') && session()->get('step-2-complete') && session()->has('requirements-complete') && session()->get('requirements-complete'))) {{route('setup.database')}} @else # @endif" class="@if (!session()->has('requirements-complete')) text-muted @endif">Database Setup</a></li> <li class="@if (request()->routeIs('setup.account') || (session()->has('step-4-complete') && session()->get('step-4-complete'))) active @endif"><a href="@if ((session()->has('step-3-complete') && session()->get('step-3-complete'))) {{route('setup.account')}} @else # @endif" class="@if (!session()->has('step-3-complete')) text-muted @endif">Account Setup</a></li> <li class="@if (request()->routeIs('setup.configuration') || (session()->has('step-5-complete') && session()->get('step-5-complete'))) active @endif"><a href="@if ((session()->has('step-4-complete') && session()->get('step-4-complete'))) {{route('setup.configuration')}} @else # @endif" class="@if (!session()->has('step-4-complete')) text-muted @endif">Configuration</a></li> <li class="@if (request()->routeIs('setup.smtp') || (session()->has('step-6-complete') && session()->get('step-6-complete'))) active @endif"><a href="@if ((session()->has('step-5-complete') && session()->get('step-5-complete'))) {{route('setup.smtp')}} @else # @endif" class="@if (!session()->has('step-5-complete')) text-muted @endif">SMTP Setup</a></li> <li class="@if (request()->routeIs('setup.complete') || (session()->has('step-7-complete') && session()->get('step-7-complete'))) active @endif"><a href="@if ((session()->has('step-6-complete') && session()->get('step-6-complete'))) {{route('setup.complete')}} @else # @endif" class="@if (!session()->has('step-6-complete')) text-muted @endif">Complete</a></li> </ul> </ul> </div> <div class="row justify-content-center"> <div class="col-12 col-md-8"> @if ($errors->any()) <div class="mb-1 card"> <div class="card-body text-danger"> {{ $errors->first() }} </div> </div> @endif @yield('content') </div> </div> </main> </body> <script src="{{ asset('global/js/jquery-3.7.1.min.js') }}"></script> <script src="{{ asset('global/toastr/toastr.min.js') }}"></script> <script src="{{ asset('backend/js/bootstrap.bundle.min.js') }}"></script> <script> $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); const makeAjaxRequest = (formData, actionUrl) => { return new Promise((resolve, reject) => { $.ajax({ url: actionUrl, method: "post", data: formData, success: function(res) { resolve(res); }, error: function(err) { reject(err); } }); }); } </script> @stack('scripts') </html>