accountRepo = $accountRepo;
$this->mailer = $mailer;
$this->emailService = $emailService;
}
public function showSetup()
{
if (Utils::isNinjaProd() || (Utils::isDatabaseSetup() && Account::count() > 0)) {
return Redirect::to('/');
}
return View::make('setup');
}
public function doSetup()
{
if (Utils::isNinjaProd()) {
return Redirect::to('/');
}
$valid = false;
$test = Input::get('test');
$app = Input::get('app');
$app['key'] = env('APP_KEY') ?: strtolower(str_random(RANDOM_KEY_LENGTH));
$app['debug'] = Input::get('debug') ? 'true' : 'false';
$app['https'] = Input::get('https') ? 'true' : 'false';
$database = Input::get('database');
$dbType = 'mysql'; // $database['default'];
$database['connections'] = [$dbType => $database['type']];
$mail = Input::get('mail');
if ($test == 'mail') {
return self::testMail($mail);
}
$valid = self::testDatabase($database);
if ($test == 'db') {
return $valid === true ? 'Success' : $valid;
} elseif (! $valid) {
return Redirect::to('/setup')->withInput();
}
if (Utils::isDatabaseSetup() && Account::count() > 0) {
return Redirect::to('/');
}
$_ENV['APP_ENV'] = 'production';
$_ENV['APP_DEBUG'] = $app['debug'];
$_ENV['APP_LOCALE'] = 'en';
$_ENV['APP_URL'] = $app['url'];
$_ENV['APP_KEY'] = $app['key'];
$_ENV['APP_CIPHER'] = env('APP_CIPHER', 'AES-256-CBC');
$_ENV['REQUIRE_HTTPS'] = $app['https'];
$_ENV['DB_TYPE'] = $dbType;
$_ENV['DB_HOST'] = $database['type']['host'];
$_ENV['DB_DATABASE'] = $database['type']['database'];
$_ENV['DB_USERNAME'] = $database['type']['username'];
$_ENV['DB_PASSWORD'] = $database['type']['password'];
$_ENV['MAIL_DRIVER'] = $mail['driver'];
$_ENV['MAIL_PORT'] = $mail['port'];
$_ENV['MAIL_ENCRYPTION'] = $mail['encryption'];
$_ENV['MAIL_HOST'] = $mail['host'];
$_ENV['MAIL_USERNAME'] = $mail['username'];
$_ENV['MAIL_FROM_NAME'] = $mail['from']['name'];
$_ENV['MAIL_FROM_ADDRESS'] = $mail['from']['address'];
$_ENV['MAIL_PASSWORD'] = $mail['password'];
$_ENV['PHANTOMJS_CLOUD_KEY'] = 'a-demo-key-with-low-quota-per-ip-address';
$_ENV['PHANTOMJS_SECRET'] = strtolower(str_random(RANDOM_KEY_LENGTH));
$_ENV['MAILGUN_DOMAIN'] = $mail['mailgun_domain'];
$_ENV['MAILGUN_SECRET'] = $mail['mailgun_secret'];
$config = '';
foreach ($_ENV as $key => $val) {
if (is_array($val)) {
continue;
}
if (preg_match('/\s/', $val)) {
$val = "'{$val}'";
}
$config .= "{$key}={$val}\n";
}
// Write Config Settings
$fp = fopen(base_path().'/.env', 'w');
fwrite($fp, $config);
fclose($fp);
if (! Utils::isDatabaseSetup()) {
// == DB Migrate & Seed == //
$sqlFile = base_path() . '/database/setup.sql';
DB::unprepared(file_get_contents($sqlFile));
}
Cache::flush();
Artisan::call('db:seed', ['--force' => true, '--class' => 'UpdateSeeder']);
if (! Account::count()) {
$firstName = trim(Input::get('first_name'));
$lastName = trim(Input::get('last_name'));
$email = trim(strtolower(Input::get('email')));
$password = trim(Input::get('password'));
$account = $this->accountRepo->create($firstName, $lastName, $email, $password);
$user = $account->users()->first();
$user->acceptLatestTerms(request()->getClientIp());
$user->save();
}
return Redirect::to('/login');
}
public function updateSetup()
{
if (Utils::isNinjaProd()) {
return Redirect::to('/');
}
if (! Auth::check() && Utils::isDatabaseSetup() && Account::count() > 0) {
return Redirect::to('/');
}
if (! $canUpdateEnv = @fopen(base_path().'/.env', 'w')) {
Session::flash('error', 'Warning: Permission denied to write to .env config file, try running sudo chown www-data:www-data /path/to/ninja/.env
');
return Redirect::to('/settings/system_settings');
}
$app = Input::get('app');
$db = Input::get('database');
$mail = Input::get('mail');
$_ENV['APP_URL'] = $app['url'];
$_ENV['APP_DEBUG'] = Input::get('debug') ? 'true' : 'false';
$_ENV['REQUIRE_HTTPS'] = Input::get('https') ? 'true' : 'false';
$_ENV['DB_TYPE'] = 'mysql'; // $db['default'];
$_ENV['DB_HOST'] = $db['type']['host'];
$_ENV['DB_DATABASE'] = $db['type']['database'];
$_ENV['DB_USERNAME'] = $db['type']['username'];
$_ENV['DB_PASSWORD'] = $db['type']['password'];
if ($mail) {
$prefix = '';
if (($user = auth()->user()) && Account::count() > 1) {
$prefix = $user->account_id . '_';
}
$_ENV[$prefix . 'MAIL_DRIVER'] = $mail['driver'];
$_ENV[$prefix . 'MAIL_PORT'] = $mail['port'];
$_ENV[$prefix . 'MAIL_ENCRYPTION'] = $mail['encryption'];
$_ENV[$prefix . 'MAIL_HOST'] = $mail['host'];
$_ENV[$prefix . 'MAIL_USERNAME'] = $mail['username'];
$_ENV[$prefix . 'MAIL_FROM_NAME'] = $mail['from']['name'];
$_ENV[$prefix . 'MAIL_FROM_ADDRESS'] = $mail['from']['address'];
$_ENV[$prefix . 'MAIL_PASSWORD'] = $mail['password'];
$_ENV['MAILGUN_DOMAIN'] = $mail['mailgun_domain'];
$_ENV['MAILGUN_SECRET'] = $mail['mailgun_secret'];
}
$config = '';
foreach ($_ENV as $key => $val) {
if (is_array($val)) {
continue;
}
if (preg_match('/\s/', $val)) {
$val = "'{$val}'";
}
$config .= "{$key}={$val}\n";
}
$filePath = base_path().'/.env';
$fp = fopen($filePath, 'w');
fwrite($fp, $config);
fclose($fp);
Session::flash('message', trans('texts.updated_settings'));
return Redirect::to('/settings/system_settings');
}
private function testDatabase($database)
{
$dbType = 'mysql'; // $database['default'];
Config::set('database.default', $dbType);
foreach ($database['connections'][$dbType] as $key => $val) {
Config::set("database.connections.{$dbType}.{$key}", $val);
}
try {
DB::reconnect();
$valid = DB::connection()->getDatabaseName() ? true : false;
} catch (Exception $e) {
return $e->getMessage();
}
return $valid;
}
private function testMail($mail)
{
$email = $mail['from']['address'];
$fromName = $mail['from']['name'];
foreach ($mail as $key => $val) {
Config::set("mail.{$key}", $val);
}
Config::set('mail.from.address', $email);
Config::set('mail.from.name', $fromName);
$data = [
'text' => 'Test email',
'fromEmail' => $email
];
try {
$response = $this->mailer->sendTo($email, $email, $fromName, 'Test email', 'contact', $data);
return $response === true ? 'Sent' : $response;
} catch (Exception $e) {
return $e->getMessage();
}
}
public function install()
{
if (! Utils::isNinjaProd() && ! Utils::isDatabaseSetup()) {
try {
set_time_limit(60 * 5); // shouldn't take this long but just in case
Artisan::call('migrate', ['--force' => true]);
if (Industry::count() == 0) {
Artisan::call('db:seed', ['--force' => true]);
}
} catch (Exception $e) {
Utils::logError($e);
return Response::make($e->getMessage(), 500);
}
}
return Redirect::to('/');
}
public function update()
{
if (! Utils::isNinjaProd()) {
if ($password = env('UPDATE_SECRET')) {
if (! hash_equals($password, request('secret') ?: '')) {
$message = 'Invalid secret: /update?secret=';
Utils::logError($message);
echo $message;
exit;
}
}
try {
set_time_limit(60 * 5);
$this->checkInnoDB();
$cacheCompiled = base_path('bootstrap/cache/compiled.php');
if (file_exists($cacheCompiled)) { unlink ($cacheCompiled); }
$cacheServices = base_path('bootstrap/cache/services.json');
if (file_exists($cacheServices)) { unlink ($cacheServices); }
Artisan::call('clear-compiled');
Artisan::call('cache:clear');
Artisan::call('debugbar:clear');
Artisan::call('route:clear');
Artisan::call('view:clear');
Artisan::call('config:clear');
Auth::logout();
Cache::flush();
Session::flush();
Artisan::call('migrate', ['--force' => true]);
Artisan::call('db:seed', ['--force' => true, '--class' => 'UpdateSeeder']);
Event::fire(new UserSettingsChanged());
// legacy fix: check cipher is in .env file
if (! env('APP_CIPHER')) {
$fp = fopen(base_path().'/.env', 'a');
fwrite($fp, "\nAPP_CIPHER=AES-256-CBC");
fclose($fp);
}
// show message with link to Trello board
$message = trans('texts.see_whats_new', ['version' => NINJA_VERSION]);
$message = link_to(RELEASES_URL, $message, ['target' => '_blank']);
$message = sprintf('%s - %s', trans('texts.processed_updates'), $message);
Session::flash('warning', $message);
} catch (Exception $e) {
Utils::logError($e);
return Response::make($e->getMessage(), 500);
}
}
return Redirect::to('/?clear_cache=true');
}
// MySQL changed the default table type from MyISAM to InnoDB
// We need to make sure all tables are InnoDB to prevent migration failures
public function checkInnoDB()
{
$result = DB::select("SELECT engine
FROM information_schema.TABLES
WHERE TABLE_NAME='clients' AND TABLE_SCHEMA='ninja'");
if (count($result) && $result[0]->engine == 'InnoDB') {
return;
}
$tables = DB::select('SHOW TABLES');
$sql = "SET sql_mode = 'ALLOW_INVALID_DATES';\n";
foreach($tables as $table) {
$fieldName = 'Tables_in_' . env('DB_DATABASE');
$sql .= "ALTER TABLE {$table->$fieldName} engine=InnoDB;\n";
}
DB::unprepared($sql);
}
public function emailBounced()
{
$messageId = Input::get('MessageID');
$error = Input::get('Name') . ': ' . Input::get('Description');
return $this->emailService->markBounced($messageId, $error) ? RESULT_SUCCESS : RESULT_FAILURE;
}
public function emailOpened()
{
$messageId = Input::get('MessageID');
return $this->emailService->markOpened($messageId) ? RESULT_SUCCESS : RESULT_FAILURE;
return RESULT_SUCCESS;
}
public function checkData()
{
try {
Artisan::call('ninja:check-data');
Artisan::call('ninja:init-lookup', ['--validate' => true]);
// check error log is empty
$errorLog = storage_path('logs/laravel-error.log');
if (file_exists($errorLog)) {
return 'Failure: error log exists';
}
return RESULT_SUCCESS;
} catch (Exception $exception) {
return $exception->getMessage() ?: RESULT_FAILURE;
}
}
public function errors()
{
if (Utils::isNinjaProd()) {
return redirect('/');
}
$errors = Utils::getErrors();
return view('errors.list', compact('errors'));
}
public function stats()
{
if (! hash_equals(Input::get('password') ?: '', env('RESELLER_PASSWORD'))) {
sleep(3);
return '';
}
if (Utils::getResllerType() == RESELLER_REVENUE_SHARE) {
$data = DB::table('accounts')
->leftJoin('payments', 'payments.account_id', '=', 'accounts.id')
->leftJoin('clients', 'clients.id', '=', 'payments.client_id')
->where('accounts.account_key', '=', NINJA_ACCOUNT_KEY)
->where('payments.is_deleted', '=', false)
->get([
'clients.public_id as client_id',
'payments.public_id as payment_id',
'payments.payment_date',
'payments.amount',
]);
} else {
$data = DB::table('users')->count();
}
return json_encode($data);
}
public function testHeadless()
{
$invoice = Invoice::scope()->orderBy('id')->first();
if (! $invoice) {
dd('Please create an invoice to run this test');
}
header('Content-type:application/pdf');
echo $invoice->getPDFString();
exit;
}
public function runCommand()
{
if (Utils::isNinjaProd()) {
abort(400, 'Not allowed');
}
$command = request()->command;
$options = request()->options ?: [];
$secret = env('COMMAND_SECRET');
if (! $secret) {
exit('Set a value for COMMAND_SECRET in the .env file');
} elseif (! hash_equals($secret, request()->secret ?: '')) {
exit('Invalid secret');
}
if (! $command || ! in_array($command, ['send-invoices', 'send-reminders', 'update-key'])) {
exit('Invalid command: Valid options are send-invoices, send-reminders or update-key');
}
Artisan::call('ninja:' . $command, $options);
return response(nl2br(Artisan::output()));
}
public function redirect()
{
return redirect((Utils::isNinja() ? NINJA_WEB_URL : ''), 301);
}
}