Initial Spark Install
This commit is contained in:
102
spark/src/Http/Controllers/Auth/EmergencyLoginController.php
Normal file
102
spark/src/Http/Controllers/Auth/EmergencyLoginController.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Auth;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Foundation\Auth\RedirectsUsers;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\Security\DisableTwoFactorAuth;
|
||||
|
||||
class EmergencyLoginController extends Controller
|
||||
{
|
||||
use RedirectsUsers;
|
||||
|
||||
/**
|
||||
* Create a new emergency login controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
|
||||
$this->middleware('throttle:3,1')->only('login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form to login via the emergency token.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function showLoginForm(Request $request)
|
||||
{
|
||||
return $request->session()->has('spark:auth:id')
|
||||
? view('spark::auth.login-via-emergency-token')
|
||||
: redirect('login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Login via the emergency token.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function login(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'token' => 'required',
|
||||
]);
|
||||
|
||||
// If there is no authentication ID stored in the session, it means that the user
|
||||
// hasn't made it through the login screen so we'll just redirect them back to
|
||||
// the login view. They must have hit the route manually via a specific URL.
|
||||
if (! $request->session()->has('spark:auth:id')) {
|
||||
return redirect('login');
|
||||
}
|
||||
|
||||
$user = Spark::user()->findOrFail(
|
||||
$request->session()->pull('spark:auth:id')
|
||||
);
|
||||
|
||||
// Here we will check this hash of the token against the stored hash of the reset
|
||||
// token to make sure they match. If they don't match then the emergency token
|
||||
// is invalid so we'll redirect back out with an error message for the user.
|
||||
$resetCode = $user->two_factor_reset_code;
|
||||
|
||||
if (! Hash::check($request->token, $resetCode)) {
|
||||
return redirect('login')->withErrors([
|
||||
'token' => 'The emergency token was invalid.'
|
||||
]);
|
||||
}
|
||||
|
||||
// If the token was valid we will login this user after disabling the two-factor
|
||||
// authentication settings so that they don't get stuck again. They will then
|
||||
// re-enable two-factor authentication in their settings if they so choose.
|
||||
$this->disableTwoFactorAuth($user);
|
||||
|
||||
Auth::login($user, $request->session()->pull(
|
||||
'spark:auth:remember', false
|
||||
));
|
||||
|
||||
return redirect()->intended($this->redirectPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable two-factor authentication for the given user.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @return void
|
||||
*/
|
||||
protected function disableTwoFactorAuth($user)
|
||||
{
|
||||
Spark::interact(DisableTwoFactorAuth::class, [$user]);
|
||||
|
||||
$user->forceFill([
|
||||
'uses_two_factor_auth' => false,
|
||||
])->save();
|
||||
}
|
||||
}
|
159
spark/src/Http/Controllers/Auth/LoginController.php
Normal file
159
spark/src/Http/Controllers/Auth/LoginController.php
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Auth;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\Security\VerifyTwoFactorAuthToken as Verify;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
use AuthenticatesUsers {
|
||||
AuthenticatesUsers::login as traitLogin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new login controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest')->except('logout');
|
||||
|
||||
$this->redirectTo = Spark::afterLoginRedirect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application login form.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function showLoginForm()
|
||||
{
|
||||
return view('spark::auth.login');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function login(Request $request)
|
||||
{
|
||||
if ($request->filled('remember')) {
|
||||
$request->session()->put('spark:auth-remember', $request->remember);
|
||||
}
|
||||
|
||||
$user = Spark::user()->where('email', $request->email)->first();
|
||||
|
||||
if (Spark::usesTwoFactorAuth() && $user && $user->uses_two_factor_auth) {
|
||||
$request->merge(['remember' => '']);
|
||||
}
|
||||
|
||||
return $this->traitLogin($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a successful authentication attempt.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @return Response
|
||||
*/
|
||||
public function authenticated(Request $request, $user)
|
||||
{
|
||||
if (Spark::usesTwoFactorAuth() && $user->uses_two_factor_auth) {
|
||||
return $this->redirectForTwoFactorAuth($request, $user);
|
||||
}
|
||||
|
||||
return redirect()->intended($this->redirectPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect the user for two-factor authentication.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @return Response
|
||||
*/
|
||||
protected function redirectForTwoFactorAuth(Request $request, $user)
|
||||
{
|
||||
Auth::logout();
|
||||
|
||||
// Before we redirect the user to the two-factor token verification screen we will
|
||||
// store this user's ID and "remember me" choice in the session so that we will
|
||||
// be able to get it back out and log in the correct user after verification.
|
||||
$request->session()->put([
|
||||
'spark:auth:id' => $user->id,
|
||||
'spark:auth:remember' => $request->remember,
|
||||
]);
|
||||
|
||||
return redirect('login/token');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the two-factor authentication token form.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function showTokenForm(Request $request)
|
||||
{
|
||||
return $request->session()->has('spark:auth:id')
|
||||
? view('spark::auth.token') : redirect('login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the given authentication token.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function verifyToken(Request $request)
|
||||
{
|
||||
$this->validate($request, ['token' => 'required']);
|
||||
|
||||
// If there is no authentication ID stored in the session, it means that the user
|
||||
// hasn't made it through the login screen so we'll just redirect them back to
|
||||
// the login view. They must have hit the route manually via a specific URL.
|
||||
if (! $request->session()->has('spark:auth:id')) {
|
||||
return redirect('login');
|
||||
}
|
||||
|
||||
$user = Spark::user()->findOrFail(
|
||||
$request->session()->pull('spark:auth:id')
|
||||
);
|
||||
|
||||
// Next, we'll verify the actual token with our two-factor authentication service
|
||||
// to see if the token is valid. If it is, we can login the user and send them
|
||||
// to their intended location within the protected part of this application.
|
||||
if (Spark::interact(Verify::class, [$user, $request->token])) {
|
||||
Auth::login($user, $request->session()->pull(
|
||||
'spark:auth:remember', false
|
||||
));
|
||||
|
||||
return redirect()->intended($this->redirectPath());
|
||||
} else {
|
||||
return back();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the user out of the application.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
$this->guard()->logout();
|
||||
|
||||
session()->flush();
|
||||
|
||||
return redirect(
|
||||
property_exists($this, 'redirectAfterLogout')
|
||||
? $this->redirectAfterLogout : '/'
|
||||
);
|
||||
}
|
||||
}
|
59
spark/src/Http/Controllers/Auth/PasswordController.php
Normal file
59
spark/src/Http/Controllers/Auth/PasswordController.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Auth;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
|
||||
class PasswordController extends Controller
|
||||
{
|
||||
use SendsPasswordResetEmails, ResetsPasswords {
|
||||
SendsPasswordResetEmails::broker insteadof ResetsPasswords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new password controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
|
||||
$this->middleware('throttle:3,1')->only('sendResetLinkEmail', 'reset');
|
||||
|
||||
$this->redirectTo = Spark::afterLoginRedirect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the form to request a password reset link.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function showLinkRequestForm()
|
||||
{
|
||||
return view('spark::auth.passwords.email');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the password reset view for the given token.
|
||||
*
|
||||
* If no token is present, display the link request form.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string|null $token
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function showResetForm(Request $request, $token = null)
|
||||
{
|
||||
if (is_null($token)) {
|
||||
return $this->showLinkRequestForm();
|
||||
}
|
||||
|
||||
return view('spark::auth.passwords.reset')
|
||||
->with(['token' => $token, 'email' => $request->email]);
|
||||
}
|
||||
}
|
68
spark/src/Http/Controllers/Auth/RegisterController.php
Normal file
68
spark/src/Http/Controllers/Auth/RegisterController.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Auth;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Laravel\Spark\Events\Auth\UserRegistered;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\RedirectsUsers;
|
||||
use Laravel\Spark\Contracts\Interactions\Auth\Register;
|
||||
use Laravel\Spark\Contracts\Http\Requests\Auth\RegisterRequest;
|
||||
|
||||
class RegisterController extends Controller
|
||||
{
|
||||
use RedirectsUsers;
|
||||
|
||||
/**
|
||||
* Create a new authentication controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
|
||||
$this->redirectTo = Spark::afterLoginRedirect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application registration form.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function showRegistrationForm(Request $request)
|
||||
{
|
||||
if (Spark::promotion() && ! $request->filled('coupon')) {
|
||||
// If the application is running a site-wide promotion, we will redirect the user
|
||||
// to a register URL that contains the promotional coupon ID, which will force
|
||||
// all new registrations to use this coupon when creating the subscriptions.
|
||||
return redirect($request->fullUrlWithQuery([
|
||||
'coupon' => Spark::promotion()
|
||||
]));
|
||||
}
|
||||
|
||||
return view('spark::auth.register');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a registration request for the application.
|
||||
*
|
||||
* @param RegisterRequest $request
|
||||
* @return Response
|
||||
*/
|
||||
public function register(RegisterRequest $request)
|
||||
{
|
||||
Auth::login($user = Spark::interact(
|
||||
Register::class, [$request]
|
||||
));
|
||||
|
||||
event(new UserRegistered($user));
|
||||
|
||||
return response()->json([
|
||||
'redirect' => $this->redirectPath()
|
||||
]);
|
||||
}
|
||||
}
|
30
spark/src/Http/Controllers/Controller.php
Normal file
30
spark/src/Http/Controllers/Controller.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use ValidatesRequests;
|
||||
|
||||
/**
|
||||
* Execute the given interaction.
|
||||
*
|
||||
* This performs the common validate and handle flow of some interactions.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $interaction
|
||||
* @param array $parameters
|
||||
* @return void
|
||||
*/
|
||||
public function interaction(Request $request, $interaction, array $parameters)
|
||||
{
|
||||
Spark::interact($interaction.'@validator', $parameters)->validate();
|
||||
|
||||
return Spark::interact($interaction, $parameters);
|
||||
}
|
||||
}
|
63
spark/src/Http/Controllers/CouponController.php
Normal file
63
spark/src/Http/Controllers/CouponController.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Contracts\Repositories\CouponRepository;
|
||||
|
||||
class CouponController extends Controller
|
||||
{
|
||||
/**
|
||||
* The coupon repository implementation.
|
||||
*
|
||||
* @var \Laravel\Spark\Contracts\Repositories\CouponRepository
|
||||
*/
|
||||
protected $coupons;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \Laravel\Spark\Contracts\Repositories\CouponRepository $coupons
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(CouponRepository $coupons)
|
||||
{
|
||||
$this->coupons = $coupons;
|
||||
|
||||
$this->middleware('auth', ['only' => 'current']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified coupon from Stripe.
|
||||
*
|
||||
* This is used during registration to show the discount.
|
||||
*
|
||||
* @param string $code
|
||||
* @return Response
|
||||
*/
|
||||
public function show($code)
|
||||
{
|
||||
$coupon = $this->coupons->find($code);
|
||||
|
||||
return $coupon ? response()->json($coupon->toArray()) : abort(404);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current discount for the given user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $userId
|
||||
* @return Response
|
||||
*/
|
||||
public function current(Request $request, $userId)
|
||||
{
|
||||
$user = Spark::user()->where('id', $userId)->firstOrFail();
|
||||
|
||||
if ($coupon = $this->coupons->forBillable($user)) {
|
||||
return response()->json($coupon->toArray());
|
||||
}
|
||||
|
||||
abort(204);
|
||||
}
|
||||
}
|
43
spark/src/Http/Controllers/GeocodingController.php
Normal file
43
spark/src/Http/Controllers/GeocodingController.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use GuzzleHttp\Client as HttpClient;
|
||||
use Laravel\Spark\Contracts\Repositories\Geography\StateRepository;
|
||||
|
||||
class GeocodingController extends Controller
|
||||
{
|
||||
/**
|
||||
* Attempt to gather the current user's country via Geocoding.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function country(Request $request)
|
||||
{
|
||||
try {
|
||||
$response = (new HttpClient)->get('http://ip2c.org/?ip='.$request->ip());
|
||||
|
||||
$body = (string) $response->getBody();
|
||||
|
||||
if ($body[0] === '1') {
|
||||
return explode(';', $body)[1];
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
return response('', 404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the states / provinces for a given country code.
|
||||
*
|
||||
* @param string $country
|
||||
* @return Response
|
||||
*/
|
||||
public function states($country)
|
||||
{
|
||||
return response()->json(app(StateRepository::class)->forCountry($country)->all());
|
||||
}
|
||||
}
|
29
spark/src/Http/Controllers/InvitationController.php
Normal file
29
spark/src/Http/Controllers/InvitationController.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Laravel\Spark\Invitation;
|
||||
|
||||
class InvitationController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get the given invitation.
|
||||
*
|
||||
* This is used during registration to show the invitation.
|
||||
*
|
||||
* @param string $token
|
||||
* @return Response
|
||||
*/
|
||||
public function show($token)
|
||||
{
|
||||
$invitation = Invitation::with('team')->where('token', $token)->firstOrFail();
|
||||
|
||||
if ($invitation->isExpired()) {
|
||||
$invitation->delete();
|
||||
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return $invitation;
|
||||
}
|
||||
}
|
92
spark/src/Http/Controllers/Kiosk/AnnouncementController.php
Normal file
92
spark/src/Http/Controllers/Kiosk/AnnouncementController.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Kiosk;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Announcement;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Repositories\AnnouncementRepository;
|
||||
|
||||
class AnnouncementController extends Controller
|
||||
{
|
||||
/**
|
||||
* The announcements repository.
|
||||
*
|
||||
* @param \Laravel\Spark\Contracts\Repositories\AnnouncementRepository
|
||||
*/
|
||||
protected $announcements;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \Laravel\Spark\Contracts\Repositories\AnnouncementRepository $announcements
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(AnnouncementRepository $announcements)
|
||||
{
|
||||
$this->announcements = $announcements;
|
||||
|
||||
$this->middleware('auth');
|
||||
$this->middleware('dev');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the application's recent announcements.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return $this->announcements->recent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new announcement.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'body' => 'required',
|
||||
'action_text' => 'required_with:action_url|max:255',
|
||||
'action_url' => 'required_with:action_text',
|
||||
]);
|
||||
|
||||
$this->announcements->create(
|
||||
$request->user(), $request->all()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given announcement.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $id
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'body' => 'required',
|
||||
'action_text' => 'max:255',
|
||||
'action_url' => 'required_with:action_text',
|
||||
]);
|
||||
|
||||
$this->announcements->update(
|
||||
Announcement::findOrFail($id), $request->all()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the announcement with the given ID.
|
||||
*
|
||||
* @param string $id
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
Announcement::findOrFail($id)->delete();
|
||||
}
|
||||
}
|
29
spark/src/Http/Controllers/Kiosk/DashboardController.php
Normal file
29
spark/src/Http/Controllers/Kiosk/DashboardController.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Kiosk;
|
||||
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
$this->middleware('dev');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the kiosk dashboard.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function show()
|
||||
{
|
||||
return view('spark::kiosk');
|
||||
}
|
||||
}
|
53
spark/src/Http/Controllers/Kiosk/DiscountController.php
Normal file
53
spark/src/Http/Controllers/Kiosk/DiscountController.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Kiosk;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Laravel\Cashier\Cashier;
|
||||
use Illuminate\Http\Request;
|
||||
use Stripe\Coupon as StripeCoupon;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class DiscountController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
$this->middleware('dev');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a discount for the given user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $userId
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Request $request, $userId)
|
||||
{
|
||||
$user = Spark::user()->where('id', $userId)->firstOrFail();
|
||||
|
||||
$this->validate($request, [
|
||||
'type' => 'required|in:amount,percent',
|
||||
'value' => 'required|integer',
|
||||
'duration' => 'required|in:once,forever,repeating',
|
||||
'months' => 'required_if:duration,repeating',
|
||||
]);
|
||||
|
||||
$coupon = StripeCoupon::create([
|
||||
'currency' => Cashier::usesCurrency(),
|
||||
'amount_off' => $request->type == 'amount' ? $request->value * 100 : null,
|
||||
'percent_off' => $request->type == 'percent' ? $request->value : null,
|
||||
'duration' => $request->duration,
|
||||
'duration_in_months' => $request->months,
|
||||
'max_redemptions' => 1,
|
||||
], config('services.stripe.secret'));
|
||||
|
||||
$user->applyCoupon($coupon->id);
|
||||
}
|
||||
}
|
79
spark/src/Http/Controllers/Kiosk/ImpersonationController.php
Normal file
79
spark/src/Http/Controllers/Kiosk/ImpersonationController.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Kiosk;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class ImpersonationController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
|
||||
$this->middleware('dev')->except('stopImpersonating');
|
||||
}
|
||||
|
||||
/**
|
||||
* Impersonate the given user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $userId
|
||||
* @return Response
|
||||
*/
|
||||
public function impersonate(Request $request, $userId)
|
||||
{
|
||||
$request->session()->flush();
|
||||
|
||||
// We will store the original user's ID in the session so we can remember who we
|
||||
// actually are when we need to stop impersonating the other user, which will
|
||||
// allow us to pull the original user back out of the database when needed.
|
||||
$request->session()->put(
|
||||
'spark:impersonator', $request->user()->id
|
||||
);
|
||||
|
||||
Auth::login(Spark::user()->findOrFail($userId));
|
||||
|
||||
return redirect('/settings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop impersonating and switch back to primary account.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function stopImpersonating(Request $request)
|
||||
{
|
||||
$currentId = Auth::id();
|
||||
|
||||
// We will make sure we have an impersonator's user ID in the session and if the
|
||||
// value doesn't exist in the session we will log this user out of the system
|
||||
// since they aren't really impersonating anyone and manually hit this URL.
|
||||
if (! $request->session()->has('spark:impersonator')) {
|
||||
Auth::logout();
|
||||
|
||||
return redirect('/');
|
||||
}
|
||||
|
||||
$userId = $request->session()->pull(
|
||||
'spark:impersonator'
|
||||
);
|
||||
|
||||
// After removing the impersonator user's ID from the session so we can retrieve
|
||||
// the original user. Then, we will flush the entire session to clear out any
|
||||
// stale data from while we were doing the impersonation of the other user.
|
||||
$request->session()->flush();
|
||||
|
||||
Auth::login(Spark::user()->findOrFail($userId));
|
||||
|
||||
return redirect('/spark/kiosk#/users/'.$currentId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Kiosk;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Laravel\Spark\Spark;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Repositories\PerformanceIndicatorsRepository;
|
||||
|
||||
class PerformanceIndicatorsController extends Controller
|
||||
{
|
||||
/**
|
||||
* The performance indicators repository instance.
|
||||
*
|
||||
* @var PerformanceIndicatorsRepository
|
||||
*/
|
||||
protected $indicators;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param PerformanceIndicatorsRepository $indicators
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(PerformanceIndicatorsRepository $indicators)
|
||||
{
|
||||
$this->indicators = $indicators;
|
||||
|
||||
$this->middleware('auth');
|
||||
$this->middleware('dev');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the performance indicators for the application.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return response()->json([
|
||||
'indicators' => $this->indicators->all(60),
|
||||
'last_month' => $this->indicators->forDate(Carbon::today()->subMonths(1)),
|
||||
'last_year' => $this->indicators->forDate(Carbon::today()->subYears(1)),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the revenue amounts for the application.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function revenue()
|
||||
{
|
||||
return [
|
||||
'yearlyRecurringRevenue' => $this->indicators->yearlyRecurringRevenue(),
|
||||
'monthlyRecurringRevenue' => $this->indicators->monthlyRecurringRevenue(),
|
||||
'totalVolume' => $this->indicators->totalVolume(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the subscriber counts by plan.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function subscribers()
|
||||
{
|
||||
$plans = [];
|
||||
|
||||
foreach (Spark::allPlans() as $plan) {
|
||||
$plans[] = [
|
||||
'name' => $plan->name,
|
||||
'interval' => $plan->interval,
|
||||
'count' => $this->indicators->subscribers($plan),
|
||||
'trialing' => $this->indicators->trialing($plan),
|
||||
];
|
||||
}
|
||||
|
||||
return collect($plans)->sortByDesc('count')->values()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of users or teams who are on a generic trial.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function trials()
|
||||
{
|
||||
$model = Spark::teamTrialDays() ? Spark::team() : Spark::user();
|
||||
|
||||
return $model
|
||||
->where('trial_ends_at', '>=', Carbon::now())
|
||||
->whereDoesntHave('subscriptions')
|
||||
->count();
|
||||
}
|
||||
}
|
50
spark/src/Http/Controllers/Kiosk/ProfileController.php
Normal file
50
spark/src/Http/Controllers/Kiosk/ProfileController.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Kiosk;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Repositories\UserRepository;
|
||||
use Laravel\Spark\Contracts\Repositories\PerformanceIndicatorsRepository;
|
||||
|
||||
class ProfileController extends Controller
|
||||
{
|
||||
/**
|
||||
* The performance indicators repository instance.
|
||||
*
|
||||
* @var PerformanceIndicatorsRepository
|
||||
*/
|
||||
protected $indicators;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param PerformanceIndicatorsRepository $indicators
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(PerformanceIndicatorsRepository $indicators)
|
||||
{
|
||||
$this->indicators = $indicators;
|
||||
|
||||
$this->middleware('auth');
|
||||
$this->middleware('dev');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user to be displayed on the user profile screen.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $id
|
||||
* @return Response
|
||||
*/
|
||||
public function show(Request $request, $id)
|
||||
{
|
||||
$user = Spark::call(UserRepository::class.'@find', [$id]);
|
||||
|
||||
return response()->json([
|
||||
'user' => $user,
|
||||
'revenue' => $this->indicators->totalRevenueForUser($user),
|
||||
]);
|
||||
}
|
||||
}
|
37
spark/src/Http/Controllers/Kiosk/SearchController.php
Normal file
37
spark/src/Http/Controllers/Kiosk/SearchController.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Kiosk;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Repositories\UserRepository;
|
||||
|
||||
class SearchController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
$this->middleware('dev');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the users based on the incoming search query.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function performBasicSearch(Request $request)
|
||||
{
|
||||
$query = str_replace('*', '%', $request->input('query'));
|
||||
|
||||
return Spark::interact(UserRepository::class.'@search', [
|
||||
$query, $request->user()
|
||||
]);
|
||||
}
|
||||
}
|
16
spark/src/Http/Controllers/MissingTeamController.php
Normal file
16
spark/src/Http/Controllers/MissingTeamController.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
class MissingTeamController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show the missing team notice.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function show()
|
||||
{
|
||||
return view('spark::missing-team');
|
||||
}
|
||||
}
|
66
spark/src/Http/Controllers/NotificationController.php
Normal file
66
spark/src/Http/Controllers/NotificationController.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Notification;
|
||||
use Laravel\Spark\Contracts\Repositories\NotificationRepository;
|
||||
use Laravel\Spark\Contracts\Repositories\AnnouncementRepository;
|
||||
|
||||
class NotificationController extends Controller
|
||||
{
|
||||
/**
|
||||
* The announcements repository.
|
||||
*
|
||||
* @var AnnouncementRepository
|
||||
*/
|
||||
protected $announcements;
|
||||
|
||||
/**
|
||||
* The notifications repository.
|
||||
*
|
||||
* @var NotificationRepository
|
||||
*/
|
||||
protected $notifications;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param AnnouncementRepository $announcements
|
||||
* @param NotificationRepository $notifications
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(AnnouncementRepository $announcements,
|
||||
NotificationRepository $notifications)
|
||||
{
|
||||
$this->announcements = $announcements;
|
||||
$this->notifications = $notifications;
|
||||
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the recent notifications and announcements for the user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function recent(Request $request)
|
||||
{
|
||||
return response()->json([
|
||||
'announcements' => $this->announcements->recent()->toArray(),
|
||||
'notifications' => $this->notifications->recent($request->user())->toArray(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the given notifications as read.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function markAsRead(Request $request)
|
||||
{
|
||||
Notification::whereIn('id', $request->notifications)->whereUserId($request->user()->id)->update(['read' => 1]);
|
||||
}
|
||||
}
|
18
spark/src/Http/Controllers/PlanController.php
Normal file
18
spark/src/Http/Controllers/PlanController.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
|
||||
class PlanController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get the all of the regular plans defined for the application.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return response()->json(Spark::allPlans());
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\API;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class TokenAbilitiesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the available token abilities.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
return response()->json(collect(Spark::tokensCan())->map(function ($value, $key) {
|
||||
return [
|
||||
'name' => $value,
|
||||
'value' => $key,
|
||||
'default' => in_array($key, Spark::tokenDefaults())
|
||||
];
|
||||
})->values());
|
||||
}
|
||||
}
|
96
spark/src/Http/Controllers/Settings/API/TokenController.php
Normal file
96
spark/src/Http/Controllers/Settings/API/TokenController.php
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\API;
|
||||
|
||||
use Laravel\Spark\Token;
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Repositories\TokenRepository;
|
||||
use Laravel\Spark\Http\Requests\Settings\API\CreateTokenRequest;
|
||||
use Laravel\Spark\Http\Requests\Settings\API\UpdateTokenRequest;
|
||||
|
||||
class TokenController extends Controller
|
||||
{
|
||||
/**
|
||||
* The token repository instance.
|
||||
*
|
||||
* @var TokenRepository
|
||||
*/
|
||||
protected $tokens;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param TokenRepository $tokens
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(TokenRepository $tokens)
|
||||
{
|
||||
$this->tokens = $tokens;
|
||||
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the tokens generated by the user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function all(Request $request)
|
||||
{
|
||||
return $this->tokens->all($request->user());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new API token for the user.
|
||||
*
|
||||
* @param CreateTokenRequest $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(CreateTokenRequest $request)
|
||||
{
|
||||
$data = count(Spark::tokensCan()) > 0 ? ['abilities' => $request->abilities] : [];
|
||||
|
||||
return response()->json(['token' => $this->tokens->createToken(
|
||||
$request->user(), $request->name, $data
|
||||
)->token]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given API token.
|
||||
*
|
||||
* @param UpdateTokenRequest $request
|
||||
* @param string $tokenId
|
||||
* @return Response
|
||||
*/
|
||||
public function update(UpdateTokenRequest $request, $tokenId)
|
||||
{
|
||||
$token = $request->user()->tokens()->where('id', $tokenId)->firstOrFail();
|
||||
|
||||
if (class_exists('Laravel\Passport\Passport')) {
|
||||
$token = new Token([
|
||||
'id' => $token->id,
|
||||
'name' => $token->name,
|
||||
'metadata' => ['abilities' => $token->scopes],
|
||||
]);
|
||||
}
|
||||
|
||||
$this->tokens->updateToken(
|
||||
$token, $request->name, (array) $request->abilities
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given token.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $tokenId
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy(Request $request, $tokenId)
|
||||
{
|
||||
$request->user()->tokens()->where('id', $tokenId)->firstOrFail()->delete();
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Billing;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class BillingInformationController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user's extra billing information.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'information' => 'max:2048',
|
||||
]);
|
||||
|
||||
$request->user()->forceFill([
|
||||
'extra_billing_information' => $request->information,
|
||||
])->save();
|
||||
}
|
||||
}
|
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Billing;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use Braintree\WebhookNotification;
|
||||
use Laravel\Spark\TeamSubscription;
|
||||
use Laravel\Cashier\Http\Controllers\WebhookController;
|
||||
use Laravel\Spark\Events\Subscription\SubscriptionCancelled;
|
||||
use Laravel\Spark\Contracts\Repositories\LocalInvoiceRepository;
|
||||
use Laravel\Spark\Events\Teams\Subscription\SubscriptionCancelled as TeamSubscriptionCancelled;
|
||||
|
||||
class BraintreeWebhookController extends WebhookController
|
||||
{
|
||||
use SendsInvoiceNotifications;
|
||||
|
||||
/**
|
||||
* Handle a successful invoice payment from a Braintree subscription.
|
||||
*
|
||||
* By default, this e-mails a copy of the invoice to the customer.
|
||||
*
|
||||
* @param WebhookNotification $webhook
|
||||
* @return Response
|
||||
*/
|
||||
protected function handleSubscriptionChargedSuccessfully($webhook)
|
||||
{
|
||||
$subscription = $this->getSubscriptionById($webhook->subscription->id);
|
||||
|
||||
if (! $subscription || ! isset($webhook->subscription->transactions[0])) {
|
||||
return $this->teamSubscriptionChargedSuccessfully($webhook);
|
||||
}
|
||||
|
||||
$invoice = $subscription->user->findInvoice(
|
||||
$webhook->subscription->transactions[0]->id
|
||||
);
|
||||
|
||||
app(LocalInvoiceRepository::class)->createForUser(
|
||||
$subscription->user, $invoice
|
||||
);
|
||||
|
||||
$this->sendInvoiceNotification($subscription->user, $invoice);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a successful invoice payment from a Braintree subscription.
|
||||
*
|
||||
* @param WebhookNotification $webhook
|
||||
* @return Response
|
||||
*/
|
||||
protected function teamSubscriptionChargedSuccessfully($webhook)
|
||||
{
|
||||
$subscription = TeamSubscription::where(
|
||||
'braintree_id', $webhook->subscription->id
|
||||
)->first();
|
||||
|
||||
if (! $subscription || ! isset($webhook->subscription->transactions[0])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$invoice = $subscription->team->findInvoice(
|
||||
$webhook->subscription->transactions[0]->id
|
||||
);
|
||||
|
||||
app(LocalInvoiceRepository::class)->createForTeam(
|
||||
$subscription->team, $invoice
|
||||
);
|
||||
|
||||
$this->sendInvoiceNotification($subscription->team, $invoice);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a subscription cancellation notification from Braintree.
|
||||
*
|
||||
* @param string $subscriptionId
|
||||
* @return Response
|
||||
*/
|
||||
protected function cancelSubscription($subscriptionId)
|
||||
{
|
||||
parent::cancelSubscription($subscriptionId);
|
||||
|
||||
if (! $this->getSubscriptionById($subscriptionId)) {
|
||||
return $this->cancelTeamSubscription($subscriptionId);
|
||||
}
|
||||
|
||||
if ($subscription = $this->getSubscriptionById($subscriptionId)) {
|
||||
event(new SubscriptionCancelled($subscription->user));
|
||||
}
|
||||
|
||||
return new Response('Webhook Handled', 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a subscription cancellation notification from Braintree.
|
||||
*
|
||||
* @param string $subscriptionId
|
||||
* @return Response
|
||||
*/
|
||||
protected function cancelTeamSubscription($subscriptionId)
|
||||
{
|
||||
$subscription = TeamSubscription::where(
|
||||
'braintree_id', $subscriptionId
|
||||
)->first();
|
||||
|
||||
if ($subscription && ! $subscription->cancelled()) {
|
||||
$subscription->markAsCancelled();
|
||||
|
||||
event(new TeamSubscriptionCancelled($subscription->team));
|
||||
}
|
||||
|
||||
return new Response('Webhook Handled', 200);
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Billing;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class InvoiceController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the invoices for the current user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function all(Request $request)
|
||||
{
|
||||
if (! $request->user()->hasBillingProvider()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $request->user()->localInvoices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the invoice with the given ID.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $id
|
||||
* @return Response
|
||||
*/
|
||||
public function download(Request $request, $id)
|
||||
{
|
||||
$invoice = $request->user()->localInvoices()
|
||||
->where('id', $id)->firstOrFail();
|
||||
|
||||
return $request->user()->downloadInvoice(
|
||||
$invoice->provider_id, ['id' => $invoice->id] + Spark::invoiceDataFor($request->user())
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Billing;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
trait SendsInvoiceNotifications
|
||||
{
|
||||
/**
|
||||
* The invoice notification e-mail view.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $emailView = 'spark::settings.invoices.emails.invoice';
|
||||
|
||||
/**
|
||||
* Send an invoice notification e-mail.
|
||||
*
|
||||
* @param mixed $billable
|
||||
* @param \Laravel\Cashier\Invoice
|
||||
* @return void
|
||||
*/
|
||||
protected function sendInvoiceNotification($billable, $invoice)
|
||||
{
|
||||
$invoiceData = Spark::invoiceDataFor($billable);
|
||||
|
||||
$data = compact('billable', 'invoice', 'invoiceData');
|
||||
|
||||
Mail::send($this->emailView, $data, function ($message) use ($billable, $invoice, $invoiceData) {
|
||||
$this->buildInvoiceMessage($message, $billable, $invoice, $invoiceData);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the invoice notification message.
|
||||
*
|
||||
* @param \Illuminate\Mail\Message $message
|
||||
* @param mixed $billable
|
||||
* @param \Laravel\Cashier\Invoice
|
||||
* @param array $invoiceData
|
||||
* @return void
|
||||
*/
|
||||
protected function buildInvoiceMessage($message, $billable, $invoice, array $invoiceData)
|
||||
{
|
||||
$localInvoice = $billable->localInvoices()
|
||||
->where('provider_id', $invoice->id)->firstOrFail();
|
||||
|
||||
$invoiceData['id'] = $localInvoice->id;
|
||||
|
||||
$message->to($billable->email, $billable->name)
|
||||
->subject($invoiceData['product'].' Invoice')
|
||||
->attachData($invoice->pdf($invoiceData), 'invoice.pdf');
|
||||
}
|
||||
}
|
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Billing;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Response;
|
||||
use Laravel\Cashier\Http\Controllers\WebhookController;
|
||||
use Laravel\Spark\Events\Subscription\SubscriptionCancelled;
|
||||
use Laravel\Spark\Contracts\Repositories\LocalInvoiceRepository;
|
||||
use Laravel\Spark\Events\Teams\Subscription\SubscriptionCancelled as TeamSubscriptionCancelled;
|
||||
|
||||
class StripeWebhookController extends WebhookController
|
||||
{
|
||||
use SendsInvoiceNotifications;
|
||||
|
||||
/**
|
||||
* Handle a successful invoice payment from a Stripe subscription.
|
||||
*
|
||||
* By default, this e-mails a copy of the invoice to the customer.
|
||||
*
|
||||
* @param array $payload
|
||||
* @return Response
|
||||
*/
|
||||
protected function handleInvoicePaymentSucceeded(array $payload)
|
||||
{
|
||||
$user = $this->getUserByStripeId(
|
||||
$payload['data']['object']['customer']
|
||||
);
|
||||
|
||||
if (is_null($user)) {
|
||||
return $this->teamInvoicePaymentSucceeded($payload);
|
||||
}
|
||||
|
||||
$invoice = $user->findInvoice($payload['data']['object']['id']);
|
||||
|
||||
app(LocalInvoiceRepository::class)->createForUser($user, $invoice);
|
||||
|
||||
$this->sendInvoiceNotification(
|
||||
$user, $invoice
|
||||
);
|
||||
|
||||
return new Response('Webhook Handled', 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a successful invoice payment from a Stripe subscription.
|
||||
*
|
||||
* @param array $payload
|
||||
* @return Response
|
||||
*/
|
||||
protected function teamInvoicePaymentSucceeded(array $payload)
|
||||
{
|
||||
$team = Spark::team()->where(
|
||||
'stripe_id', $payload['data']['object']['customer']
|
||||
)->first();
|
||||
|
||||
if (is_null($team)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$invoice = $team->findInvoice($payload['data']['object']['id']);
|
||||
|
||||
app(LocalInvoiceRepository::class)->createForTeam($team, $invoice);
|
||||
|
||||
$this->sendInvoiceNotification(
|
||||
$team, $invoice
|
||||
);
|
||||
|
||||
return new Response('Webhook Handled', 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a cancelled customer from a Stripe subscription.
|
||||
*
|
||||
* @param array $payload
|
||||
* @return Response
|
||||
*/
|
||||
protected function handleCustomerSubscriptionDeleted(array $payload)
|
||||
{
|
||||
parent::handleCustomerSubscriptionDeleted($payload);
|
||||
|
||||
$user = $this->getUserByStripeId($payload['data']['object']['customer']);
|
||||
|
||||
if (! $user) {
|
||||
return $this->teamSubscriptionDeleted($payload);
|
||||
}
|
||||
|
||||
event(new SubscriptionCancelled(
|
||||
$this->getUserByStripeId($payload['data']['object']['customer']))
|
||||
);
|
||||
|
||||
return new Response('Webhook Handled', 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a cancelled customer from a Stripe subscription.
|
||||
*
|
||||
* @param array $payload
|
||||
* @return Response
|
||||
*/
|
||||
protected function teamSubscriptionDeleted(array $payload)
|
||||
{
|
||||
$team = Spark::team()->where(
|
||||
'stripe_id', $payload['data']['object']['customer']
|
||||
)->first();
|
||||
|
||||
if ($team) {
|
||||
$team->subscriptions->filter(function ($subscription) use ($payload) {
|
||||
return $subscription->stripe_id === $payload['data']['object']['id'];
|
||||
})->each(function ($subscription) {
|
||||
$subscription->markAsCancelled();
|
||||
});
|
||||
} else {
|
||||
return new Response('Webhook Handled', 200);
|
||||
}
|
||||
|
||||
event(new TeamSubscriptionCancelled($team));
|
||||
|
||||
return new Response('Webhook Handled', 200);
|
||||
}
|
||||
}
|
28
spark/src/Http/Controllers/Settings/DashboardController.php
Normal file
28
spark/src/Http/Controllers/Settings/DashboardController.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings;
|
||||
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the settings dashboard.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function show()
|
||||
{
|
||||
return view('spark::settings');
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\PaymentMethod;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\PaymentMethod\UpdatePaymentMethod;
|
||||
use Laravel\Spark\Contracts\Http\Requests\Settings\PaymentMethod\UpdatePaymentMethodRequest;
|
||||
|
||||
class PaymentMethodController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the payment method for the user.
|
||||
*
|
||||
* @param UpdatePaymentMethodRequest $request
|
||||
* @return Response
|
||||
*/
|
||||
public function update(UpdatePaymentMethodRequest $request)
|
||||
{
|
||||
Spark::interact(UpdatePaymentMethod::class, [
|
||||
$request->user(), $request->all(),
|
||||
]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\PaymentMethod;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Repositories\CouponRepository;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\PaymentMethod\RedeemCoupon;
|
||||
|
||||
class RedeemCouponController extends Controller
|
||||
{
|
||||
/**
|
||||
* The coupon repository implementation.
|
||||
*
|
||||
* @var CouponRepository
|
||||
*/
|
||||
protected $coupons;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \Laravel\Spark\Contracts\Repositories\CouponRepository $coupons
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(CouponRepository $coupons)
|
||||
{
|
||||
$this->coupons = $coupons;
|
||||
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Redeem the given coupon code.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function redeem(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'coupon' => 'required',
|
||||
]);
|
||||
|
||||
// We will verify that the coupon can actually be redeemed. In some cases even
|
||||
// valid coupons can not get redeemed by an existing user if this coupon is
|
||||
// running as a promotion for brand new registrations to the application.
|
||||
if (! $this->coupons->canBeRedeemed($request->coupon)) {
|
||||
return response()->json(['coupon' => [
|
||||
'This coupon code is invalid.'
|
||||
]], 422);
|
||||
}
|
||||
|
||||
Spark::interact(RedeemCoupon::class, [
|
||||
$request->user(), $request->coupon
|
||||
]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\PaymentMethod;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Repositories\UserRepository;
|
||||
|
||||
class VatIdController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the VAT ID for the user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'vat_id' => 'max:50|vat_id',
|
||||
]);
|
||||
|
||||
Spark::call(UserRepository::class.'@updateVatId', [
|
||||
$request->user(), $request->vat_id
|
||||
]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Profile;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\Profile\UpdateContactInformation;
|
||||
|
||||
class ContactInformationController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user's contact information settings.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
$this->interaction(
|
||||
$request, UpdateContactInformation::class,
|
||||
[$request->user(), $request->all()]
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Profile;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\Profile\UpdateProfilePhoto;
|
||||
|
||||
class PhotoController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the user's profile photo.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->interaction(
|
||||
$request, UpdateProfilePhoto::class,
|
||||
[$request->user(), $request->all()]
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Security;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class PasswordController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user's password.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'current_password' => 'required',
|
||||
'password' => 'required|confirmed|min:'.Spark::minimumPasswordLength(),
|
||||
]);
|
||||
|
||||
if (! Hash::check($request->current_password, $request->user()->password)) {
|
||||
return response()->json([
|
||||
'current_password' => ['The given password does not match our records.']
|
||||
], 422);
|
||||
}
|
||||
|
||||
$request->user()->forceFill([
|
||||
'password' => bcrypt($request->password)
|
||||
])->save();
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Security;
|
||||
|
||||
use Exception;
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Debug\ExceptionHandler;
|
||||
use Laravel\Spark\Http\Requests\Settings\Security\EnableTwoFactorAuthRequest;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\Security\EnableTwoFactorAuth;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\Security\DisableTwoFactorAuth;
|
||||
|
||||
class TwoFactorAuthController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable two-factor authentication for the user.
|
||||
*
|
||||
* @param EnableTwoFactorAuthRequest $request
|
||||
* @return Response
|
||||
*/
|
||||
public function enable(EnableTwoFactorAuthRequest $request)
|
||||
{
|
||||
try {
|
||||
Spark::interact(EnableTwoFactorAuth::class, [
|
||||
$request->user(), $request->country_code, $request->phone
|
||||
]);
|
||||
|
||||
return $this->storeTwoFactorInformation($request);
|
||||
} catch (Exception $e) {
|
||||
app(ExceptionHandler::class)->report($e);
|
||||
|
||||
return response()->json(['phone' => [
|
||||
'We were not able to enable two-factor authentication for this phone number.'
|
||||
]], 422);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the two-factor authentication information on the user instance.
|
||||
*
|
||||
* @param EnableTwoFactorAuthRequest $request
|
||||
* @return string
|
||||
*/
|
||||
protected function storeTwoFactorInformation($request)
|
||||
{
|
||||
$request->user()->forceFill([
|
||||
'uses_two_factor_auth' => true,
|
||||
'country_code' => $request->country_code,
|
||||
'phone' => $request->phone,
|
||||
'two_factor_reset_code' => bcrypt($code = str_random(40)),
|
||||
])->save();
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable two-factor authentication for the user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function disable(Request $request)
|
||||
{
|
||||
Spark::interact(DisableTwoFactorAuth::class, [$request->user()]);
|
||||
|
||||
$request->user()->forceFill([
|
||||
'uses_two_factor_auth' => false,
|
||||
])->save();
|
||||
}
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Subscription;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Interactions\Subscribe;
|
||||
use Laravel\Spark\Events\Subscription\SubscriptionUpdated;
|
||||
use Laravel\Spark\Events\Subscription\SubscriptionCancelled;
|
||||
use Laravel\Spark\Http\Requests\Settings\Subscription\UpdateSubscriptionRequest;
|
||||
use Laravel\Spark\Contracts\Http\Requests\Settings\Subscription\CreateSubscriptionRequest;
|
||||
|
||||
class PlanController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the subscription for the user.
|
||||
*
|
||||
* @param CreateSubscriptionRequest $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(CreateSubscriptionRequest $request)
|
||||
{
|
||||
$plan = Spark::plans()->where('id', $request->plan)->first();
|
||||
|
||||
Spark::interact(Subscribe::class, [
|
||||
$request->user(), $plan, false, $request->all()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the subscription for the user.
|
||||
*
|
||||
* @param \Laravel\Spark\Http\Requests\Settings\Subscription\UpdateSubscriptionRequest $request
|
||||
* @return Response
|
||||
*/
|
||||
public function update(UpdateSubscriptionRequest $request)
|
||||
{
|
||||
$plan = Spark::plans()->where('id', $request->plan)->first();
|
||||
|
||||
// This method is used both for updating subscriptions and for resuming cancelled
|
||||
// subscriptions that are still within their grace periods as this swap method
|
||||
// will be used for either of these situations without causing any problems.
|
||||
if ($plan->price === 0) {
|
||||
return $this->destroy($request);
|
||||
} else {
|
||||
$subscription = $request->user()->subscription();
|
||||
|
||||
if (Spark::prorates()) {
|
||||
$subscription->swap($request->plan);
|
||||
} else {
|
||||
$subscription->noProrate()->swap($request->plan);
|
||||
}
|
||||
}
|
||||
|
||||
event(new SubscriptionUpdated(
|
||||
$request->user()->fresh()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the user's subscription.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy(Request $request)
|
||||
{
|
||||
$request->user()->subscription()->cancel();
|
||||
|
||||
event(new SubscriptionCancelled($request->user()->fresh()));
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams\Billing;
|
||||
|
||||
use Laravel\Spark\Team;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class BillingInformationController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the team's extra billing information.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request, Team $team)
|
||||
{
|
||||
abort_unless($request->user()->ownsTeam($team), 403);
|
||||
|
||||
$this->validate($request, [
|
||||
'information' => 'max:2048',
|
||||
]);
|
||||
|
||||
$team->forceFill([
|
||||
'extra_billing_information' => $request->information,
|
||||
])->save();
|
||||
}
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams\Billing;
|
||||
|
||||
use Laravel\Spark\Team;
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class InvoiceController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the invoices for the given team.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function all(Request $request, Team $team)
|
||||
{
|
||||
abort_unless($request->user()->ownsTeam($team), 403);
|
||||
|
||||
if (! $team->hasBillingProvider()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $team->localInvoices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the invoice with the given ID.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Team $team
|
||||
* @param string $id
|
||||
* @return Response
|
||||
*/
|
||||
public function download(Request $request, Team $team, $id)
|
||||
{
|
||||
abort_unless($request->user()->ownsTeam($team), 403);
|
||||
|
||||
$invoice = $team->localInvoices()
|
||||
->where('id', $id)->firstOrFail();
|
||||
|
||||
return $team->downloadInvoice(
|
||||
$invoice->provider_id, ['id' => $invoice->id] + Spark::invoiceDataFor($team)
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the team settings dashboard.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function show(Request $request, $team)
|
||||
{
|
||||
abort_unless($request->user()->onTeam($team), 404);
|
||||
|
||||
return view('spark::settings.teams.team-settings', compact('team'));
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Invitation;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Repositories\TeamRepository;
|
||||
use Laravel\Spark\Http\Requests\Settings\Teams\CreateInvitationRequest;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\Teams\SendInvitation;
|
||||
|
||||
class MailedInvitationController extends Controller
|
||||
{
|
||||
/**
|
||||
* The team repository implementation.
|
||||
*
|
||||
* @var \Laravel\Spark\Contracts\Repositories\TeamRepository
|
||||
*/
|
||||
protected $teams;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param TeamRepository $teams
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(TeamRepository $teams)
|
||||
{
|
||||
$this->teams = $teams;
|
||||
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the mailed invitations for the given team.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Laravel\Spark\Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function all(Request $request, $team)
|
||||
{
|
||||
abort_unless($request->user()->onTeam($team), 404);
|
||||
|
||||
return $team->invitations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new invitation.
|
||||
*
|
||||
* @param CreateInvitationRequest $request
|
||||
* @param \Laravel\Spark\Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function store(CreateInvitationRequest $request, $team)
|
||||
{
|
||||
Spark::interact(SendInvitation::class, [$team, $request->email]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel / delete the given invitation.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Laravel\Spark\Invitation $invitation
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy(Request $request, Invitation $invitation)
|
||||
{
|
||||
abort_unless($request->user()->ownsTeam($invitation->team), 404);
|
||||
|
||||
$invitation->delete();
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams\PaymentMethod;
|
||||
|
||||
use Laravel\Spark\Team;
|
||||
use Laravel\Spark\Spark;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\PaymentMethod\UpdatePaymentMethod;
|
||||
use Laravel\Spark\Contracts\Http\Requests\Settings\PaymentMethod\UpdatePaymentMethodRequest;
|
||||
|
||||
class PaymentMethodController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the payment method for the user.
|
||||
*
|
||||
* @param UpdatePaymentMethodRequest $request
|
||||
* @param Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function update(UpdatePaymentMethodRequest $request, Team $team)
|
||||
{
|
||||
abort_unless($request->user()->ownsTeam($team), 403);
|
||||
|
||||
Spark::interact(UpdatePaymentMethod::class, [
|
||||
$team, $request->all(),
|
||||
]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams\PaymentMethod;
|
||||
|
||||
use Laravel\Spark\Team;
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Repositories\CouponRepository;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\PaymentMethod\RedeemCoupon;
|
||||
|
||||
class RedeemCouponController extends Controller
|
||||
{
|
||||
/**
|
||||
* The coupon repository implementation.
|
||||
*
|
||||
* @var CouponRepository
|
||||
*/
|
||||
protected $coupons;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \Laravel\Spark\Contracts\Repositories\CouponRepository $coupons
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(CouponRepository $coupons)
|
||||
{
|
||||
$this->coupons = $coupons;
|
||||
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Redeem the given coupon code.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function redeem(Request $request, Team $team)
|
||||
{
|
||||
abort_unless($request->user()->ownsTeam($team), 403);
|
||||
|
||||
$this->validate($request, [
|
||||
'coupon' => 'required',
|
||||
]);
|
||||
|
||||
// We will verify that the coupon can actually be redeemed. In some cases even
|
||||
// valid coupons can not get redeemed by an existing user if this coupon is
|
||||
// running as a promotion for brand new registrations to the application.
|
||||
if (! $this->coupons->canBeRedeemed($request->coupon)) {
|
||||
return response()->json(['coupon' => [
|
||||
'This coupon code is invalid.'
|
||||
]], 422);
|
||||
}
|
||||
|
||||
Spark::interact(RedeemCoupon::class, [
|
||||
$team, $request->coupon
|
||||
]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams\PaymentMethod;
|
||||
|
||||
use Laravel\Spark\Team;
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Repositories\TeamRepository;
|
||||
|
||||
class VatIdController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the VAT ID for the team.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request, Team $team)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'vat_id' => 'max:50|vat_id',
|
||||
]);
|
||||
|
||||
Spark::call(TeamRepository::class.'@updateVatId', [
|
||||
$team, $request->vat_id
|
||||
]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Invitation;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\Teams\AddTeamMember;
|
||||
|
||||
class PendingInvitationController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the pending invitations for the user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function all(Request $request)
|
||||
{
|
||||
return $request->user()->invitations()->with('team')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept the given invitations.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Laravel\Spark\Invitation $invitation
|
||||
* @return Response
|
||||
*/
|
||||
public function accept(Request $request, Invitation $invitation)
|
||||
{
|
||||
abort_unless($request->user()->id == $invitation->user_id, 404);
|
||||
|
||||
Spark::interact(AddTeamMember::class, [
|
||||
$invitation->team, $request->user()
|
||||
]);
|
||||
|
||||
$invitation->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reject the given invitations.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Laravel\Spark\Invitation $invitation
|
||||
* @return Response
|
||||
*/
|
||||
public function reject(Request $request, Invitation $invitation)
|
||||
{
|
||||
abort_unless($request->user()->id == $invitation->user_id, 404);
|
||||
|
||||
$invitation->delete();
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams\Subscription;
|
||||
|
||||
use Laravel\Spark\Team;
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Interactions\SubscribeTeam;
|
||||
use Laravel\Spark\Events\Teams\Subscription\SubscriptionUpdated;
|
||||
use Laravel\Spark\Events\Teams\Subscription\SubscriptionCancelled;
|
||||
use Laravel\Spark\Http\Requests\Settings\Teams\Subscription\UpdateSubscriptionRequest;
|
||||
use Laravel\Spark\Contracts\Http\Requests\Settings\Teams\Subscription\CreateSubscriptionRequest;
|
||||
|
||||
class PlanController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the subscription for the team.
|
||||
*
|
||||
* @param CreateSubscriptionRequest $request
|
||||
* @param Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function store(CreateSubscriptionRequest $request, Team $team)
|
||||
{
|
||||
Spark::interact(SubscribeTeam::class, [
|
||||
$team, $request->plan(), false, $request->all()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the subscription for the team.
|
||||
*
|
||||
* @param UpdateSubscriptionRequest $request
|
||||
* @param Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function update(UpdateSubscriptionRequest $request, Team $team)
|
||||
{
|
||||
$plan = $request->plan();
|
||||
|
||||
// This method is used both for updating subscriptions and for resuming cancelled
|
||||
// subscriptions that are still within their grace periods as this swap method
|
||||
// will be used for either of these situations without causing any problems.
|
||||
if ($plan->price === 0) {
|
||||
return $this->destroy($request, $team);
|
||||
} else {
|
||||
$team->subscription()->swap($request->plan);
|
||||
}
|
||||
|
||||
event(new SubscriptionUpdated(
|
||||
$team->fresh()
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the team's subscription.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy(Request $request, Team $team)
|
||||
{
|
||||
abort_unless($request->user()->ownsTeam($team), 403);
|
||||
|
||||
$team->subscription()->cancel();
|
||||
|
||||
event(new SubscriptionCancelled($team->fresh()));
|
||||
}
|
||||
}
|
60
spark/src/Http/Controllers/Settings/Teams/TeamController.php
Normal file
60
spark/src/Http/Controllers/Settings/Teams/TeamController.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Events\Teams\TeamDeleted;
|
||||
use Laravel\Spark\Events\Teams\DeletingTeam;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\Teams\CreateTeam;
|
||||
|
||||
class TeamController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new team.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
if (! Spark::createsAdditionalTeams()) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$this->interaction($request, CreateTeam::class, [
|
||||
$request->user(), $request->all()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given team.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Laravel\Spark\Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy(Request $request, $team)
|
||||
{
|
||||
if (! $request->user()->ownsTeam($team)) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
event(new DeletingTeam($team));
|
||||
|
||||
$team->detachUsersAndDestroy();
|
||||
|
||||
event(new TeamDeleted($team));
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Events\Teams\TeamMemberRemoved;
|
||||
use Laravel\Spark\Http\Requests\Settings\Teams\RemoveTeamMemberRequest;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\Teams\UpdateTeamMember;
|
||||
|
||||
class TeamMemberController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given team member.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Laravel\Spark\Team $team
|
||||
* @param mixed $member
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request, $team, $member)
|
||||
{
|
||||
abort_unless($request->user()->ownsTeam($team), 404);
|
||||
|
||||
$this->interaction($request, UpdateTeamMember::class, [
|
||||
$team, $member, $request->all()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the given team member from the team.
|
||||
*
|
||||
* @param RemoveTeamMemberRequest $request
|
||||
* @param \Laravel\Spark\Team $team
|
||||
* @param mixed $member
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy(RemoveTeamMemberRequest $request, $team, $member)
|
||||
{
|
||||
$team->users()->detach($member->id);
|
||||
|
||||
event(new TeamMemberRemoved($team, $member));
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class TeamMemberRoleController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the available team member roles.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
$roles = [];
|
||||
|
||||
foreach (Spark::roles() as $key => $value) {
|
||||
$roles[] = ['value' => $key, 'text' => $value];
|
||||
}
|
||||
|
||||
return response()->json($roles);
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
|
||||
class TeamNameController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given team's name.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Laravel\Spark\Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request, $team)
|
||||
{
|
||||
abort_unless($request->user()->ownsTeam($team), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'name' => 'required|max:255',
|
||||
]);
|
||||
|
||||
$team->forceFill([
|
||||
'name' => $request->name,
|
||||
])->save();
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers\Settings\Teams;
|
||||
|
||||
use Laravel\Spark\Http\Controllers\Controller;
|
||||
use Laravel\Spark\Contracts\Interactions\Settings\Teams\UpdateTeamPhoto;
|
||||
use Laravel\Spark\Http\Requests\Settings\Teams\UpdateTeamPhotoRequest;
|
||||
|
||||
class TeamPhotoController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given team's photo.
|
||||
*
|
||||
* @param UpdateTeamPhotoRequest $request
|
||||
* @param \Laravel\Spark\Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function update(UpdateTeamPhotoRequest $request, $team)
|
||||
{
|
||||
$this->interaction(
|
||||
$request, UpdateTeamPhoto::class,
|
||||
[$team, $request->all()]
|
||||
);
|
||||
}
|
||||
}
|
22
spark/src/Http/Controllers/SupportController.php
Normal file
22
spark/src/Http/Controllers/SupportController.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Contracts\Interactions\Support\SendSupportEmail;
|
||||
|
||||
class SupportController extends Controller
|
||||
{
|
||||
/**
|
||||
* Send a customer support request e-mail.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function sendEmail(Request $request)
|
||||
{
|
||||
$this->interaction($request, SendSupportEmail::class, [
|
||||
$request->all(),
|
||||
]);
|
||||
}
|
||||
}
|
37
spark/src/Http/Controllers/TaxRateController.php
Normal file
37
spark/src/Http/Controllers/TaxRateController.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TaxRateController extends Controller
|
||||
{
|
||||
/**
|
||||
* Attempt to calculate the tax rate for the billing address.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function calculate(Request $request)
|
||||
{
|
||||
if (! $request->filled('city', 'state', 'zip', 'country')) {
|
||||
return response()->json(['rate' => 0]);
|
||||
}
|
||||
|
||||
$user = Spark::user();
|
||||
|
||||
$user->forceFill([
|
||||
'vat_id' => $request->vat_id,
|
||||
'billing_city' => $request->city,
|
||||
'billing_state' => $request->state,
|
||||
'billing_zip' => $request->zip,
|
||||
'billing_country' => $request->country,
|
||||
'card_country' => $request->country,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'rate' => $user->taxPercentage()
|
||||
]);
|
||||
}
|
||||
}
|
86
spark/src/Http/Controllers/TeamController.php
Normal file
86
spark/src/Http/Controllers/TeamController.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Contracts\Repositories\TeamRepository;
|
||||
|
||||
class TeamController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the teams for the current user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function all(Request $request)
|
||||
{
|
||||
return Spark::interact(
|
||||
TeamRepository::class.'@forUser', [$request->user()]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current team for the user.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function current(Request $request)
|
||||
{
|
||||
abort_unless($request->user()->current_team_id, 404);
|
||||
|
||||
return Spark::interact(TeamRepository::class.'@find', [
|
||||
$request->user()->current_team_id
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the team matching the given ID.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $teamId
|
||||
* @return Response
|
||||
*/
|
||||
public function show(Request $request, $teamId)
|
||||
{
|
||||
$team = Spark::interact(TeamRepository::class.'@find', [$teamId]);
|
||||
|
||||
abort_unless($request->user()->onTeam($team), 404);
|
||||
|
||||
if ($request->user()->ownsTeam($team)) {
|
||||
$team->load('subscriptions');
|
||||
|
||||
$team->shouldHaveOwnerVisibility();
|
||||
}
|
||||
|
||||
return $team;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch the current team the user is viewing.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \Laravel\Spark\Team $team
|
||||
* @return Response
|
||||
*/
|
||||
public function switchCurrentTeam(Request $request, $team)
|
||||
{
|
||||
abort_unless($request->user()->onTeam($team), 404);
|
||||
|
||||
$request->user()->switchToTeam($team);
|
||||
|
||||
return back();
|
||||
}
|
||||
}
|
48
spark/src/Http/Controllers/TeamCouponController.php
Normal file
48
spark/src/Http/Controllers/TeamCouponController.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Contracts\Repositories\CouponRepository;
|
||||
|
||||
class TeamCouponController extends Controller
|
||||
{
|
||||
/**
|
||||
* The coupon repository implementation.
|
||||
*
|
||||
* @var \Laravel\Spark\Contracts\Repositories\CouponRepository
|
||||
*/
|
||||
protected $coupons;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param \Laravel\Spark\Contracts\Repositories\CouponRepository $coupons
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(CouponRepository $coupons)
|
||||
{
|
||||
$this->coupons = $coupons;
|
||||
|
||||
$this->middleware('auth')->only('current');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current discount for the given team.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $teamId
|
||||
* @return Response
|
||||
*/
|
||||
public function current(Request $request, $teamId)
|
||||
{
|
||||
$team = Spark::team()->where('id', $teamId)->firstOrFail();
|
||||
|
||||
if ($coupon = $this->coupons->forBillable($team)) {
|
||||
return response()->json($coupon->toArray());
|
||||
}
|
||||
|
||||
abort(204);
|
||||
}
|
||||
}
|
20
spark/src/Http/Controllers/TermsController.php
Normal file
20
spark/src/Http/Controllers/TermsController.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Parsedown;
|
||||
|
||||
class TermsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show the terms of service for the application.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function show()
|
||||
{
|
||||
return view('spark::terms', [
|
||||
'terms' => (new Parsedown)->text(file_get_contents(base_path('terms.md')))
|
||||
]);
|
||||
}
|
||||
}
|
44
spark/src/Http/Controllers/TokenController.php
Normal file
44
spark/src/Http/Controllers/TokenController.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Contracts\Repositories\TokenRepository;
|
||||
|
||||
class TokenController extends Controller
|
||||
{
|
||||
/**
|
||||
* The token repository instance.
|
||||
*
|
||||
* @var TokenRepository
|
||||
*/
|
||||
protected $tokens;
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @param TokenRepository $tokens
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(TokenRepository $tokens)
|
||||
{
|
||||
$this->tokens = $tokens;
|
||||
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Exchange the current transient API token for a new one.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function refresh(Request $request)
|
||||
{
|
||||
$this->tokens->deleteExpiredTokens($request->user());
|
||||
|
||||
return response('Refreshed.')->withCookie(
|
||||
$this->tokens->createTokenCookie($request->user())
|
||||
);
|
||||
}
|
||||
}
|
46
spark/src/Http/Controllers/UserController.php
Normal file
46
spark/src/Http/Controllers/UserController.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Controllers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Spark\Contracts\Repositories\UserRepository;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth')->only(
|
||||
'updateLastReadAnnouncementsTimestamp'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current user of the application.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return Spark::interact(UserRepository::class.'@current');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the last read announcements timestamp.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function updateLastReadAnnouncementsTimestamp(Request $request)
|
||||
{
|
||||
$request->user()->forceFill([
|
||||
'last_read_announcements_at' => Carbon::now(),
|
||||
])->save();
|
||||
}
|
||||
}
|
103
spark/src/Http/Middleware/CreateFreshApiToken.php
Normal file
103
spark/src/Http/Middleware/CreateFreshApiToken.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Http\Response;
|
||||
use Laravel\Spark\Contracts\Repositories\TokenRepository;
|
||||
|
||||
class CreateFreshApiToken
|
||||
{
|
||||
/**
|
||||
* The token repository implementation.
|
||||
*
|
||||
* @var TokenRepository
|
||||
*/
|
||||
protected $tokens;
|
||||
|
||||
/**
|
||||
* Create a new middleware instance.
|
||||
*
|
||||
* @param TokenRepository $tokens
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(TokenRepository $tokens)
|
||||
{
|
||||
$this->tokens = $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string|null $guard
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next, $guard = null)
|
||||
{
|
||||
$response = $next($request);
|
||||
|
||||
if ($this->shouldReceiveFreshToken($request, $response)) {
|
||||
$response->withCookie($this->tokens->createTokenCookie($request->user()));
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given request should receive a fresh token.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Illuminate\Http\Response $response
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldReceiveFreshToken($request, $response)
|
||||
{
|
||||
return Spark::usesApi() && $this->requestShouldReceiveFreshToken($request) &&
|
||||
$this->responseShouldReceiveFreshToken($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request should receive a fresh token.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return bool
|
||||
*/
|
||||
protected function requestShouldReceiveFreshToken($request)
|
||||
{
|
||||
return $request->isMethod('GET') && $request->user() && ! $request->ajax();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the response should receive a fresh token.
|
||||
*
|
||||
* @param \Illuminate\Http\Response $response
|
||||
* @return bool
|
||||
*/
|
||||
protected function responseShouldReceiveFreshToken($response)
|
||||
{
|
||||
return $response instanceof Response &&
|
||||
! $this->alreadyContainsToken($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given response already contains a Spark API token.
|
||||
*
|
||||
* This avoids us overwriting a just "refreshed" token.
|
||||
*
|
||||
* @param \Illuminate\Http\Response $response
|
||||
* @return bool
|
||||
*/
|
||||
protected function alreadyContainsToken($response)
|
||||
{
|
||||
foreach ($response->headers->getCookies() as $cookie) {
|
||||
if ($cookie->getName() === 'spark_token') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
47
spark/src/Http/Middleware/VerifyTeamIsSubscribed.php
Normal file
47
spark/src/Http/Middleware/VerifyTeamIsSubscribed.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Middleware;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
|
||||
class VerifyTeamIsSubscribed
|
||||
{
|
||||
/**
|
||||
* Verify the incoming request's current team has a subscription.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string $subscription
|
||||
* @param string $plan
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function handle($request, $next, $subscription = 'default', $plan = null)
|
||||
{
|
||||
if ($this->subscribed($request->user(), $subscription, $plan, func_num_args() === 2)) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
return $request->ajax() || $request->wantsJson()
|
||||
? response('Subscription Required.', 402)
|
||||
: redirect('/settings/'.str_plural(Spark::teamString()).'/'.$request->user()->currentTeam->id.'#/subscription');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given user's current team is subscribed to the given plan.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @param string $subscription
|
||||
* @param bool $plan
|
||||
* @param bool $defaultSubscription
|
||||
* @return bool
|
||||
*/
|
||||
protected function subscribed($user, $subscription, $plan, $defaultSubscription)
|
||||
{
|
||||
if (! $user || ! $user->currentTeam) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ($defaultSubscription && $user->currentTeam->onGenericTrial()) ||
|
||||
$user->currentTeam->subscribed($subscription, $plan);
|
||||
}
|
||||
}
|
24
spark/src/Http/Middleware/VerifyUserHasTeam.php
Normal file
24
spark/src/Http/Middleware/VerifyUserHasTeam.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Middleware;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
|
||||
class VerifyUserHasTeam
|
||||
{
|
||||
/**
|
||||
* Verify the incoming request's user belongs to team.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function handle($request, $next)
|
||||
{
|
||||
if (Spark::usesTeams() && $request->user() && ! $request->user()->hasTeams()) {
|
||||
return redirect('missing-'.Spark::teamString());
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
26
spark/src/Http/Middleware/VerifyUserIsDeveloper.php
Normal file
26
spark/src/Http/Middleware/VerifyUserIsDeveloper.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Middleware;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
|
||||
class VerifyUserIsDeveloper
|
||||
{
|
||||
/**
|
||||
* Determine if the authenticated user is a developer.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function handle($request, $next)
|
||||
{
|
||||
if ($request->user() && Spark::developer($request->user()->email)) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
return $request->ajax() || $request->wantsJson()
|
||||
? response('Unauthorized.', 401)
|
||||
: redirect()->guest('login');
|
||||
}
|
||||
}
|
45
spark/src/Http/Middleware/VerifyUserIsSubscribed.php
Normal file
45
spark/src/Http/Middleware/VerifyUserIsSubscribed.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Middleware;
|
||||
|
||||
class VerifyUserIsSubscribed
|
||||
{
|
||||
/**
|
||||
* Verify the incoming request's user has a subscription.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @param string $subscription
|
||||
* @param string $plan
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function handle($request, $next, $subscription = 'default', $plan = null)
|
||||
{
|
||||
if ($this->subscribed($request->user(), $subscription, $plan, func_num_args() === 2)) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
return $request->ajax() || $request->wantsJson()
|
||||
? response('Subscription Required.', 402)
|
||||
: redirect('/settings#/subscription');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given user is subscribed to the given plan.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Authenticatable $user
|
||||
* @param string $subscription
|
||||
* @param string $plan
|
||||
* @param bool $defaultSubscription
|
||||
* @return bool
|
||||
*/
|
||||
protected function subscribed($user, $subscription, $plan, $defaultSubscription)
|
||||
{
|
||||
if (! $user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ($defaultSubscription && $user->onGenericTrial()) ||
|
||||
$user->subscribed($subscription, $plan);
|
||||
}
|
||||
}
|
18
spark/src/Http/Requests/Auth/BraintreeRegisterRequest.php
Normal file
18
spark/src/Http/Requests/Auth/BraintreeRegisterRequest.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Auth;
|
||||
|
||||
use Laravel\Spark\Contracts\Http\Requests\Auth\RegisterRequest as Contract;
|
||||
|
||||
class BraintreeRegisterRequest extends RegisterRequest implements Contract
|
||||
{
|
||||
/**
|
||||
* Get the validator for the request.
|
||||
*
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function validator()
|
||||
{
|
||||
return $this->registerValidator(['braintree_type', 'braintree_token']);
|
||||
}
|
||||
}
|
141
spark/src/Http/Requests/Auth/RegisterRequest.php
Normal file
141
spark/src/Http/Requests/Auth/RegisterRequest.php
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Auth;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Laravel\Spark\Invitation;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Laravel\Spark\Contracts\Interactions\Auth\CreateUser;
|
||||
use Laravel\Spark\Contracts\Repositories\CouponRepository;
|
||||
|
||||
class RegisterRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validator for a registration request.
|
||||
*
|
||||
* @param array $paymentAttributes
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
protected function registerValidator(array $paymentAttributes)
|
||||
{
|
||||
$validator = $this->baseValidator();
|
||||
|
||||
// If a paid plan is selected, we will validate the given required fields which
|
||||
// are typically the Stripe / Braintree tokens. If the selected plan is free
|
||||
// of course we will not need to validate that these fields are available.
|
||||
$validator->sometimes($paymentAttributes, 'required', function ($input) {
|
||||
return $this->plan() && $this->plan()->price > 0;
|
||||
});
|
||||
|
||||
return $this->after($validator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base validator instance for a register request.
|
||||
*
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function baseValidator()
|
||||
{
|
||||
$validator = Spark::interact(
|
||||
CreateUser::class.'@validator', [$this]
|
||||
);
|
||||
|
||||
$allPlanIdList = Spark::activePlanIdList().','.Spark::activeTeamPlanIdList();
|
||||
|
||||
$validator->sometimes('plan', 'required|in:'.$allPlanIdList, function () {
|
||||
return Spark::needsCardUpFront();
|
||||
});
|
||||
|
||||
return $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the "after" callabck for the validator.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
protected function after($validator)
|
||||
{
|
||||
return $validator->after(function ($validator) {
|
||||
if ($this->coupon) {
|
||||
$this->validateCoupon($validator);
|
||||
}
|
||||
|
||||
if ($this->invitation) {
|
||||
$this->validateInvitation($validator);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the coupon on the request.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @return void
|
||||
*/
|
||||
protected function validateCoupon($validator)
|
||||
{
|
||||
if (! app(CouponRepository::class)->valid($this->coupon)) {
|
||||
$validator->errors()->add('coupon', 'This coupon code is invalid.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the invitation code on the request.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @return void
|
||||
*/
|
||||
protected function validateInvitation($validator)
|
||||
{
|
||||
if (! $this->invitation()) {
|
||||
$validator->errors()->add('invitation', 'This invitation code is invalid.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request contains a paid plan.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPaidPlan()
|
||||
{
|
||||
return $this->plan() && $this->plan()->price > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full plan array for the specified plan.
|
||||
*
|
||||
* @return \Laravel\Spark\Plan|null
|
||||
*/
|
||||
public function plan()
|
||||
{
|
||||
if ($this->plan) {
|
||||
return Spark::plans()->merge(Spark::teamPlans())->where('id', $this->plan)->first();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full invitation instance.
|
||||
*
|
||||
* @return \Laravel\Spark\Invitation
|
||||
*/
|
||||
public function invitation()
|
||||
{
|
||||
if ($this->invitation) {
|
||||
return Invitation::where('token', $this->invitation)->first();
|
||||
}
|
||||
}
|
||||
}
|
28
spark/src/Http/Requests/Auth/StripeRegisterRequest.php
Normal file
28
spark/src/Http/Requests/Auth/StripeRegisterRequest.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Auth;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Laravel\Spark\Http\Requests\ValidatesBillingAddresses;
|
||||
use Laravel\Spark\Contracts\Http\Requests\Auth\RegisterRequest as Contract;
|
||||
|
||||
class StripeRegisterRequest extends RegisterRequest implements Contract
|
||||
{
|
||||
use ValidatesBillingAddresses;
|
||||
|
||||
/**
|
||||
* Get the validator for the request.
|
||||
*
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function validator()
|
||||
{
|
||||
$validator = $this->registerValidator(['stripe_token']);
|
||||
|
||||
if (Spark::collectsBillingAddress() && $this->hasPaidPlan()) {
|
||||
$this->validateBillingAddress($validator);
|
||||
}
|
||||
|
||||
return $validator;
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\API;
|
||||
|
||||
class CreateTokenRequest extends TokenRequest
|
||||
{
|
||||
//
|
||||
}
|
61
spark/src/Http/Requests/Settings/API/TokenRequest.php
Normal file
61
spark/src/Http/Requests/Settings/API/TokenRequest.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\API;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class TokenRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validator for the request.
|
||||
*
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function validator()
|
||||
{
|
||||
return $this->validateAbilities(Validator::make($this->all(), [
|
||||
'name' => 'required|max:255',
|
||||
], $this->messages()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the valdiator to validate the token abilities.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
protected function validateAbilities($validator)
|
||||
{
|
||||
$abilities = implode(',', array_keys(Spark::tokensCan()));
|
||||
|
||||
$validator->sometimes('abilities', 'required|array|in:'.$abilities, function () {
|
||||
return count(Spark::tokensCan()) > 0;
|
||||
});
|
||||
|
||||
return $validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set custom messages for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'abilities.required' => 'Please select at least one ability.',
|
||||
];
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\API;
|
||||
|
||||
class UpdateTokenRequest extends TokenRequest
|
||||
{
|
||||
//
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\PaymentMethod;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Laravel\Spark\Contracts\Http\Requests\Settings\PaymentMethod\UpdatePaymentMethodRequest;
|
||||
|
||||
class UpdateBraintreePaymentMethodRequest extends FormRequest implements UpdatePaymentMethodRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'braintree_type' => 'required',
|
||||
'braintree_token' => 'required',
|
||||
];
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\PaymentMethod;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Laravel\Spark\Http\Requests\ValidatesBillingAddresses;
|
||||
use Laravel\Spark\Contracts\Http\Requests\Settings\PaymentMethod\UpdatePaymentMethodRequest;
|
||||
|
||||
class UpdateStripePaymentMethodRequest extends FormRequest implements UpdatePaymentMethodRequest
|
||||
{
|
||||
use ValidatesBillingAddresses;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validator for the request.
|
||||
*
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function validator()
|
||||
{
|
||||
$validator = Validator::make($this->all(), [
|
||||
'stripe_token' => 'required',
|
||||
]);
|
||||
|
||||
if (Spark::collectsBillingAddress()) {
|
||||
$this->validateBillingAddress($validator);
|
||||
}
|
||||
|
||||
return $validator;
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Security;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class EnableTwoFactorAuthRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'country_code' => 'required|numeric',
|
||||
'phone' => 'required|numeric',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get data to be validated from the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function validationData()
|
||||
{
|
||||
if ($this->phone) {
|
||||
$this->merge(['phone' => preg_replace('/[^0-9]/', '', $this->phone)]);
|
||||
}
|
||||
|
||||
return $this->all();
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Subscription;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Spark\Contracts\Http\Requests\Settings\Subscription\CreateSubscriptionRequest as Contract;
|
||||
|
||||
class CreateBraintreeSubscriptionRequest extends CreateSubscriptionRequest implements Contract
|
||||
{
|
||||
/**
|
||||
* Get the validator for the request.
|
||||
*
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function validator()
|
||||
{
|
||||
$validator = Validator::make($this->all(), [
|
||||
'braintree_type' => 'required',
|
||||
'braintree_token' => 'required',
|
||||
'plan' => 'required|in:'.Spark::activePlanIdList()
|
||||
]);
|
||||
|
||||
return $validator->after(function ($validator) {
|
||||
$this->validatePlanEligibility($validator);
|
||||
|
||||
if ($this->coupon) {
|
||||
$this->validateCoupon($validator);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Subscription;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Laravel\Spark\Http\Requests\ValidatesBillingAddresses;
|
||||
use Laravel\Spark\Contracts\Http\Requests\Settings\Subscription\CreateSubscriptionRequest as Contract;
|
||||
|
||||
class CreateStripeSubscriptionRequest extends CreateSubscriptionRequest implements Contract
|
||||
{
|
||||
use ValidatesBillingAddresses;
|
||||
|
||||
/**
|
||||
* Get the validator for the request.
|
||||
*
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function validator()
|
||||
{
|
||||
$validator = Validator::make($this->all(), [
|
||||
'stripe_token' => 'required',
|
||||
'plan' => 'required|in:'.Spark::activePlanIdList(),
|
||||
'vat_id' => 'nullable|max:50|vat_id',
|
||||
]);
|
||||
|
||||
if (Spark::collectsBillingAddress()) {
|
||||
$this->validateBillingAddress($validator);
|
||||
}
|
||||
|
||||
return $validator->after(function ($validator) {
|
||||
$this->validatePlanEligibility($validator);
|
||||
|
||||
if ($this->coupon) {
|
||||
$this->validateCoupon($validator);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Subscription;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Laravel\Spark\Contracts\Repositories\CouponRepository;
|
||||
|
||||
class CreateSubscriptionRequest extends FormRequest
|
||||
{
|
||||
use DeterminesPlanEligibility;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the coupon on the request.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @return void
|
||||
*/
|
||||
protected function validateCoupon($validator)
|
||||
{
|
||||
if (! app(CouponRepository::class)->valid($this->coupon)) {
|
||||
$validator->errors()->add('coupon', 'This coupon code is invalid.');
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Subscription;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Laravel\Spark\Exceptions\IneligibleForPlan;
|
||||
|
||||
trait DeterminesPlanEligibility
|
||||
{
|
||||
/**
|
||||
* Validate that the plan is eligible based on team restrictions.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @return void
|
||||
*/
|
||||
protected function validatePlanEligibility($validator)
|
||||
{
|
||||
$plan = Spark::plans()->where('id', $this->plan)->first();
|
||||
|
||||
// If the desired plan is free, we will always need to let the user switch to that
|
||||
// plan since we'll want the user to always be able to cancel this subscription
|
||||
// without preventing them. So, we will just return here if it's a free plan.
|
||||
if (! $plan || $plan->price === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->callCustomCallback($validator, $plan);
|
||||
|
||||
// If the user is ineligible for a plan based on their team member or collaborator
|
||||
// count, we will prevent them switching to this plan and send an error message
|
||||
// back to the client informing them of this limitation and they can upgrade.
|
||||
if (! $this->userIsEligibleForPlan($plan)) {
|
||||
$validator->errors()->add(
|
||||
'plan', trans('spark::validation.eligibility')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user is eligible to move to a given plan.
|
||||
*
|
||||
* @param \Laravel\Spark\Plan $plan
|
||||
* @return bool
|
||||
*/
|
||||
protected function userIsEligibleForPlan($plan)
|
||||
{
|
||||
return ! $this->exceedsMaximumTeams($plan) &&
|
||||
! $this->exceedsMaximumTeamMembers($plan) &&
|
||||
! $this->exceedsMaximumCollaborators($plan);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user exceeds the maximum teams.
|
||||
*
|
||||
* @param \Laravel\Spark\Plan $plan
|
||||
* @return bool
|
||||
*/
|
||||
protected function exceedsMaximumTeams($plan)
|
||||
{
|
||||
if (is_null($plan->teams)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $plan->teams < $this->user()->ownedTeams()->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user exceeds the maximum team members for the plan.
|
||||
*
|
||||
* @param \Laravel\Spark\Plan $plan
|
||||
* @return bool
|
||||
*/
|
||||
protected function exceedsMaximumTeamMembers($plan)
|
||||
{
|
||||
if (is_null($plan->teamMembers)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! is_null($this->user()->teams->first(function ($team) use ($plan) {
|
||||
return $plan->teamMembers < $team->totalPotentialUsers();
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user exceeds the maximum total collaborators for the plan.
|
||||
*
|
||||
* @param \Laravel\Spark\Plan $plan
|
||||
* @return bool
|
||||
*/
|
||||
protected function exceedsMaximumCollaborators($plan)
|
||||
{
|
||||
return ! is_null($plan->collaborators) &&
|
||||
$plan->collaborators < $this->user()->totalPotentialCollaborators();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the custom plan eligibility checker callback.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @param \Laravel\Spark\Plan $plan
|
||||
* @return void
|
||||
*/
|
||||
protected function callCustomCallback($validator, $plan)
|
||||
{
|
||||
try {
|
||||
if (! Spark::eligibleForPlan($this->user(), $plan)) {
|
||||
$validator->errors()->add('plan', 'You are not eligible for this plan.');
|
||||
}
|
||||
} catch (IneligibleForPlan $e) {
|
||||
$validator->errors()->add('plan', $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Subscription;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UpdateSubscriptionRequest extends FormRequest
|
||||
{
|
||||
use DeterminesPlanEligibility;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validator for the request.
|
||||
*
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function validator()
|
||||
{
|
||||
$validator = Validator::make($this->all(), [
|
||||
'plan' => 'required|in:'.Spark::activePlanIdList()
|
||||
]);
|
||||
|
||||
return $validator->after(function ($validator) {
|
||||
$this->validatePlanEligibility($validator);
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Teams;
|
||||
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class CreateInvitationRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return $this->user()->ownsTeam($this->team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validator for the request.
|
||||
*
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function validator()
|
||||
{
|
||||
$validator = Validator::make($this->all(), [
|
||||
'email' => 'required|email|max:255',
|
||||
]);
|
||||
|
||||
$validator->after(function ($validator) {
|
||||
$this->validateMaxTeamMembersNotExceeded($validator);
|
||||
});
|
||||
|
||||
return $validator->after(function ($validator) {
|
||||
return $this->verifyEmailNotAlreadyOnTeam($validator, $this->team)
|
||||
->verifyEmailNotAlreadyInvited($validator, $this->team);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the maximum number of team members hasn't been exceeded.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @return void
|
||||
*/
|
||||
protected function validateMaxTeamMembersNotExceeded($validator)
|
||||
{
|
||||
if ($plan = $this->user()->sparkPlan()) {
|
||||
$this->validateMaxTeamMembersNotExceededForPlan($validator, $plan);
|
||||
}
|
||||
|
||||
if ($plan = $this->team->sparkPlan()) {
|
||||
$this->validateMaxTeamMembersNotExceededForPlan($validator, $plan);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the team member limit hasn't been exceeded for the given plan.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @param \Laravel\Spark\Plan $plan
|
||||
* @return void
|
||||
*/
|
||||
protected function validateMaxTeamMembersNotExceededForPlan($validator, $plan)
|
||||
{
|
||||
if (is_null($plan->teamMembers) && is_null($plan->collaborators)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->exceedsMaxTeamMembers($plan) || $this->exceedsMaxCollaborators($plan)) {
|
||||
$validator->errors()->add('email', 'Please upgrade your subscription to add more team members.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request will exceed the max allowed team members.
|
||||
*
|
||||
* @param \Laravel\Spark\Plan $plan
|
||||
* @return bool
|
||||
*/
|
||||
protected function exceedsMaxTeamMembers($plan)
|
||||
{
|
||||
return ! is_null($plan->teamMembers) &&
|
||||
$plan->teamMembers <= $this->team->totalPotentialUsers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the request will exceed the max allowed collaborators.
|
||||
*
|
||||
* @param \Laravel\Spark\Plan $plan
|
||||
* @return bool
|
||||
*/
|
||||
protected function exceedsMaxCollaborators($plan)
|
||||
{
|
||||
return ! is_null($plan->collaborators) &&
|
||||
$plan->collaborators <= $this->user()->totalPotentialCollaborators();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the given e-mail is not already on the team.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @param \Laravel\Spark\Team $team
|
||||
* @return $this
|
||||
*/
|
||||
protected function verifyEmailNotAlreadyOnTeam($validator, $team)
|
||||
{
|
||||
if ($team->users()->where('email', $this->email)->exists()) {
|
||||
$validator->errors()->add('email', 'That user is already on the team.');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the given e-mail is not already invited.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @param \Laravel\Spark\Team $team
|
||||
* @return $this
|
||||
*/
|
||||
protected function verifyEmailNotAlreadyInvited($validator, $team)
|
||||
{
|
||||
if ($team->invitations()->where('email', $this->email)->exists()) {
|
||||
$validator->errors()->add('email', 'That user is already invited to the team.');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Teams;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class RemoveTeamMemberRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
$team = $this->route('team');
|
||||
|
||||
$member = $this->route('team_member');
|
||||
|
||||
return ($this->user()->ownsTeam($team) && $this->user()->id !== $member->id) ||
|
||||
(! $this->user()->ownsTeam($team) && $this->user()->id === $member->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules for the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Teams\Subscription;
|
||||
|
||||
use Laravel\Spark\Contracts\Http\Requests\Settings\Teams\Subscription\CreateSubscriptionRequest as Contract;
|
||||
|
||||
class CreateBraintreeSubscriptionRequest extends CreateSubscriptionRequest implements Contract
|
||||
{
|
||||
/**
|
||||
* Get the validator for the request.
|
||||
*
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function validator()
|
||||
{
|
||||
return $this->baseValidator([
|
||||
'braintree_type' => 'required',
|
||||
'braintree_token' => 'required',
|
||||
]);
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Teams\Subscription;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Laravel\Spark\Http\Requests\ValidatesBillingAddresses;
|
||||
use Laravel\Spark\Contracts\Http\Requests\Settings\Teams\Subscription\CreateSubscriptionRequest as Contract;
|
||||
|
||||
class CreateStripeSubscriptionRequest extends CreateSubscriptionRequest implements Contract
|
||||
{
|
||||
use ValidatesBillingAddresses;
|
||||
|
||||
/**
|
||||
* Get the validator for the request.
|
||||
*
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function validator()
|
||||
{
|
||||
$validator = $this->baseValidator([
|
||||
'stripe_token' => 'required',
|
||||
'vat_id' => 'nullable|max:50|vat_id',
|
||||
]);
|
||||
|
||||
if (Spark::collectsBillingAddress()) {
|
||||
$this->validateBillingAddress($validator);
|
||||
}
|
||||
|
||||
return $validator;
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Teams\Subscription;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Laravel\Spark\Contracts\Repositories\CouponRepository;
|
||||
|
||||
class CreateSubscriptionRequest extends FormRequest
|
||||
{
|
||||
use DeterminesTeamPlanEligibility;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return $this->user() && $this->user()->ownsTeam($this->route('team'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validator instance for the request.
|
||||
*
|
||||
* @param array $rules
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function baseValidator(array $rules)
|
||||
{
|
||||
$validator = Validator::make($this->all(), array_merge([
|
||||
'plan' => 'required|in:'.Spark::activeTeamPlanIdList()
|
||||
], $rules));
|
||||
|
||||
return $validator->after(function ($validator) {
|
||||
$this->validatePlanEligibility($validator);
|
||||
|
||||
if ($this->coupon) {
|
||||
$this->validateCoupon($validator);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the coupon on the request.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @return void
|
||||
*/
|
||||
protected function validateCoupon($validator)
|
||||
{
|
||||
if (! app(CouponRepository::class)->valid($this->coupon)) {
|
||||
$validator->errors()->add('coupon', 'This coupon code is invalid.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Spark plan associated with the request.
|
||||
*
|
||||
* @return \Laravel\Spark\Plan
|
||||
*/
|
||||
public function plan()
|
||||
{
|
||||
return Spark::teamPlans()->where('id', $this->plan)->first();
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Teams\Subscription;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Laravel\Spark\Exceptions\IneligibleForPlan;
|
||||
|
||||
trait DeterminesTeamPlanEligibility
|
||||
{
|
||||
/**
|
||||
* Validate that the plan is eligible based on team restrictions.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @return void
|
||||
*/
|
||||
protected function validatePlanEligibility($validator)
|
||||
{
|
||||
$plan = Spark::teamPlans()->where('id', $this->plan)->first();
|
||||
|
||||
// If the desired plan is free, we will always need to let the user switch to that
|
||||
// plan since we'll want the user to always be able to cancel this subscription
|
||||
// without preventing them. So, we will just return here if it's a free plan.
|
||||
if (! $plan || $plan->price === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->callCustomCallback($validator, $plan);
|
||||
|
||||
// If the user is ineligible for a plan based on their team member or collaborator
|
||||
// count, we will prevent them switching to this plan and send an error message
|
||||
// back to the client informing them of this limitation and they can upgrade.
|
||||
if (! $this->teamIsEligibleForPlan($this->route('team'), $plan)) {
|
||||
$validator->errors()->add(
|
||||
'plan', 'This team has too many team members for the selected plan.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the team is eligible to move to a given plan.
|
||||
*
|
||||
* @param \Laravel\Spark\Team $team
|
||||
* @param \Laravel\Spark\Plan $plan
|
||||
* @return bool
|
||||
*/
|
||||
protected function teamIsEligibleForPlan($team, $plan)
|
||||
{
|
||||
return ! $this->exceedsMaximumTeamMembers($team, $plan);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the team exceeds the maximum team members for the plan.
|
||||
*
|
||||
* @param \Laravel\Spark\Team $team
|
||||
* @param \Laravel\Spark\Plan $plan
|
||||
* @return bool
|
||||
*/
|
||||
protected function exceedsMaximumTeamMembers($team, $plan)
|
||||
{
|
||||
return ! is_null($plan->teamMembers)
|
||||
? $plan->teamMembers < $team->totalPotentialUsers() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the custom plan eligibility checker callback.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @param \Laravel\Spark\Plan $plan
|
||||
* @return void
|
||||
*/
|
||||
protected function callCustomCallback($validator, $plan)
|
||||
{
|
||||
try {
|
||||
if (! Spark::eligibleForTeamPlan($this->route('team'), $plan)) {
|
||||
$validator->errors()->add('plan', 'This team is not eligible for this plan.');
|
||||
}
|
||||
} catch (IneligibleForPlan $e) {
|
||||
$validator->errors()->add('plan', $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Teams\Subscription;
|
||||
|
||||
use Laravel\Spark\Spark;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UpdateSubscriptionRequest extends FormRequest
|
||||
{
|
||||
use DeterminesTeamPlanEligibility;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return $this->user()->ownsTeam($this->route('team'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validator for the request.
|
||||
*
|
||||
* @return \Illuminate\Validation\Validator
|
||||
*/
|
||||
public function validator()
|
||||
{
|
||||
$validator = Validator::make($this->all(), [
|
||||
'plan' => 'required|in:'.Spark::activeTeamPlanIdList()
|
||||
]);
|
||||
|
||||
return $validator->after(function ($validator) {
|
||||
$this->validatePlanEligibility($validator);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Spark plan associated with the request.
|
||||
*
|
||||
* @return \Laravel\Spark\Plan
|
||||
*/
|
||||
public function plan()
|
||||
{
|
||||
return Spark::teamPlans()->where('id', $this->plan)->first();
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests\Settings\Teams;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UpdateTeamPhotoRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return $this->user()->ownsTeam($this->route('team'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules for the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'photo' => 'required|image|max:4000'
|
||||
];
|
||||
}
|
||||
}
|
63
spark/src/Http/Requests/ValidatesBillingAddresses.php
Normal file
63
spark/src/Http/Requests/ValidatesBillingAddresses.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Laravel\Spark\Http\Requests;
|
||||
|
||||
use Laravel\Spark\Services\Stripe as StripeService;
|
||||
|
||||
trait ValidatesBillingAddresses
|
||||
{
|
||||
/**
|
||||
* Merges billing address validation rules into the given validator.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @return void
|
||||
*/
|
||||
protected function validateBillingAddress($validator)
|
||||
{
|
||||
$this->mergeCardCountryIntoRequest();
|
||||
|
||||
$validator->addRules([
|
||||
'address' => 'required|max:255',
|
||||
'address_line_2' => 'max:255',
|
||||
'city' => 'required|max:255',
|
||||
'state' => 'required|max:255|state:'.$this->country,
|
||||
'zip' => 'required|max:25',
|
||||
'country' => 'required|max:2|country',
|
||||
]);
|
||||
|
||||
$validator->after(function ($validator) {
|
||||
$this->validateLocation($validator);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the billing card country into the request.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function mergeCardCountryIntoRequest()
|
||||
{
|
||||
if (! $this->stripe_token) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->merge(['card_country' => app(StripeService::class)->countryForToken(
|
||||
$this->stripe_token
|
||||
)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the request's location information agrees.
|
||||
*
|
||||
* @param \Illuminate\Validation\Validator $validator
|
||||
* @return void
|
||||
*/
|
||||
protected function validateLocation($validator)
|
||||
{
|
||||
if (! app(StripeService::class)->tokenIsForCountry($this->stripe_token, $this->country)) {
|
||||
$validator->errors()->add(
|
||||
'country', 'This country does not match the origin country of your card.'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
197
spark/src/Http/routes.php
Normal file
197
spark/src/Http/routes.php
Normal file
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
$router->group(['middleware' => 'web'], function ($router) {
|
||||
$teamString = Spark::teamString();
|
||||
|
||||
$pluralTeamString = str_plural(Spark::teamString());
|
||||
|
||||
// Terms Of Service...
|
||||
$router->get('/terms', 'TermsController@show')->name('terms');
|
||||
|
||||
// Missing Team Notice...
|
||||
$router->get('/missing-'.$teamString, 'MissingTeamController@show');
|
||||
|
||||
// Customer Support...
|
||||
$router->post('/support/email', 'SupportController@sendEmail');
|
||||
|
||||
// API Token Refresh...
|
||||
$router->put('/spark/token', 'TokenController@refresh');
|
||||
|
||||
// Users...
|
||||
$router->get('/user/current', 'UserController@current');
|
||||
$router->put('/user/last-read-announcements-at', 'UserController@updateLastReadAnnouncementsTimestamp');
|
||||
|
||||
// Notifications
|
||||
$router->get('/notifications/recent', 'NotificationController@recent');
|
||||
$router->put('/notifications/read', 'NotificationController@markAsRead');
|
||||
|
||||
// Settings Dashboard...
|
||||
$router->get('/settings', 'Settings\DashboardController@show')->name('settings');
|
||||
|
||||
// Profile Contact Information...
|
||||
$router->put('/settings/contact', 'Settings\Profile\ContactInformationController@update');
|
||||
|
||||
// Profile Photo...
|
||||
$router->post('/settings/photo', 'Settings\Profile\PhotoController@store');
|
||||
|
||||
// Teams...
|
||||
if (Spark::usesTeams()) {
|
||||
// General Settings...
|
||||
$router->get('/settings/'.$pluralTeamString.'/roles', 'Settings\Teams\TeamMemberRoleController@all');
|
||||
$router->get('/settings/'.$pluralTeamString.'/{team}', 'Settings\Teams\DashboardController@show')->name('settings.team');
|
||||
|
||||
$router->get('/'.$pluralTeamString.'', 'TeamController@all');
|
||||
$router->get('/'.$pluralTeamString.'/current', 'TeamController@current');
|
||||
$router->get('/'.$pluralTeamString.'/{team_id}', 'TeamController@show');
|
||||
$router->post('/settings/'.$pluralTeamString, 'Settings\Teams\TeamController@store');
|
||||
$router->post('/settings/'.$pluralTeamString.'/{team}/photo', 'Settings\Teams\TeamPhotoController@update');
|
||||
$router->put('/settings/'.$pluralTeamString.'/{team}/name', 'Settings\Teams\TeamNameController@update');
|
||||
|
||||
// Invitations...
|
||||
$router->get('/settings/'.$pluralTeamString.'/{team}/invitations', 'Settings\Teams\MailedInvitationController@all');
|
||||
$router->post('/settings/'.$pluralTeamString.'/{team}/invitations', 'Settings\Teams\MailedInvitationController@store');
|
||||
$router->get('/settings/invitations/pending', 'Settings\Teams\PendingInvitationController@all');
|
||||
$router->get('/invitations/{invitation}', 'InvitationController@show');
|
||||
$router->post('/settings/invitations/{invitation}/accept', 'Settings\Teams\PendingInvitationController@accept');
|
||||
$router->post('/settings/invitations/{invitation}/reject', 'Settings\Teams\PendingInvitationController@reject');
|
||||
$router->delete('/settings/invitations/{invitation}', 'Settings\Teams\MailedInvitationController@destroy');
|
||||
|
||||
$router->put('/settings/'.$pluralTeamString.'/{team}/members/{team_member}', 'Settings\Teams\TeamMemberController@update');
|
||||
$router->delete('/settings/'.$pluralTeamString.'/{team}/members/{team_member}', 'Settings\Teams\TeamMemberController@destroy');
|
||||
$router->delete('/settings/'.$pluralTeamString.'/{team}', 'Settings\Teams\TeamController@destroy');
|
||||
$router->get('/'.$pluralTeamString.'/{team}/switch', 'TeamController@switchCurrentTeam');
|
||||
|
||||
// Billing
|
||||
|
||||
// Subscription Settings...
|
||||
$router->post('/settings/'.$pluralTeamString.'/{team}/subscription', 'Settings\Teams\Subscription\PlanController@store');
|
||||
$router->put('/settings/'.$pluralTeamString.'/{team}/subscription', 'Settings\Teams\Subscription\PlanController@update');
|
||||
$router->delete('/settings/'.$pluralTeamString.'/{team}/subscription', 'Settings\Teams\Subscription\PlanController@destroy');
|
||||
|
||||
// VAT ID Settings...
|
||||
$router->put('/settings/'.$pluralTeamString.'/{team}/payment-method/vat-id', 'Settings\Teams\PaymentMethod\VatIdController@update');
|
||||
|
||||
// Credit Card Settings...
|
||||
$router->put('/settings/'.$pluralTeamString.'/{team}/payment-method', 'Settings\Teams\PaymentMethod\PaymentMethodController@update');
|
||||
|
||||
// Redeem Coupon...
|
||||
$router->post('/settings/'.$pluralTeamString.'/{team}/payment-method/coupon', 'Settings\Teams\PaymentMethod\RedeemCouponController@redeem');
|
||||
|
||||
// Billing History...
|
||||
$router->put(
|
||||
'/settings/'.$pluralTeamString.'/{team}/extra-billing-information',
|
||||
'Settings\Teams\Billing\BillingInformationController@update'
|
||||
);
|
||||
|
||||
// Coupons...
|
||||
$router->get('/coupon/'.$teamString.'/{id}', 'TeamCouponController@current');
|
||||
|
||||
// Invoices...
|
||||
$router->get('/settings/'.$pluralTeamString.'/{team}/invoices', 'Settings\Teams\Billing\InvoiceController@all');
|
||||
$router->get('/settings/'.$pluralTeamString.'/{team}/invoice/{id}', 'Settings\Teams\Billing\InvoiceController@download');
|
||||
}
|
||||
|
||||
// Security Settings...
|
||||
$router->put('/settings/password', 'Settings\Security\PasswordController@update');
|
||||
$router->post('/settings/two-factor-auth', 'Settings\Security\TwoFactorAuthController@enable');
|
||||
$router->delete('/settings/two-factor-auth', 'Settings\Security\TwoFactorAuthController@disable');
|
||||
|
||||
// API Settings
|
||||
$router->get('/settings/api/tokens', 'Settings\API\TokenController@all');
|
||||
$router->post('/settings/api/token', 'Settings\API\TokenController@store');
|
||||
$router->put('/settings/api/token/{token_id}', 'Settings\API\TokenController@update');
|
||||
$router->get('/settings/api/token/abilities', 'Settings\API\TokenAbilitiesController@all');
|
||||
$router->delete('/settings/api/token/{token_id}', 'Settings\API\TokenController@destroy');
|
||||
|
||||
// Plans...
|
||||
$router->get('/spark/plans', 'PlanController@all');
|
||||
|
||||
// Subscription Settings...
|
||||
$router->post('/settings/subscription', 'Settings\Subscription\PlanController@store');
|
||||
$router->put('/settings/subscription', 'Settings\Subscription\PlanController@update');
|
||||
$router->delete('/settings/subscription', 'Settings\Subscription\PlanController@destroy');
|
||||
|
||||
// VAT ID Settings...
|
||||
$router->put('/settings/payment-method/vat-id', 'Settings\PaymentMethod\VatIdController@update');
|
||||
|
||||
// Credit Card Settings...
|
||||
$router->put('/settings/payment-method', 'Settings\PaymentMethod\PaymentMethodController@update');
|
||||
|
||||
// Redeem Coupon...
|
||||
$router->post('/settings/payment-method/coupon', 'Settings\PaymentMethod\RedeemCouponController@redeem');
|
||||
|
||||
// Billing History...
|
||||
$router->put(
|
||||
'/settings/extra-billing-information',
|
||||
'Settings\Billing\BillingInformationController@update'
|
||||
);
|
||||
|
||||
// Invoices...
|
||||
$router->get('/settings/invoices', 'Settings\Billing\InvoiceController@all');
|
||||
$router->get('/settings/invoice/{id}', 'Settings\Billing\InvoiceController@download');
|
||||
|
||||
// Coupons...
|
||||
$router->get('/coupon/user/{id}', 'CouponController@current');
|
||||
$router->get('/coupon/{code}', 'CouponController@show');
|
||||
|
||||
// Kiosk...
|
||||
$router->get('/spark/kiosk', 'Kiosk\DashboardController@show')->name('kiosk');
|
||||
|
||||
// Kiosk Search...
|
||||
$router->post('/spark/kiosk/users/search', 'Kiosk\SearchController@performBasicSearch');
|
||||
|
||||
// Kiosk Announcements...
|
||||
$router->get('/spark/kiosk/announcements', 'Kiosk\AnnouncementController@all');
|
||||
$router->post('/spark/kiosk/announcements', 'Kiosk\AnnouncementController@store');
|
||||
$router->put('/spark/kiosk/announcements/{id}', 'Kiosk\AnnouncementController@update');
|
||||
$router->delete('/spark/kiosk/announcements/{id}', 'Kiosk\AnnouncementController@destroy');
|
||||
|
||||
// Kiosk Metrics / Performance Indicators...
|
||||
$router->get('/spark/kiosk/performance-indicators', 'Kiosk\PerformanceIndicatorsController@all');
|
||||
$router->get('/spark/kiosk/performance-indicators/revenue', 'Kiosk\PerformanceIndicatorsController@revenue');
|
||||
$router->get('/spark/kiosk/performance-indicators/plans', 'Kiosk\PerformanceIndicatorsController@subscribers');
|
||||
$router->get('/spark/kiosk/performance-indicators/trialing', 'Kiosk\PerformanceIndicatorsController@trials');
|
||||
|
||||
// Kiosk User Profiles...
|
||||
$router->get('/spark/kiosk/users/{id}/profile', 'Kiosk\ProfileController@show');
|
||||
|
||||
// Kiosk Discounts...
|
||||
$router->post('/spark/kiosk/users/discount/{id}', 'Kiosk\DiscountController@store');
|
||||
|
||||
// Kiosk Impersonation...
|
||||
$router->get('/spark/kiosk/users/impersonate/{id}', 'Kiosk\ImpersonationController@impersonate');
|
||||
$router->get('/spark/kiosk/users/stop-impersonating', 'Kiosk\ImpersonationController@stopImpersonating');
|
||||
|
||||
// Authentication...
|
||||
$router->get('/login', 'Auth\LoginController@showLoginForm')->name('login');
|
||||
$router->post('/login', 'Auth\LoginController@login');
|
||||
$router->get('/logout', 'Auth\LoginController@logout')->name('logout');
|
||||
|
||||
// Two-Factor Authentication Routes...
|
||||
$router->get('/login/token', 'Auth\LoginController@showTokenForm');
|
||||
$router->post('/login/token', 'Auth\LoginController@verifyToken');
|
||||
|
||||
// Two-Factor Emergency Token Login Routes...
|
||||
$router->get('/login-via-emergency-token', 'Auth\EmergencyLoginController@showLoginForm');
|
||||
$router->post('/login-via-emergency-token', 'Auth\EmergencyLoginController@login');
|
||||
|
||||
// Registration...
|
||||
$router->get('/register', 'Auth\RegisterController@showRegistrationForm')->name('register');
|
||||
$router->post('/register', 'Auth\RegisterController@register');
|
||||
|
||||
// Password Reset...
|
||||
$router->get('/password/reset/{token?}', 'Auth\PasswordController@showResetForm')->name('password.reset');
|
||||
$router->post('/password/email', 'Auth\PasswordController@sendResetLinkEmail');
|
||||
$router->post('/password/reset', 'Auth\PasswordController@reset');
|
||||
});
|
||||
|
||||
// Tax Rates...
|
||||
$router->post('/tax-rate', 'TaxRateController@calculate');
|
||||
|
||||
// Geocoding...
|
||||
$router->get('/geocode/country', 'GeocodingController@country');
|
||||
$router->get('/geocode/states/{country}', 'GeocodingController@states');
|
||||
|
||||
// Webhooks...
|
||||
$router->post('/webhook/stripe', 'Settings\Billing\StripeWebhookController@handleWebhook');
|
||||
$router->post('/webhook/braintree', 'Settings\Billing\BraintreeWebhookController@handleWebhook');
|
Reference in New Issue
Block a user