mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Working on the API
This commit is contained in:
parent
c130e67e54
commit
6130626422
@ -7,7 +7,7 @@ use Input;
|
|||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Account;
|
use App\Models\Account;
|
||||||
use App\Ninja\Repositories\AccountRepository;
|
use App\Ninja\Repositories\AccountRepository;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use League\Fractal;
|
use League\Fractal;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
use League\Fractal\Manager;
|
use League\Fractal\Manager;
|
||||||
@ -23,6 +23,19 @@ class AccountApiController extends Controller
|
|||||||
$this->accountRepo = $accountRepo;
|
$this->accountRepo = $accountRepo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function login(Request $request)
|
||||||
|
{
|
||||||
|
if ( ! env(API_SECRET) || $request->api_secret !== env(API_SECRET)) {
|
||||||
|
return 'Invalid secret';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Auth::attempt(['email' => $request->email, 'password' => $request->password])) {
|
||||||
|
return $this->accountRepo->createToken($request->token_name);
|
||||||
|
} else {
|
||||||
|
return 'Invalid credentials';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$manager = new Manager();
|
$manager = new Manager();
|
||||||
|
@ -98,13 +98,6 @@ class AuthController extends Controller {
|
|||||||
$users = $this->accountRepo->loadAccounts(Auth::user()->id);
|
$users = $this->accountRepo->loadAccounts(Auth::user()->id);
|
||||||
}
|
}
|
||||||
Session::put(SESSION_USER_ACCOUNTS, $users);
|
Session::put(SESSION_USER_ACCOUNTS, $users);
|
||||||
|
|
||||||
if ($request->create_token) {
|
|
||||||
if ( ! env(API_SECRET) || $request->api_secret !== env(API_SECRET)) {
|
|
||||||
return 'Invalid secret';
|
|
||||||
}
|
|
||||||
return $this->accountRepo->createToken($request->token_name);
|
|
||||||
}
|
|
||||||
} elseif ($user) {
|
} elseif ($user) {
|
||||||
$user->failed_logins = $user->failed_logins + 1;
|
$user->failed_logins = $user->failed_logins + 1;
|
||||||
$user->save();
|
$user->save();
|
||||||
|
@ -109,6 +109,7 @@ class DashboardController extends BaseController
|
|||||||
->leftJoin('contacts', 'contacts.client_id', '=', 'clients.id')
|
->leftJoin('contacts', 'contacts.client_id', '=', 'clients.id')
|
||||||
->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id')
|
->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id')
|
||||||
->where('payments.account_id', '=', Auth::user()->account_id)
|
->where('payments.account_id', '=', Auth::user()->account_id)
|
||||||
|
->where('payments.deleted_at', '=', null)
|
||||||
->where('clients.deleted_at', '=', null)
|
->where('clients.deleted_at', '=', null)
|
||||||
->where('contacts.deleted_at', '=', null)
|
->where('contacts.deleted_at', '=', null)
|
||||||
->where('contacts.is_primary', '=', true)
|
->where('contacts.is_primary', '=', true)
|
||||||
|
@ -528,7 +528,7 @@ class PaymentController extends BaseController
|
|||||||
if (method_exists($gateway, 'completePurchase') && !$accountGateway->isGateway(GATEWAY_TWO_CHECKOUT)) {
|
if (method_exists($gateway, 'completePurchase') && !$accountGateway->isGateway(GATEWAY_TWO_CHECKOUT)) {
|
||||||
$details = $this->paymentService->getPaymentDetails($invitation, $accountGateway);
|
$details = $this->paymentService->getPaymentDetails($invitation, $accountGateway);
|
||||||
$response = $gateway->completePurchase($details)->send();
|
$response = $gateway->completePurchase($details)->send();
|
||||||
$ref = $response->getTransactionReference();
|
$ref = $response->getTransactionReference() ?: $token;
|
||||||
|
|
||||||
if ($response->isSuccessful()) {
|
if ($response->isSuccessful()) {
|
||||||
$payment = $this->paymentService->createPayment($invitation, $ref, $payerId);
|
$payment = $this->paymentService->createPayment($invitation, $ref, $payerId);
|
||||||
|
@ -21,33 +21,38 @@ class ApiCheck {
|
|||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle($request, Closure $next)
|
||||||
{
|
{
|
||||||
|
$loggingIn = $request->is('api/v1/login');
|
||||||
$headers = Utils::getApiHeaders();
|
$headers = Utils::getApiHeaders();
|
||||||
|
|
||||||
// check for a valid token
|
if ($loggingIn) {
|
||||||
$token = AccountToken::where('token', '=', Request::header('X-Ninja-Token'))->first(['id', 'user_id']);
|
// do nothing
|
||||||
|
|
||||||
if ($token) {
|
|
||||||
Auth::loginUsingId($token->user_id);
|
|
||||||
Session::set('token_id', $token->id);
|
|
||||||
} else {
|
} else {
|
||||||
sleep(3);
|
// check for a valid token
|
||||||
return Response::make('Invalid token', 403, $headers);
|
$token = AccountToken::where('token', '=', Request::header('X-Ninja-Token'))->first(['id', 'user_id']);
|
||||||
|
|
||||||
|
if ($token) {
|
||||||
|
Auth::loginUsingId($token->user_id);
|
||||||
|
Session::set('token_id', $token->id);
|
||||||
|
} else {
|
||||||
|
sleep(3);
|
||||||
|
return Response::make('Invalid token', 403, $headers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Utils::isNinja()) {
|
if (!Utils::isNinja() && !$loggingIn) {
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Utils::isPro()) {
|
if (!Utils::isPro() && !$loggingIn) {
|
||||||
return Response::make('API requires pro plan', 403, $headers);
|
return Response::make('API requires pro plan', 403, $headers);
|
||||||
} else {
|
} else {
|
||||||
$accountId = Auth::user()->account->id;
|
$key = Auth::check() ? Auth::user()->account->id : $request->getClientIp();
|
||||||
|
|
||||||
// http://stackoverflow.com/questions/1375501/how-do-i-throttle-my-sites-api-users
|
// http://stackoverflow.com/questions/1375501/how-do-i-throttle-my-sites-api-users
|
||||||
$hour = 60 * 60;
|
$hour = 60 * 60;
|
||||||
$hour_limit = 100; # users are limited to 100 requests/hour
|
$hour_limit = 100; # users are limited to 100 requests/hour
|
||||||
$hour_throttle = Cache::get("hour_throttle:{$accountId}", null);
|
$hour_throttle = Cache::get("hour_throttle:{$key}", null);
|
||||||
$last_api_request = Cache::get("last_api_request:{$accountId}", 0);
|
$last_api_request = Cache::get("last_api_request:{$key}", 0);
|
||||||
$last_api_diff = time() - $last_api_request;
|
$last_api_diff = time() - $last_api_request;
|
||||||
|
|
||||||
if (is_null($hour_throttle)) {
|
if (is_null($hour_throttle)) {
|
||||||
@ -66,11 +71,10 @@ class ApiCheck {
|
|||||||
return Response::make("Please wait {$wait} second(s)", 403, $headers);
|
return Response::make("Please wait {$wait} second(s)", 403, $headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cache::put("hour_throttle:{$accountId}", $new_hour_throttle, 10);
|
Cache::put("hour_throttle:{$key}", $new_hour_throttle, 10);
|
||||||
Cache::put("last_api_request:{$accountId}", time(), 10);
|
Cache::put("last_api_request:{$key}", time(), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ class VerifyCsrfToken extends BaseVerifier {
|
|||||||
|
|
||||||
private $openRoutes = [
|
private $openRoutes = [
|
||||||
'signup/register',
|
'signup/register',
|
||||||
|
'api/v1/login',
|
||||||
'api/v1/clients',
|
'api/v1/clients',
|
||||||
'api/v1/invoices',
|
'api/v1/invoices',
|
||||||
'api/v1/quotes',
|
'api/v1/quotes',
|
||||||
@ -34,12 +35,6 @@ class VerifyCsrfToken extends BaseVerifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($request->is('login')) {
|
|
||||||
if (env(API_SECRET) && $request->api_secret === env(API_SECRET)) {
|
|
||||||
return $next($request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent::handle($request, $next);
|
return parent::handle($request, $next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,10 +186,11 @@ Route::group(['middleware' => 'auth'], function() {
|
|||||||
get('/resend_confirmation', 'AccountController@resendConfirmation');
|
get('/resend_confirmation', 'AccountController@resendConfirmation');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route group for API
|
// Route groups for API
|
||||||
Route::group(['middleware' => 'api', 'prefix' => 'api/v1'], function()
|
Route::group(['middleware' => 'api', 'prefix' => 'api/v1'], function()
|
||||||
{
|
{
|
||||||
Route::resource('ping', 'ClientApiController@ping');
|
Route::resource('ping', 'ClientApiController@ping');
|
||||||
|
Route::post('login', 'AccountApiController@login');
|
||||||
Route::get('accounts', 'AccountApiController@index');
|
Route::get('accounts', 'AccountApiController@index');
|
||||||
Route::resource('clients', 'ClientApiController');
|
Route::resource('clients', 'ClientApiController');
|
||||||
Route::get('quotes/{client_id?}', 'QuoteApiController@index');
|
Route::get('quotes/{client_id?}', 'QuoteApiController@index');
|
||||||
|
@ -459,8 +459,14 @@ class AccountRepository
|
|||||||
|
|
||||||
public function createToken($name)
|
public function createToken($name)
|
||||||
{
|
{
|
||||||
|
$name = trim($name) ?: 'TOKEN';
|
||||||
|
|
||||||
|
if ($token = AccountToken::scope()->whereName($name)->first()) {
|
||||||
|
return $token->token;
|
||||||
|
}
|
||||||
|
|
||||||
$token = AccountToken::createNew();
|
$token = AccountToken::createNew();
|
||||||
$token->name = trim($name) ?: 'TOKEN';
|
$token->name = $name;
|
||||||
$token->token = str_random(RANDOM_KEY_LENGTH);
|
$token->token = str_random(RANDOM_KEY_LENGTH);
|
||||||
$token->save();
|
$token->save();
|
||||||
|
|
||||||
|
@ -39,15 +39,15 @@ If you'd like to use our code to sell your own invoicing app email us for detail
|
|||||||
* [Support Forum](https://www.invoiceninja.com/forums/forum/support/)
|
* [Support Forum](https://www.invoiceninja.com/forums/forum/support/)
|
||||||
* [Feature Roadmap](https://trello.com/b/63BbiVVe/)
|
* [Feature Roadmap](https://trello.com/b/63BbiVVe/)
|
||||||
|
|
||||||
### Recommended Providers
|
|
||||||
* [Stripe](https://stripe.com/)
|
|
||||||
* [Postmark](https://postmarkapp.com/)
|
|
||||||
|
|
||||||
### Contributors
|
### Contributors
|
||||||
* [Troels Liebe Bentsen](https://github.com/tlbdk)
|
* [Troels Liebe Bentsen](https://github.com/tlbdk)
|
||||||
* [Jeramy Simpson](https://github.com/JeramyMywork) - [MyWork](https://www.mywork.com.au)
|
* [Jeramy Simpson](https://github.com/JeramyMywork) - [MyWork](https://www.mywork.com.au)
|
||||||
* [Sigitas Limontas](https://lt.linkedin.com/in/sigitaslimontas)
|
* [Sigitas Limontas](https://lt.linkedin.com/in/sigitaslimontas)
|
||||||
|
|
||||||
|
### Recommended Providers
|
||||||
|
* [Stripe](https://stripe.com/)
|
||||||
|
* [Postmark](https://postmarkapp.com/)
|
||||||
|
|
||||||
### Frameworks/Libraries
|
### Frameworks/Libraries
|
||||||
* [laravel/laravel](https://github.com/laravel/laravel) - A PHP Framework For Web Artisans
|
* [laravel/laravel](https://github.com/laravel/laravel) - A PHP Framework For Web Artisans
|
||||||
* [twbs/bootstrap](https://github.com/twbs/bootstrap) - Sleek, intuitive, and powerful front-end framework for faster and easier web development.
|
* [twbs/bootstrap](https://github.com/twbs/bootstrap) - Sleek, intuitive, and powerful front-end framework for faster and easier web development.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user