diff --git a/README.md b/README.md index 8d750270f5ab..0d88ab5a55ba 100644 --- a/README.md +++ b/README.md @@ -47,17 +47,10 @@ Note: you may be prompted for your Github user/pass due to their API limits. composer install -Install JavaScript and HTML packages using Bower +Install JavaScript and HTML packages using Bower. This is optional, it's only needed if you want to modify the JavaScript. bower install -Create the development environment configurations - - mkdir app/config/development - cp app/config/app.php app/config/development/ - cp app/config/database.php app/config/development/ - cp app/config/mail.php app/config/development/ - Create database user and a database for ninja CREATE SCHEMA `ninja` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; @@ -65,11 +58,7 @@ Create database user and a database for ninja GRANT ALL PRIVILEGES ON `ninja`.* TO 'ninja'@'localhost'; FLUSH PRIVILEGES; -Configure development/config/database.php and development/config/mail.php and initialize the database. - - php artisan migrate --seed - -Add public/ to your web server root +Add public/ to your web server root then load / to configure the application. ### Deleveloper Notes diff --git a/app/config/app.php b/app/config/app.php index 76b4a1680e70..6e6257f07353 100755 --- a/app/config/app.php +++ b/app/config/app.php @@ -13,7 +13,7 @@ return array( | */ - 'debug' => true, + 'debug' => false, /* |-------------------------------------------------------------------------- diff --git a/app/config/mail.php b/app/config/mail.php index 62dac9c3a572..9840e66e9967 100755 --- a/app/config/mail.php +++ b/app/config/mail.php @@ -28,7 +28,7 @@ return array( | */ - 'host' => '', + //'host' => '', /* |-------------------------------------------------------------------------- diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index b26e716d21dd..5f093c450c2f 100755 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -19,52 +19,6 @@ class AccountController extends \BaseController { $this->contactMailer = $contactMailer; } - public function install() - { - if (!Utils::isNinja() && !Schema::hasTable('accounts')) { - try { - Artisan::call('migrate'); - Artisan::call('db:seed'); - } catch (Exception $e) { - Response::make($e->getMessage(), 500); - } - } - - return Redirect::to('/'); - } - - public function update() - { - if (!Utils::isNinja()) { - try { - Artisan::call('migrate'); - Cache::flush(); - } catch (Exception $e) { - Response::make($e->getMessage(), 500); - } - } - - return Redirect::to('/'); - } - - /* - public function reset() - { - if (Utils::isNinjaDev()) { - Confide::logout(); - try { - Artisan::call('migrate:reset'); - Artisan::call('migrate'); - Artisan::call('db:seed'); - } catch (Exception $e) { - Response::make($e->getMessage(), 500); - } - } - - return Redirect::to('/'); - } - */ - public function demo() { $demoAccountId = Utils::getDemoAccountId(); @@ -114,7 +68,7 @@ class AccountController extends \BaseController { } Auth::login($user, true); - Event::fire('user.login'); + Event::fire('user.login'); return Redirect::to('invoices/create'); } @@ -918,32 +872,7 @@ class AccountController extends \BaseController { $user->registered = true; $user->amend(); - if (Utils::isNinja()) - { - $this->userMailer->sendConfirmation($user); - } - else - { - /* - $url = NINJA_APP_URL . '/signup/register'; - $data = ''; - $fields = [ - 'first_name' => urlencode($user->first_name), - 'last_name' => urlencode($user->last_name), - 'email' => urlencode($user->email) - ]; - - foreach($fields as $key=>$value) { $data .= $key.'='.$value.'&'; } - rtrim($data, '&'); - - $ch = curl_init(); - curl_setopt($ch,CURLOPT_URL, $url); - curl_setopt($ch,CURLOPT_POST, count($fields)); - curl_setopt($ch,CURLOPT_POSTFIELDS, $data); - curl_exec($ch); - curl_close($ch); - */ - } + $this->userMailer->sendConfirmation($user); $activities = Activity::scope()->get(); foreach ($activities as $activity) diff --git a/app/controllers/AppController.php b/app/controllers/AppController.php new file mode 100644 index 000000000000..e209e22b1507 --- /dev/null +++ b/app/controllers/AppController.php @@ -0,0 +1,202 @@ +accountRepo = $accountRepo; + $this->mailer = $mailer; + } + + public function showSetup() + { + if (Utils::isNinja() || Utils::isDatabaseSetup()) + { + return Redirect::to('/'); + } + + return View::make('setup'); + } + + public function doSetup() + { + if (Utils::isNinja() || Utils::isDatabaseSetup()) + { + return Redirect::to('/'); + } + + $valid = false; + $test = Input::get('test'); + + $app = Input::get('app'); + $app['key'] = str_random(RANDOM_KEY_LENGTH); + + $database = Input::get('database'); + $dbType = $database['default']; + $database[$dbType] = $database['type']; + unset($database['type']); + + $mail = Input::get('mail'); + $email = $mail['username']; + $mail['from']['address'] = $email; + + if ($test == 'mail') + { + return self::testMail($mail); + } + + $valid = self::testDatabase($database); + + if ($test == 'db') + { + return $valid ? 'Success' : 'Failed'; + } + else if (!$valid) + { + return Redirect::to('/setup')->withInput(); + } + + $configDir = app_path() . '/config/production'; + if (!file_exists($configDir)) + { + mkdir($configDir); + } + + foreach(['app' => $app, 'database' => $database, 'mail' => $mail] as $key => $config) + { + $content = 'accountRepo->create(); + $user = $account->users()->first(); + + $user->first_name = trim(Input::get('first_name')); + $user->last_name = trim(Input::get('last_name')); + $user->email = trim(strtolower(Input::get('email'))); + $user->username = $user->email; + $user->password = trim(Input::get('password')); + $user->password_confirmation = trim(Input::get('password')); + $user->registered = true; + $user->amend(); + + //Auth::login($user, true); + //self::register($user); + + return Redirect::to('/invoices/create'); + } + + private function testDatabase($database) + { + $dbType = $database['default']; + + Config::set('database.default', $dbType); + + foreach ($database[$dbType] as $key => $val) + { + Config::set("database.connections.{$dbType}.{$key}", $val); + } + + try + { + $valid = DB::connection()->getDatabaseName() ? true : false; + } + catch (Exception $e) + { + return $e->getMessage(); + } + + return $valid; + } + + private function testMail($mail) + { + $email = $mail['username']; + $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' + ]; + + try + { + $this->mailer->sendTo($email, $email, $fromName, 'Test email', 'contact', $data); + return 'Sent'; + } + catch (Exception $e) + { + return $e->getMessage(); + } + } + + private function register($user) + { + $url = NINJA_APP_URL . '/signup/register'; + $data = ''; + $fields = [ + 'first_name' => urlencode($user->first_name), + 'last_name' => urlencode($user->last_name), + 'email' => urlencode($user->email) + ]; + + foreach($fields as $key=>$value) { $data .= $key.'='.$value.'&'; } + rtrim($data, '&'); + + $ch = curl_init(); + curl_setopt($ch,CURLOPT_URL, $url); + curl_setopt($ch,CURLOPT_POST, count($fields)); + curl_setopt($ch,CURLOPT_POSTFIELDS, $data); + curl_exec($ch); + curl_close($ch); + } + + public function install() + { + if (!Utils::isNinja() && !Utils::isDatabaseSetup()) { + try { + Artisan::call('migrate'); + Artisan::call('db:seed'); + } catch (Exception $e) { + Response::make($e->getMessage(), 500); + } + } + + return Redirect::to('/'); + } + + public function update() + { + if (!Utils::isNinja()) { + try { + Artisan::call('migrate'); + Cache::flush(); + } catch (Exception $e) { + Response::make($e->getMessage(), 500); + } + } + + return Redirect::to('/'); + } + +} \ No newline at end of file diff --git a/app/controllers/HomeController.php b/app/controllers/HomeController.php index 8389a36980b2..5750227aa91b 100755 --- a/app/controllers/HomeController.php +++ b/app/controllers/HomeController.php @@ -4,7 +4,6 @@ use ninja\mailers\Mailer; class HomeController extends BaseController { - protected $layout = 'master'; protected $mailer; public function __construct(Mailer $mailer) @@ -22,7 +21,11 @@ class HomeController extends BaseController { } else { - if (Account::count() == 0) + if (!Utils::isDatabaseSetup()) + { + return Redirect::to('/setup'); + } + else if (Account::count() == 0) { return Redirect::to('/invoice_now'); } diff --git a/app/filters.php b/app/filters.php index 3e4f1816443b..74ee30ac001c 100755 --- a/app/filters.php +++ b/app/filters.php @@ -13,6 +13,7 @@ App::before(function($request) { + // Ensure all request are over HTTPS in production if (App::environment() == ENV_PRODUCTION) { if (!Request::secure()) @@ -21,12 +22,18 @@ App::before(function($request) } } + // If the database doens't yet exist we'll skip the rest + if (!Utils::isNinja() && !Utils::isDatabaseSetup()) + { + return; + } + + // check the application is up to date and for any news feed messages if (Auth::check()) { $count = Session::get(SESSION_COUNTER, 0); Session::put(SESSION_COUNTER, ++$count); - // check the application is up to date and for any news feed messages if (!Utils::startsWith($_SERVER['REQUEST_URI'], '/news_feed') && !Session::has('news_feed_id')) { $data = false; if (Utils::isNinja()) { @@ -56,6 +63,7 @@ App::before(function($request) } } + // Check if we're requesting to change the account's language if (Input::has('lang')) { $locale = Input::get('lang'); @@ -78,6 +86,13 @@ App::before(function($request) App::setLocale($locale); } + // Make sure the account/user localization settings are in the session + if (Auth::check() && !Session::has(SESSION_TIMEZONE)) + { + Event::fire('user.refresh'); + } + + // Check if the user is claiming a license (ie, additional invoices, white label, etc.) $claimingLicense = Utils::startsWith($_SERVER['REQUEST_URI'], '/claim_license'); if (!$claimingLicense && Input::has('license_key') && Input::has('product_id')) { diff --git a/app/libraries/utils.php b/app/libraries/utils.php index 3e5a98b92fff..ad0bc6fe0ff5 100755 --- a/app/libraries/utils.php +++ b/app/libraries/utils.php @@ -12,6 +12,21 @@ class Utils return Auth::check() && Auth::user()->confirmed; } + public static function isDatabaseSetup() + { + try + { + if (Schema::hasTable('accounts')) + { + return true; + } + } + catch (Exception $e) + { + return false; + } + } + public static function isProd() { return App::environment() == ENV_PRODUCTION; diff --git a/app/ninja/mailers/Mailer.php b/app/ninja/mailers/Mailer.php index cf566da051c6..42dc5c1c190a 100755 --- a/app/ninja/mailers/Mailer.php +++ b/app/ninja/mailers/Mailer.php @@ -17,7 +17,7 @@ class Mailer { $replyEmail = $fromEmail; // http://stackoverflow.com/questions/2421234/gmail-appearing-to-ignore-reply-to - if ($toEmail != CONTACT_EMAIL) + if (Utils::isNinja() && $toEmail != CONTACT_EMAIL) { $fromEmail = NINJA_FROM_EMAIL; } diff --git a/app/routes.php b/app/routes.php index 297a079e9ac7..656077a8f125 100755 --- a/app/routes.php +++ b/app/routes.php @@ -1,13 +1,5 @@ 0; + return Utils::parseFloat($value) > 0; }); Validator::extend('has_credit', function($attribute, $value, $parameters) diff --git a/app/views/master.blade.php b/app/views/master.blade.php index a29314f537ed..443a06ecebe9 100755 --- a/app/views/master.blade.php +++ b/app/views/master.blade.php @@ -20,7 +20,7 @@ - + diff --git a/app/views/public/splash.blade.php b/app/views/public/splash.blade.php index 699c69308734..3e2fd6e4df3f 100755 --- a/app/views/public/splash.blade.php +++ b/app/views/public/splash.blade.php @@ -18,7 +18,7 @@ - +
@@ -31,7 +31,7 @@
- +
@@ -73,166 +73,166 @@
-
- -
-
-
- -
-
- Invoice Ninja Does Everything You'd Expect Your Online Invoicing App to Do -
-
-
-
- -
-
- - Invoice clients via email -
-
- - Intuitive editing interface -
- -
- - Printable .pdf invoices -
-
- - Multiple tax settings -
-
- - Import/export records -
-
- -
-
- - Accept payments online -
-
- - Best-in-class security -
- -
- - Adjustable payment terms -
-
- - Multiple currency support -
-
- - Recurring invoice profiles -
-
- -
-
- - Free invoicing platform -
-
- - Estimates & pro-forma -
- -
- - Payment tracking -
-
- - Multilingual support -
-
- - Self-hosted available -
-
- -
-
- - Live .pdf creation -
-
- - Clone invoices -
- -
- - Cloud-based app -
-
- - Open source -
-
- - Beautiful templates -
-
- -
-
- - Cutomize invoices with your company logo -
-
- - Personalize invoice color schemes -
- -
- - Alerts when invoices are viewed or paid -
-
- - Integrate with top payment gateways -
-
- - Manual or automatic invoice numbers -
-
- -
-
-
+
+ +
+
+
+ +
+
+ Invoice Ninja Does Everything You'd Expect Your Online Invoicing App to Do +
+
+
+
+ +
+
+ + Invoice clients via email +
+
+ + Intuitive editing interface +
+ +
+ + Printable .pdf invoices +
+
+ + Multiple tax settings +
+
+ + Import/export records +
+
+ +
+
+ + Accept payments online +
+
+ + Best-in-class security +
+ +
+ + Adjustable payment terms +
+
+ + Multiple currency support +
+
+ + Recurring invoice profiles +
+
+ +
+
+ + Free invoicing platform +
+
+ + Estimates & pro-forma +
+ +
+ + Payment tracking +
+
+ + Multilingual support +
+
+ + Self-hosted available +
+
+ +
+
+ + Live .pdf creation +
+
+ + Clone invoices +
+ +
+ + Cloud-based app +
+
+ + Open source +
+
+ + Beautiful templates +
+
+ +
+
+ + Cutomize invoices with your company logo +
+
+ + Personalize invoice color schemes +
+ +
+ + Alerts when invoices are viewed or paid +
+
+ + Integrate with top payment gateways +
+
+ + Manual or automatic invoice numbers +
+
+ +
+
+
-

{{ trans('public.home.footer') }}

-
-
- -
-

{{ trans('public.invoice_now') }} +

-
-
+

{{ trans('public.home.footer') }}

+ +

{{ trans('public.no_signup_needed') }}

+
+
+
-

{{ trans('public.no_signup_needed') }}

-
-
-
-
diff --git a/app/views/setup.blade.php b/app/views/setup.blade.php new file mode 100644 index 000000000000..29ce13a25979 --- /dev/null +++ b/app/views/setup.blade.php @@ -0,0 +1,114 @@ + + + + Invoice Ninja | Setup + + + + + + + +
+ +   +
+
+ +
+

Invoice Ninja Setup

+

+

-- Commands to create a MySQL database and user
+CREATE SCHEMA `ninja` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
+CREATE USER 'ninja'@'localhost' IDENTIFIED BY 'ninja';
+GRANT ALL PRIVILEGES ON `ninja`.* TO 'ninja'@'localhost';
+FLUSH PRIVILEGES;
+

+ If you need help you can either post to our Google Group + or email us at contact@invoiceninja.com. +
+ + {{ Former::open() }} + +
+
+

Application Settings

+
+
+ {{ Former::text('app[url]')->label('URL')->value(Request::root()) }} +
+
+ +
+
+

Database Connection

+
+
+ {{ Former::select('database[default]')->label('Driver')->options(['mysql' => 'MySQL', 'pgsql' => 'PostgreSQL', 'sqlite' => 'SQLite']) }} + {{ Former::text('database[type][host]')->label('Host')->value('localhost') }} + {{ Former::text('database[type][database]')->label('Database')->value('ninja') }} + {{ Former::text('database[type][username]')->label('Username')->value('ninja') }} + {{ Former::text('database[type][password]')->label('Password')->value('ninja') }} + {{ Former::actions( Button::normal('Test connection', ['onclick' => 'testDatabase()']), '  ' ) }} +
+
+ + +
+
+

Email Settings

+
+
+ {{ Former::select('mail[driver]')->label('Driver')->options(['smtp' => 'SMTP', 'mail' => 'Mail', 'sendmail' => 'Sendmail']) }} + {{ Former::text('mail[host]')->label('Host')->value('localhost') }} + {{ Former::text('mail[port]')->label('Port')->value('587') }} + {{ Former::select('mail[encryption]')->label('Encryption')->options(['tls' => 'TLS', 'ssl' => 'SSL']) }} + {{ Former::text('mail[from][name]')->label('From Name') }} + {{ Former::text('mail[username]')->label('Email') }} + {{ Former::text('mail[password]')->label('Password') }} + {{ Former::actions( Button::normal('Send test email', ['onclick' => 'testMail()']), '  ' ) }} +
+
+ + +
+
+

User Details

+
+
+ {{ Former::text('first_name') }} + {{ Former::text('last_name') }} + {{ Former::text('email') }} + {{ Former::text('password') }} +
+
+ + {{ Former::actions( Button::submit_lg('Submit') ) }} + {{ Former::close() }} + +
+ + + + + \ No newline at end of file