Added support for Zapier

This commit is contained in:
Hillel Coren 2014-07-27 23:31:41 +03:00
parent f5f87319b2
commit 9feb616f1b
23 changed files with 913 additions and 303 deletions

View File

@ -20,6 +20,7 @@ Site design by [kantorp-wegl.in](http://kantorp-wegl.in/)
* Integrates with many payment providers * Integrates with many payment providers
* Recurring invoices * Recurring invoices
* Tax rates and payment terms * Tax rates and payment terms
* Multi-user support
### Steps to setup ### Steps to setup

View File

@ -379,6 +379,7 @@ class AccountController extends \BaseController {
$client = Client::createNew(); $client = Client::createNew();
$contact = Contact::createNew(); $contact = Contact::createNew();
$contact->is_primary = true; $contact->is_primary = true;
$contact->send_invoice = true;
$count++; $count++;
foreach ($row as $index => $value) foreach ($row as $index => $value)
@ -443,7 +444,7 @@ class AccountController extends \BaseController {
$client->save(); $client->save();
$client->contacts()->save($contact); $client->contacts()->save($contact);
Activity::createClient($client); Activity::createClient($client, false);
} }
$message = Utils::pluralize('created_client', $count); $message = Utils::pluralize('created_client', $count);
@ -470,7 +471,7 @@ class AccountController extends \BaseController {
if (count($csv->data) + Client::scope()->count() > Auth::user()->getMaxNumClients()) if (count($csv->data) + Client::scope()->count() > Auth::user()->getMaxNumClients())
{ {
$message = Utils::pluralize('limit_clients', Auth::user()->getMaxNumClients()); $message = trans('texts.limit_clients', ['count' => Auth::user()->getMaxNumClients()]);
Session::flash('error', $message); Session::flash('error', $message);
return Redirect::to('company/import_export'); return Redirect::to('company/import_export');
} }

View File

@ -17,6 +17,6 @@ class BaseController extends Controller {
public function __construct() public function __construct()
{ {
$this->beforeFilter('csrf', array('on' => array('post', 'delete', 'put'))); $this->beforeFilter('csrf', array('on' => array('post', 'delete', 'put')));
} }
} }

View File

@ -3,58 +3,46 @@
use ninja\repositories\ClientRepository; use ninja\repositories\ClientRepository;
use Client; use Client;
class ClientApiController extends \BaseController { class ClientApiController extends Controller {
protected $clientRepo; protected $clientRepo;
public function __construct(ClientRepository $clientRepo) public function __construct(ClientRepository $clientRepo)
{ {
parent::__construct();
$this->clientRepo = $clientRepo; $this->clientRepo = $clientRepo;
} }
public function ping()
{
$headers = Utils::getApiHeaders();
return Response::make('', 200, $headers);
}
public function index() public function index()
{ {
$clients = Client::scope()->get(); if (!Utils::isPro()) {
Redirect::to('/');
/* }
$response = [
'status' => 200,
'error' => false,
'clients' => $clients->toArray()
];
*/
$response = json_encode($clients->toArray(), JSON_PRETTY_PRINT); $clients = Client::scope()->with('contacts')->orderBy('created_at', 'desc')->get();
$headers = [ $clients = Utils::remapPublicIds($clients->toArray());
'Content-Type' => 'application/json',
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'GET',
//'Access-Control-Allow-Headers' => 'Origin, Content-Type, Accept, Authorization, X-Requested-With',
//'Access-Control-Allow-Credentials' => 'true',
//'X-Total-Count' => 0
//'X-Rate-Limit-Limit' - The number of allowed requests in the current period
//'X-Rate-Limit-Remaining' - The number of remaining requests in the current period
//'X-Rate-Limit-Reset' - The number of seconds left in the current period,
];
/* $response = json_encode($clients, JSON_PRETTY_PRINT);
200 OK - Response to a successful GET, PUT, PATCH or DELETE. Can also be used for a POST that doesn't result in a creation. $headers = Utils::getApiHeaders(count($clients));
201 Created - Response to a POST that results in a creation. Should be combined with a Location header pointing to the location of the new resource return Response::make($response, 200, $headers);
204 No Content - Response to a successful request that won't be returning a body (like a DELETE request) }
304 Not Modified - Used when HTTP caching headers are in play
400 Bad Request - The request is malformed, such as if the body does not parse
401 Unauthorized - When no or invalid authentication details are provided. Also useful to trigger an auth popup if the API is used from a browser
403 Forbidden - When authentication succeeded but authenticated user doesn't have access to the resource
404 Not Found - When a non-existent resource is requested
405 Method Not Allowed - When an HTTP method is being requested that isn't allowed for the authenticated user
410 Gone - Indicates that the resource at this end point is no longer available. Useful as a blanket response for old API versions
415 Unsupported Media Type - If incorrect content type was provided as part of the request
422 Unprocessable Entity - Used for validation errors
429 Too Many Requests - When a request is rejected due to rate limiting
*/
public function store()
{
if (!Utils::isPro()) {
Redirect::to('/');
}
$data = Input::all();
$client = $this->clientRepo->save(false, $data, false);
$response = json_encode($client, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders();
return Response::make($response, 200, $headers); return Response::make($response, 200, $headers);
} }
} }

View File

@ -0,0 +1,29 @@
<?php
class IntegrationController extends Controller {
public function subscribe()
{
$eventId = Utils::lookupEventId(trim(Input::get('event')));
if (!$eventId)
{
return Response::json('', 500);
}
$subscription = Subscription::where('account_id', '=', Auth::user()->account_id)->where('event_id', '=', $eventId)->first();
if (!$subscription)
{
$subscription = new Subscription;
$subscription->account_id = Auth::user()->account_id;
$subscription->event_id = $eventId;
}
$subscription->target_url = trim(Input::get('target_url'));
$subscription->save();
return Response::json('{"id":'.$subscription->id.'}', 201);
}
}

View File

@ -0,0 +1,40 @@
<?php
use ninja\repositories\InvoiceRepository;
use Invoice;
class InvoiceApiController extends Controller {
protected $invoiceRepo;
public function __construct(InvoiceRepository $invoiceRepo)
{
$this->invoiceRepo = $invoiceRepo;
}
public function index()
{
if (!Utils::isPro()) {
Redirect::to('/');
}
$invoices = Invoice::scope()->where('invoices.is_quote', '=', false)->orderBy('created_at', 'desc')->get();
$invoices = Utils::remapPublicIds($invoices->toArray());
$response = json_encode($invoices, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders(count($invoices));
return Response::make($response, 200, $headers);
}
/*
public function store()
{
$data = Input::all();
$invoice = $this->invoiceRepo->save(false, $data, false);
$response = json_encode($invoice, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders();
return Response::make($response, 200, $headers);
}
*/
}

View File

@ -0,0 +1,40 @@
<?php
use ninja\repositories\PaymentRepository;
use Payment;
class PaymentApiController extends Controller {
protected $paymentRepo;
public function __construct(PaymentRepository $paymentRepo)
{
$this->paymentRepo = $paymentRepo;
}
public function index()
{
if (!Utils::isPro()) {
Redirect::to('/');
}
$payments = Payment::scope()->orderBy('created_at', 'desc')->get();
$payments = Utils::remapPublicIds($payments->toArray());
$response = json_encode($payments, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders(count($payments));
return Response::make($response, 200, $headers);
}
/*
public function store()
{
$data = Input::all();
$invoice = $this->invoiceRepo->save(false, $data, false);
$response = json_encode($invoice, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders();
return Response::make($response, 200, $headers);
}
*/
}

View File

@ -0,0 +1,40 @@
<?php
use ninja\repositories\InvoiceRepository;
use Invoice;
class QuoteApiController extends Controller {
protected $invoiceRepo;
public function __construct(InvoiceRepository $invoiceRepo)
{
$this->invoiceRepo = $invoiceRepo;
}
public function index()
{
if (!Utils::isPro()) {
Redirect::to('/');
}
$invoices = Invoice::scope()->where('invoices.is_quote', '=', true)->orderBy('created_at', 'desc')->get();
$invoices = Utils::remapPublicIds($invoices->toArray());
$response = json_encode($invoices, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders(count($invoices));
return Response::make($response, 200, $headers);
}
/*
public function store()
{
$data = Input::all();
$invoice = $this->invoiceRepo->save(false, $data, false);
$response = json_encode($invoice, JSON_PRETTY_PRINT);
$headers = Utils::getApiHeaders();
return Response::make($response, 200, $headers);
}
*/
}

View File

@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddZapierSupport extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('subscriptions', function($table)
{
$table->increments('id');
$table->unsignedInteger('account_id')->nullable();
$table->timestamps();
$table->softDeletes();
$table->unsignedInteger('event_id')->nullable();
$table->string('target_url');
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
$table->unique( ['account_id', 'event_id'] );
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('subscriptions');
}
}

View File

@ -119,11 +119,11 @@ Route::filter('csrf', function()
{ {
$token = Request::ajax() ? Request::header('X-CSRF-Token') : Input::get('_token'); $token = Request::ajax() ? Request::header('X-CSRF-Token') : Input::get('_token');
if (Session::token() != $token) if (Session::token() != $token)
{ {
Session::flash('warning', trans('texts.session_expired')); Session::flash('warning', trans('texts.session_expired'));
return Redirect::to('/'); return Redirect::to('/');
//throw new Illuminate\Session\TokenMismatchException; //throw new Illuminate\Session\TokenMismatchException;
} }
}); });

View File

@ -463,4 +463,76 @@ class Utils
} }
return join('-', $parts); return join('-', $parts);
} }
public static function lookupEventId($eventName)
{
if ($eventName == 'create_client') {
return EVENT_CREATE_CLIENT;
} else if ($eventName == 'create_invoice') {
return EVENT_CREATE_INVOICE;
} else if ($eventName == 'create_quote') {
return EVENT_CREATE_QUOTE;
} else if ($eventName == 'create_payment') {
return EVENT_CREATE_PAYMENT;
} else {
return false;
}
}
public static function notifyZapier($subscription, $data) {
$curl = curl_init();
$jsonEncodedData = json_encode($data->toJson());
$opts = [
CURLOPT_URL => $subscription->target_url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $jsonEncodedData,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Content-Length: ' . strlen($jsonEncodedData)]
];
curl_setopt_array($curl, $opts);
$result = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($status == 410)
{
$subscription->delete();
}
}
public static function remapPublicIds($data) {
foreach ($data as $index => $record) {
if (!isset($data[$index]['public_id'])) {
continue;
}
$data[$index]['id'] = $data[$index]['public_id'];
unset($data[$index]['public_id']);
foreach ($record as $key => $val) {
if (is_array($val)) {
$data[$index][$key] = Utils::remapPublicIds($val);
}
}
}
return $data;
}
public static function getApiHeaders($count = 0) {
return [
'Content-Type' => 'application/json',
//'Access-Control-Allow-Origin' => '*',
//'Access-Control-Allow-Methods' => 'GET',
//'Access-Control-Allow-Headers' => 'Origin, Content-Type, Accept, Authorization, X-Requested-With',
//'Access-Control-Allow-Credentials' => 'true',
'X-Total-Count' => $count,
//'X-Rate-Limit-Limit' - The number of allowed requests in the current period
//'X-Rate-Limit-Remaining' - The number of remaining requests in the current period
//'X-Rate-Limit-Reset' - The number of seconds left in the current period,
];
}
} }

View File

@ -248,4 +248,8 @@ class Account extends Eloquent
return $interval->y == 0; return $interval->y == 0;
} }
public function getSubscription($eventId)
{
return Subscription::where('account_id', '=', $this->id)->where('event_id', '=', $eventId)->first();
}
} }

View File

@ -67,13 +67,18 @@ class Activity extends Eloquent
return $activity; return $activity;
} }
public static function createClient($client) public static function createClient($client, $notify = true)
{ {
$activity = Activity::getBlank(); $activity = Activity::getBlank();
$activity->client_id = $client->id; $activity->client_id = $client->id;
$activity->activity_type_id = ACTIVITY_TYPE_CREATE_CLIENT; $activity->activity_type_id = ACTIVITY_TYPE_CREATE_CLIENT;
$activity->message = Utils::encodeActivity(Auth::user(), 'created', $client); $activity->message = Utils::encodeActivity(Auth::user(), 'created', $client);
$activity->save(); $activity->save();
if ($notify)
{
Activity::checkSubscriptions(EVENT_CREATE_CLIENT, $client);
}
} }
public static function updateClient($client) public static function updateClient($client)
@ -129,6 +134,8 @@ class Activity extends Eloquent
$activity->balance = $client->balance; $activity->balance = $client->balance;
$activity->adjustment = $adjustment; $activity->adjustment = $adjustment;
$activity->save(); $activity->save();
Activity::checkSubscriptions($invoice->is_quote ? EVENT_CREATE_QUOTE : EVENT_CREATE_INVOICE, $invoice);
} }
public static function archiveInvoice($invoice) public static function archiveInvoice($invoice)
@ -290,6 +297,8 @@ class Activity extends Eloquent
$activity->balance = $client->balance; $activity->balance = $client->balance;
$activity->adjustment = $payment->amount * -1; $activity->adjustment = $payment->amount * -1;
$activity->save(); $activity->save();
Activity::checkSubscriptions(EVENT_CREATE_PAYMENT, $payment);
} }
public static function updatePayment($payment) public static function updatePayment($payment)
@ -429,4 +438,14 @@ class Activity extends Eloquent
$activity->balance = $credit->client->balance; $activity->balance = $credit->client->balance;
$activity->save(); $activity->save();
} }
private static function checkSubscriptions($event, $data)
{
$subscription = Auth::user()->account->getSubscription($event);
if ($subscription)
{
Utils::notifyZapier($subscription, $data);
}
}
} }

View File

@ -0,0 +1,7 @@
<?php
class Subscription extends Eloquent
{
public $timestamps = true;
protected $softDelete = true;
}

View File

@ -51,7 +51,7 @@ class User extends ConfideUser implements UserInterface, RemindableInterface
* @return mixed * @return mixed
*/ */
public function getAuthIdentifier() public function getAuthIdentifier()
{ {
return $this->getKey(); return $this->getKey();
} }
@ -173,5 +173,5 @@ class User extends ConfideUser implements UserInterface, RemindableInterface
public function getRememberTokenName() public function getRememberTokenName()
{ {
return 'remember_token'; return 'remember_token';
} }
} }

View File

@ -32,13 +32,22 @@ class ClientRepository
return $query; return $query;
} }
public function save($publicId, $data) public function save($publicId, $data, $notify = true)
{ {
if ($publicId == "-1") $contact = isset($data['contacts']) ? (array)$data['contacts'][0] : (isset($data['contact']) ? $data['contact'] : []);
$validator = \Validator::make($contact, ['email' => 'required|email']);
if ($validator->fails()) {
dd($validator->messages());
return false;
}
if (!$publicId || $publicId == "-1")
{ {
$client = Client::createNew(); $client = Client::createNew();
$client->currency_id = 1;
$contact = Contact::createNew(); $contact = Contact::createNew();
$contact->is_primary = true; $contact->is_primary = true;
$contact->send_invoice = true;
} }
else else
{ {
@ -46,66 +55,128 @@ class ClientRepository
$contact = $client->contacts()->where('is_primary', '=', true)->firstOrFail(); $contact = $client->contacts()->where('is_primary', '=', true)->firstOrFail();
} }
if (isset($data['name'])) {
$client->name = trim($data['name']);
}
if (isset($data['work_phone'])) {
$client->work_phone = trim($data['work_phone']);
}
if (isset($data['custom_value1'])) {
$client->custom_value1 = trim($data['custom_value1']);
}
if (isset($data['custom_value2'])) {
$client->custom_value2 = trim($data['custom_value2']);
}
if (isset($data['address1'])) {
$client->address1 = trim($data['address1']);
}
if (isset($data['address2'])) {
$client->address2 = trim($data['address2']);
}
if (isset($data['city'])) {
$client->city = trim($data['city']);
}
if (isset($data['state'])) {
$client->state = trim($data['state']);
}
if (isset($data['postal_code'])) {
$client->postal_code = trim($data['postal_code']);
}
if (isset($data['country_id'])) {
$client->country_id = $data['country_id'] ? $data['country_id'] : null;
}
if (isset($data['private_notes'])) {
$client->private_notes = trim($data['private_notes']);
}
if (isset($data['size_id'])) {
$client->size_id = $data['size_id'] ? $data['size_id'] : null;
}
if (isset($data['industry_id'])) {
$client->industry_id = $data['industry_id'] ? $data['industry_id'] : null;
}
if (isset($data['currency_id'])) {
$client->currency_id = $data['currency_id'] ? $data['currency_id'] : 1;
}
if (isset($data['payment_terms'])) {
$client->payment_terms = $data['payment_terms'];
}
if (isset($data['website'])) {
$client->website = trim($data['website']);
}
$client->name = trim($data['name']);
$client->work_phone = trim($data['work_phone']);
$client->custom_value1 = trim($data['custom_value1']);
$client->custom_value2 = trim($data['custom_value2']);
$client->address1 = trim($data['address1']);
$client->address2 = trim($data['address2']);
$client->city = trim($data['city']);
$client->state = trim($data['state']);
$client->postal_code = trim($data['postal_code']);
$client->country_id = $data['country_id'] ? $data['country_id'] : null;
$client->private_notes = trim($data['private_notes']);
$client->size_id = $data['size_id'] ? $data['size_id'] : null;
$client->industry_id = $data['industry_id'] ? $data['industry_id'] : null;
$client->currency_id = $data['currency_id'] ? $data['currency_id'] : 1;
$client->payment_terms = $data['payment_terms'];
$client->website = trim($data['website']);
$client->save(); $client->save();
$isPrimary = true; $isPrimary = true;
$contactIds = []; $contactIds = [];
foreach ($data['contacts'] as $record) if (isset($data['contact']))
{ {
$record = (array) $record; $info = $data['contact'];
if (isset($info['email'])) {
if ($publicId != "-1" && isset($record['public_id']) && $record['public_id']) $contact->email = trim(strtolower($info['email']));
{
$contact = Contact::scope($record['public_id'])->firstOrFail();
} }
else if (isset($info['first_name'])) {
{ $contact->first_name = trim($info['first_name']);
$contact = Contact::createNew();
} }
if (isset($info['last_name'])) {
$contact->email = trim(strtolower($record['email'])); $contact->last_name = trim($info['last_name']);
$contact->first_name = trim($record['first_name']); }
$contact->last_name = trim($record['last_name']); if (isset($info['phone'])) {
$contact->phone = trim($record['phone']); $contact->phone = trim($info['phone']);
$contact->is_primary = $isPrimary; }
$contact->send_invoice = $record['send_invoice']; $contact->is_primary = true;
$isPrimary = false; $contact->send_invoice = true;
$client->contacts()->save($contact); $client->contacts()->save($contact);
$contactIds[] = $contact->public_id;
} }
else
foreach ($client->contacts as $contact)
{ {
if (!in_array($contact->public_id, $contactIds)) foreach ($data['contacts'] as $record)
{ {
$contact->delete(); $record = (array) $record;
if ($publicId != "-1" && isset($record['public_id']) && $record['public_id'])
{
$contact = Contact::scope($record['public_id'])->firstOrFail();
}
else
{
$contact = Contact::createNew();
}
if (isset($record['email'])) {
$contact->email = trim(strtolower($record['email']));
}
if (isset($record['first_name'])) {
$contact->first_name = trim($record['first_name']);
}
if (isset($record['last_name'])) {
$contact->last_name = trim($record['last_name']);
}
if (isset($record['phone'])) {
$contact->phone = trim($record['phone']);
}
$contact->is_primary = $isPrimary;
$contact->send_invoice = isset($record['send_invoice']) ? $record['send_invoice'] : true;
$isPrimary = false;
$client->contacts()->save($contact);
$contactIds[] = $contact->public_id;
}
foreach ($client->contacts as $contact)
{
if (!in_array($contact->public_id, $contactIds))
{
$contact->delete();
}
} }
} }
$client->save(); $client->save();
if ($publicId == "-1") if (!$publicId || $publicId == "-1")
{ {
\Activity::createClient($client); \Activity::createClient($client, $notify);
} }
return $client; return $client;

View File

@ -154,30 +154,30 @@ class InvoiceRepository
{ {
$contact = (array) $input->client->contacts[0]; $contact = (array) $input->client->contacts[0];
$rules = ['email' => 'required|email']; $rules = ['email' => 'required|email'];
$validator = \Validator::make($contact, $rules); $validator = \Validator::make($contact, $rules);
if ($validator->fails()) if ($validator->fails())
{ {
return $validator; return $validator;
} }
$invoice = (array) $input; $invoice = (array) $input;
$invoiceId = isset($invoice['public_id']) && $invoice['public_id'] ? Invoice::getPrivateId($invoice['public_id']) : null; $invoiceId = isset($invoice['public_id']) && $invoice['public_id'] ? Invoice::getPrivateId($invoice['public_id']) : null;
$rules = ['invoice_number' => 'required|unique:invoices,invoice_number,' . $invoiceId . ',id,account_id,' . \Auth::user()->account_id]; $rules = ['invoice_number' => 'required|unique:invoices,invoice_number,' . $invoiceId . ',id,account_id,' . \Auth::user()->account_id];
if ($invoice['is_recurring'] && $invoice['start_date'] && $invoice['end_date']) if ($invoice['is_recurring'] && $invoice['start_date'] && $invoice['end_date'])
{ {
$rules['end_date'] = 'after:' . $invoice['start_date']; $rules['end_date'] = 'after:' . $invoice['start_date'];
} }
$validator = \Validator::make($invoice, $rules); $validator = \Validator::make($invoice, $rules);
if ($validator->fails()) if ($validator->fails())
{ {
return $validator; return $validator;
} }
return false; return false;
} }
public function save($publicId, $data, $entityType) public function save($publicId, $data, $entityType)

View File

@ -1,5 +1,6 @@
<?php <?php
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Application Routes | Application Routes
@ -22,6 +23,7 @@
//dd(gethostname()); //dd(gethostname());
//Log::error('test'); //Log::error('test');
Route::get('/', 'HomeController@showIndex'); Route::get('/', 'HomeController@showIndex');
Route::get('/rocksteady', 'HomeController@showIndex'); Route::get('/rocksteady', 'HomeController@showIndex');
Route::get('/about', 'HomeController@showAboutUs'); Route::get('/about', 'HomeController@showAboutUs');
@ -123,12 +125,20 @@ Route::group(array('before' => 'auth'), function()
Route::post('credits/bulk', 'CreditController@bulk'); Route::post('credits/bulk', 'CreditController@bulk');
}); });
// Route group for API versioning // Route group for API
Route::group(array('prefix' => 'api/v1', 'before' => 'auth.basic'), function() Route::group(array('prefix' => 'api/v1', 'before' => 'auth.basic'), function()
{ {
Route::resource('clients', 'ClientApiController'); Route::resource('ping', 'ClientApiController@ping');
Route::resource('clients', 'ClientApiController');
Route::resource('invoices', 'InvoiceApiController');
Route::resource('quotes', 'QuoteApiController');
Route::resource('payments', 'PaymentApiController');
}); });
Route::group(array('before' => 'auth.basic'), function()
{
Route::post('api/hooks', 'IntegrationController@subscribe');
});
define('CONTACT_EMAIL', 'contact@invoiceninja.com'); define('CONTACT_EMAIL', 'contact@invoiceninja.com');
define('CONTACT_NAME', 'Invoice Ninja'); define('CONTACT_NAME', 'Invoice Ninja');
@ -215,12 +225,17 @@ define('GATEWAY_PAYPAL_EXPRESS', 17);
define('GATEWAY_BEANSTREAM', 29); define('GATEWAY_BEANSTREAM', 29);
define('GATEWAY_PSIGATE', 30); define('GATEWAY_PSIGATE', 30);
define('EVENT_CREATE_CLIENT', 1);
define('EVENT_CREATE_INVOICE', 2);
define('EVENT_CREATE_QUOTE', 3);
define('EVENT_CREATE_PAYMENT', 4);
define('REQUESTED_PRO_PLAN', 'REQUESTED_PRO_PLAN'); define('REQUESTED_PRO_PLAN', 'REQUESTED_PRO_PLAN');
define('NINJA_ACCOUNT_KEY', 'zg4ylmzDkdkPOT8yoKQw9LTWaoZJx79h'); define('NINJA_ACCOUNT_KEY', 'zg4ylmzDkdkPOT8yoKQw9LTWaoZJx79h');
define('NINJA_GATEWAY_ID', GATEWAY_AUTHORIZE_NET); define('NINJA_GATEWAY_ID', GATEWAY_AUTHORIZE_NET);
define('NINJA_GATEWAY_CONFIG', '{"apiLoginId":"626vWcD5","transactionKey":"4bn26TgL9r4Br4qJ","testMode":"","developerMode":""}'); define('NINJA_GATEWAY_CONFIG', '{"apiLoginId":"626vWcD5","transactionKey":"4bn26TgL9r4Br4qJ","testMode":"","developerMode":""}');
define('NINJA_URL', 'https://www.invoiceninja.com'); define('NINJA_URL', 'https://www.invoiceninja.com');
define('NINJA_VERSION', '1.3.0'); define('NINJA_VERSION', '1.3.1');
define('PRO_PLAN_PRICE', 50); define('PRO_PLAN_PRICE', 50);
define('LICENSE_PRICE', 30); define('LICENSE_PRICE', 30);
@ -380,3 +395,5 @@ if (Auth::check() && Auth::user()->id === 1)
} }
*/ */

View File

@ -63,6 +63,10 @@ App::error(function(Exception $exception, $code)
Utils::logError($exception . ' ' . $code); Utils::logError($exception . ' ' . $code);
return Response::view('error', ['hideHeader' => true, 'error' => "A {$code} error occurred."], $code); return Response::view('error', ['hideHeader' => true, 'error' => "A {$code} error occurred."], $code);
} }
else if (Utils::isNinjaDev())
{
return "{$exception->getFile()}:{$exception->getLine()} => {$exception->getMessage()}";
}
else else
{ {
return null; return null;

View File

@ -57,7 +57,7 @@
'password_confirmation' => 'required', 'password_confirmation' => 'required',
)); }} )); }}
<h2 class="form-signin-heading">Set Passord</h2><p/>&nbsp; <h2 class="form-signin-heading">Set Password</h2><p/>&nbsp;
<input type="hidden" name="token" value="{{{ $token }}}"> <input type="hidden" name="token" value="{{{ $token }}}">
<p> <p>

View File

@ -32,6 +32,14 @@ if (!function_exists('gethostname')) {
} }
} }
// Fortrabbit HTTP AUTH CODE
if (!empty($_SERVER['REMOTE_USER'])) {
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(
':',
base64_decode(substr($_SERVER['REMOTE_USER'], 6))
);
}
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

594
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -5,4 +5,7 @@
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L] RewriteRule ^ index.php [L]
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]
</IfModule> </IfModule>