├── adding-profile-fields.md
├── adding-registration-fields.md
├── announcements.md
├── api.md
├── available-variables.md
├── billing.md
├── client-customization.md
├── customization.md
├── email-verification.md
├── european-vat.md
├── faq.md
├── forms.md
├── installation.md
├── kiosk.md
├── localization.md
├── notifications.md
├── quickstart.md
├── releases.md
├── support.md
├── teams.md
├── two-factor.md
└── upgrade.md
/adding-profile-fields.md:
--------------------------------------------------------------------------------
1 | # Adding Profile Fields
2 |
3 | - [Introduction](#introduction)
4 | - [Modifying The View](#modifying-the-view)
5 | - [Defining The JavaScript Component](#defining-the-javascript-component)
6 | - [Validation & Storage](#validation-and-storage)
7 |
8 |
9 | ## Introduction
10 |
11 | Once you've added extra fields to the Spark registration form, you will most likely want to add them to the user's "profile" settings, allowing them to update the fields even after they have registered. In this overview, we'll take a look at how to add an extra field to the profile form and update its value in our database.
12 |
13 |
14 | ## Modifying The View
15 |
16 | The "profile" tab of the settings dashboard contains several panels that allow the user to update various information. We will add a new panel to this screen which will allow our users to update their age. First, let's add a Blade `@include` directive to the `/resources/views/vendor/spark/settings/profile.blade.php` file to load a new `update-profile-details` template:
17 |
18 |
19 |
29 |
30 |
31 | This `@include` directive will load a new Blade template which contains our custom panel. We can define the new template at `/resources/views/settings/profile/update-profile-details`. This template will contain a simple form where the user can update their age:
32 |
33 |
34 |
35 |
Profile Details
36 |
37 |
38 |
39 |
40 | Your profile has been updated!
41 |
42 |
43 |
71 |
72 |
73 |
74 |
75 |
76 | ## Defining The JavaScript Component
77 |
78 | Next, we will define the new `update-profile-details` Vue component which will manage our new panel and form. We can define this component at `/resources/js/components/settings/profile/update-profile-details.js`:
79 |
80 | Vue.component('update-profile-details', {
81 | props: ['user'],
82 |
83 | data() {
84 | return {
85 | form: new SparkForm({
86 | age: ''
87 | })
88 | };
89 | },
90 |
91 | mounted() {
92 | this.form.age = this.user.age;
93 | },
94 |
95 | methods: {
96 | update() {
97 | Spark.put('/settings/profile/details', this.form)
98 | .then(response => {
99 | Bus.$emit('updateUser');
100 | });
101 | }
102 | }
103 | });
104 |
105 | Note that this component uses the `Spark.put` helper, which adds some convenient features on top of the `axios` library. The `Spark` HTTP helpers accept a form object and will automatically set the form's `busy` attribute to `true` when the form is submitted.
106 |
107 | When you define a new Vue component, you also need to instruct Spark to compile the component into your main `app.js` file. You can do this by adding a line to your `/resources/js/components/bootstrap.js` file:
108 |
109 | require('./home');
110 |
111 | // Load the new Vue component...
112 | require('./settings/profile/update-profile-details');
113 |
114 | > **Note:** After defining the new Vue component, remember to run the `npm run dev` command in your terminal to compile your JavaScript.
115 |
116 |
117 | ## Validation & Storage
118 |
119 | Next, we need to define a route and controller to handle updating the `age` for an existing user. First, let's add a route to our `routes/web.php` file:
120 |
121 | Route::put('/settings/profile/details', 'ProfileDetailsController@update');
122 |
123 | Once the route has been defined, we can define the controller in `app/Http/Controllers/ProfileDetailsController.php`:
124 |
125 | middleware('auth');
141 | }
142 |
143 | /**
144 | * Update the user's profile details.
145 | *
146 | * @return Response
147 | */
148 | public function update(Request $request)
149 | {
150 | $this->validate($request, [
151 | 'age' => 'required|integer|min:1',
152 | ]);
153 |
154 | $request->user()->forceFill([
155 | 'age' => $request->age
156 | ])->save();
157 | }
158 | }
159 |
160 | Finally, we're ready to visit the "profile" settings screen and update our age! This same general process can be applied to customizing most of the other "settings" screens within Spark, so feel free to customize any of these screens to meet the needs of your application.
161 |
--------------------------------------------------------------------------------
/adding-registration-fields.md:
--------------------------------------------------------------------------------
1 | # Adding Registration Fields
2 |
3 | - [Introduction](#introduction)
4 | - [Modifying The View](#modifying-the-view)
5 | - [Extending The JavaScript](#extending-the-javascript)
6 | - [Validation & Storage](#validation-and-storage)
7 |
8 |
9 | ## Introduction
10 |
11 | A common Spark extension use case is adding fields to the Spark registration form. In this overview, we'll take a look at how to add an extra field to the registration process and store its value in our database.
12 |
13 |
14 | ## Modifying The View
15 |
16 | First, let's add a new `age` form field to the `/resources/views/vendor/spark/auth/register-common-form.blade.php` file. We'll place this new field under the existing "e-mail" field:
17 |
18 |
19 |
32 |
33 | Remember, you're free to edit any of the views in `/resources/views/vendor/spark`. When you update Spark, any of the views you haven't modified will automatically be updated. If you have modified a view, you will be notified that it was not replaced in order to preserve your changes.
34 |
35 |
36 | ## Extending The JavaScript
37 |
38 | Since extending the registration form is a common use case, Spark makes it easy to add a field to the JavaScript object that models the registration form. In your `/resources/js/app.js` file, adding the following lines of code just before the call to `new Vue`:
39 |
40 | Spark.forms.register = {
41 | age: ''
42 | };
43 |
44 | var app = new Vue({
45 | mixins: [require('spark')]
46 | });
47 |
48 | The contents of `Spark.form.register` will automatically be merged with the base definition of the registration form.
49 |
50 |
51 | ## Validation & Storage
52 |
53 | Next, we need to customize Spark's new user validation and storage methods to handle our new `age` field. Within the `boot` method of our `SparkServiceProvider`, we'll call the `validateUsersWith` and `createUsersWith` methods to customize this logic. First, let's call `validateUsersWith` and define the validation rules for our new `age` field:
54 |
55 | Spark::validateUsersWith(function () {
56 | return [
57 | 'name' => 'required|max:255',
58 | 'age' => 'required|integer|min:1',
59 | 'email' => 'required|email|max:255|unique:users',
60 | 'password' => 'required|confirmed|min:6',
61 | 'vat_id' => 'max:50|vat_id',
62 | 'terms' => 'required|accepted',
63 | ];
64 | });
65 |
66 | If you do not want to pass a Closure, you may also pass a `Class@method` string to instruct Spark which class and method to call in order to obtain the validation rules:
67 |
68 | Spark::validateUsersWith('UserValidator@validate');
69 |
70 | Next, let's call `createUsersWith` to make sure our new field is stored in the database:
71 |
72 | use Illuminate\Support\Carbon;
73 |
74 | Spark::createUsersWith(function ($request) {
75 | $user = Spark::user();
76 |
77 | $data = $request->all();
78 |
79 | $user->forceFill([
80 | 'name' => $data['name'],
81 | 'email' => $data['email'],
82 | 'age' => $data['age'],
83 | 'password' => bcrypt($data['password']),
84 | 'last_read_announcements_at' => Carbon::now(),
85 | 'trial_ends_at' => Carbon::now()->addDays(Spark::trialDays()),
86 | ])->save();
87 |
88 | return $user;
89 | });
90 |
91 | As was the case with validation, you may also pass a `Class@method` callback:
92 |
93 | Spark::createUsersWith('UserCreator@create');
94 |
--------------------------------------------------------------------------------
/announcements.md:
--------------------------------------------------------------------------------
1 | # Announcements
2 |
3 | - [Introduction](#introduction)
4 | - [Announcement Events](#announcement-events)
5 |
6 |
7 | ## Introduction
8 |
9 | From the [Spark Kiosk](/docs/11.0/kiosk), you may create announcements to be displayed to your users. These announcements may be viewed by users when they click on the "notification bell" icon in the application's navigation bar. The notification bell will have an unread count indicator when there are unread announcements or notifications.
10 |
11 | To create an announcement, [configure your user as a developer](/docs/11.0/kiosk) and enter the Kiosk via the user profile drop-down menu, then click the "Announcements" tab.
12 |
13 | The announcement text supports Markdown, so feel free to use Markdown syntax within your announcement body. If needed, you may attach an "Action Button" to the announcement. Adding an action button gives users a chance to view more information about the announcement, such as a blog post.
14 |
15 |
16 | ## Announcement Events
17 |
18 | When an announcement is created, the `Laravel\Spark\Events\AnnouncementCreated` event is dispatched, allowing you to perform additional actions such as sending an announcement push notification, etc.
19 |
--------------------------------------------------------------------------------
/api.md:
--------------------------------------------------------------------------------
1 | # API
2 |
3 | - [Introduction](#introduction)
4 | - [Configuration](#configuration)
5 | - [Routes](#routes)
6 | - [Abilities](#abilities)
7 | - [API Driven Applications](#api-driven-applications)
8 | - [Sharing Your API With Your JavaScript Application](#sharing-your-api)
9 | - [Using Passport](#using-passport)
10 |
11 |
12 | ## Introduction
13 |
14 | Spark makes it simple for your users to generate API tokens that can be used to consume your application's API. You may even allow users to grant abilities to tokens to limit the scope of actions a given token can perform.
15 |
16 | In addition, Spark ships with a custom Laravel authentication guard to authenticate requests that are made using these tokens, allowing you to easily share the same back-end API for your main web application and your API SDKs you provide to your users and third parties.
17 |
18 |
19 | ## Configuration
20 |
21 | To enable API support, verify that the `$usesApi` property of your `SparkServiceProvider` is set to `true`. When API support is enabled, an "API" tab will be available to your users via their settings dashboard. From this dashboard users may generate and revoke API tokens.
22 |
23 |
24 | ## Routes
25 |
26 | Spark automatically generates a `routes/api.php` file to contain all of your API routes. This file is automatically loaded by the `RouteServiceProvider` and that provider also applies the `api` middleware by default. You are free to modify these settings as necessary for your own application. However, the default configuration should be suitable for most applications.
27 |
28 |
29 | ## Abilities
30 |
31 | If you would like to give users the ability to grant "abilities" to tokens and constrain the actions that a given token can perform, you may use the `tokensCan` method on the `Spark` configuration object. You should place this call within the `boot` method of your `SparkServiceProvider`:
32 |
33 | Spark::tokensCan([
34 | 'read-servers' => 'Read Servers',
35 | 'create-servers' => 'Create Servers',
36 | 'delete-servers' => 'Delete Servers',
37 | ]);
38 |
39 | The keys of the array given to this method should be unique "slugs" while the values are the displayable, human-readable versions of the abilities. Once you have defined these abilities, they will automatically be displayed on the API settings dashboard.
40 |
41 | ### Checking Abilities On Active Tokens
42 |
43 | Of course, you will need an easy method of determining if a token authenticated user's token can perform a given action. Spark makes it a cinch. When a user is authenticated via the `api` guard, you may access the `token` property on the user instance. The `token` property contains a `can` method which can be used to verify if a token has a given ability:
44 |
45 | Route::get('/api/servers', function () {
46 | if (Auth::user()->token()->can('read-servers')) {
47 | //
48 | }
49 | })->middleware('auth:api');
50 |
51 |
52 | ## API Driven Applications
53 |
54 | Once a user has an API token, they can access your API by passing the token in the `api_token` query string parameter when making requests. You should assign the `auth:api` middleware to all of the API routes you wish to authenticate:
55 |
56 | Route::get('/api/users', function () {
57 | //
58 | })->middleware('auth:api');
59 |
60 |
61 | ### Sharing Your API With Your JavaScript Application
62 |
63 | > **Note:** This feature requires that you use [Vue.js](https://vuejs.org) as your application's JavaScript framework.
64 |
65 | If your application exposes an API, it can be beneficial to consume that API yourself from your application's front-end JavaScript code. This allows you to share the same API between your application and your API SDKs you may be shipping on various package managers.
66 |
67 | Spark makes it entirely painless to consume your API in this way. Simply make requests to your API routes using your JavaScript framework as normal. You do not need to pass any token or credentials. All of the authentication will be handled automatically by Spark, which generates "transient", short-lived API tokens behind the scenes automatically when users load your application's pages. These API tokens are automatically refreshed in the background by Spark.
68 |
69 | So, if you are using Vue, you may simply call your API routes like normal. No additional configuration is necessary to start consuming your API:
70 |
71 | axios.get('/api/users')
72 | .then(response => {
73 | this.users = response.data;
74 | });
75 |
76 |
77 |
78 | ## Using Passport
79 |
80 | In addition to the built-in API authentication driver, Spark supports [Laravel Passport](https://laravel.com/docs/5.5/passport) out of the box. You may install Passport by following the [Passport installation documentation](https://laravel.com/docs/5.8/passport).
81 |
82 | After installing Passport, you can almost always use Passport as you would in any other Laravel application. However, instead of calling the `Passport::tokensCan()` method, you should use the `Spark::tokensCan()` method.
83 |
--------------------------------------------------------------------------------
/available-variables.md:
--------------------------------------------------------------------------------
1 | # Available Variables
2 |
3 | - [Introduction](#introduction)
4 | - [Accessing Via Vue Properties](#accessing-via-vue-properties)
5 | - [Accessing Via Global Spark Object](#accessing-via-global-spark-object)
6 | - [The Spark Computed Property](#the-spark-computed-property)
7 | - [Adding Custom Properties](#adding-custom-properties)
8 |
9 |
10 | ## Introduction
11 |
12 | While building your Spark application using Vue.js, you will commonly need access to a few pieces of key information such as the current user, the user's teams, and the user's current team. Spark makes it a breeze to access this information either using Vue component properties or the global `Spark.state` object.
13 |
14 |
15 | ## Accessing Via Vue Properties
16 |
17 | You may ask for the `user`, `teams`, or `currentTeam` properties in your Vue components. For example, let's add the properties to the `home.js` component:
18 |
19 | Vue.component('home', {
20 | props: ['user', 'teams', 'currentTeam'],
21 |
22 | mounted() {
23 | //
24 | }
25 | });
26 |
27 | Remember, a user may not have a current team if they do not belong to any teams at all. In this case, `currentTeam` will be `null` and the `teams` property will be an empty array.
28 |
29 | Next, just pass the properties into your component in your `home.blade.php` file:
30 |
31 |
32 |
33 |
34 | ## Accessing Via Global Spark Object
35 |
36 | You may also access data using the `Spark.state` object. For example, let's do this in the `home.js` component. Typically you should pass this data down your application via properties; however, the `Spark.state` object can be useful if you have deeply nested components where it is inconvenient to pass the data as properties:
37 |
38 | Vue.component('home', {
39 | props: ['user'],
40 |
41 | mounted() {
42 | console.log(Spark.state.user);
43 | console.log(Spark.state.teams);
44 | console.log(Spark.state.currentTeam);
45 | }
46 | });
47 |
48 |
49 | ## The Spark Computed Property
50 |
51 | Spark registers a global Vue mixin that makes a few properties available to all of your components. One of these properties is `spark`, which provides you with a variety of information about the current Spark application. By default, the `spark` computed property object contains the following information:
52 |
53 | Property | Description
54 | ------------- | -------------
55 | `cardUpFront` | Indicates if the application requires credit cards up front.
56 | `collectsBillingAddress` | Indicates if the application collects billing addresses.
57 | `collectsEuropeanVat` | Indicates if the application collects European VAT.
58 | `csrfToken` | The current Laravel CSRF token.
59 | `currencySymbol` | The symbol used throughout the application for formatting currency.
60 | `env` | The current Laravel application environment.
61 | `roles` | All of the available user roles.
62 | `userId` | The current user's ID.
63 | `usesApi` | Indicates if the application exposes an API.
64 | `usesTeams` | Indicates if the application supports teams.
65 |
66 | You may access these properties in your templates or in your JavaScript:
67 |
68 |
69 |
70 | This application has an API.
71 |
72 |
73 |
74 | if (this.spark.usesApi) {
75 | console.log('This application has an API.');
76 | }
77 |
78 |
79 | ### Adding Custom Properties
80 |
81 | You can add your own properties to the `spark` computed property by adding them to your `resources/views/vendor/spark/layouts/app.blade.php` file. They will be merged with the default properties that are available on the object:
82 |
83 | window.Spark = 'value'
86 | 'another-custom-value' => 'value'
87 | ]
88 | )); ?>
89 |
--------------------------------------------------------------------------------
/billing.md:
--------------------------------------------------------------------------------
1 | # Billing
2 |
3 | - [Provider Configuration](#provider-configuration)
4 | - [Webhooks](#webhooks)
5 | - [Configuring Billing Plans](#configuring-billing-plans)
6 | - [Configuring User Billing Plans](#configuring-billing-plans)
7 | - [Configuring Team Billing Plans](#configuring-team-billing-plans)
8 | - [No Credit Card Up Front](#no-credit-card-up-front)
9 | - [Requiring Credit Cards Up Front](#requiring-credit-cards-up-front)
10 | - [Collecting Billing Addresses](#collecting-billing-addresses)
11 | - [Constraining Access To Plans](#constraining-access-to-plans)
12 | - [Archiving Plans](#archiving-plans)
13 | - [Charging Per Seat](#charging-per-seat)
14 | - [Charging Users Per Team](#charging-users-per-team)
15 | - [Charging Teams Per Member](#charging-teams-per-member)
16 | - [Custom Per Seat Targets](#custom-per-seat-targets)
17 | - [Checking Subscription Status Via Middleware](#checking-subscription-status-via-middleware)
18 | - [Site Wide Promotions](#site-wide-promotions)
19 | - [Currency Customization](#currency-customization)
20 | - [Proration](#proration)
21 | - [Billing Events](#billing-events)
22 |
23 |
24 | ## Provider Configuration
25 |
26 | After installing Spark, your application's `.env` file will contain the `STRIPE_KEY` and `STRIPE_SECRET` environment variables that need to be populated. You may retrieve these values from your Stripe control panel.
27 |
28 |
29 | ### Webhooks
30 |
31 | Stripe webhooks should be configured to point to the `/webhook/stripe` URI. Here's the list of event types you need to configure:
32 |
33 | - customer.subscription.updated
34 | - customer.subscription.deleted
35 | - customer.updated
36 | - customer.deleted
37 | - invoice.payment_action_required
38 | - invoice.payment_succeeded
39 |
40 |
41 | ## Configuring Billing Plans
42 |
43 | ### Configuring User Billing Plans
44 |
45 | All of your application's billing plans are defined in the `app/Providers/SparkServiceProvider` class. Of course, this service provider is automatically generated when you create a new Spark project. Within the service provider's `boot` method, you will find a sample plan already defined. The default Spark application defines a "no card up front" trial plan, which will allow new users to sign up for your application without providing their billing details during their initial registration.
46 |
47 | You may modify this plan and define additional plans as needed. The first argument given to the `plan` method is the displayable name of the plan while the second argument is the plan's ID on Stripe:
48 |
49 | Spark::plan('Pro', 'monthly-pro')
50 | ->price(20)
51 | ->features([
52 | 'Feature 1',
53 | 'Feature 2',
54 | 'Feature 3',
55 | ]);
56 |
57 | The `features` method accepts an array of features provided by a given plan. These features will be displayed when a user clicks the "Plan Features" modal on the registration or settings views.
58 |
59 | If you would like to define a plan that has a yearly billing frequency, you may use the `yearly` method:
60 |
61 | Spark::plan('Pro', 'yearly-pro')
62 | ->price(100)
63 | ->yearly()
64 | ->features([
65 | 'Feature 1',
66 | 'Feature 2',
67 | 'Feature 3',
68 | ]);
69 |
70 |
71 | ### Configuring Team Billing Plans
72 |
73 | Team billing plans allows teams to subscribe to billing plans instead of users. For example, a user may create one team for their business that is subscribed to the "Pro" plan, while having another team for their personal projects that is subscribed to the "Basic" plan.
74 |
75 | If your application offers team plans instead of individual user plans, you should generate your application using the `--team-billing` switch. This will generate a `SparkServiceProvider` stub that defines team plans instead of individual plans:
76 |
77 | spark new project-name --team-billing
78 |
79 | When your application provides team billing, the `boot` method of your `SparkServiceProvider` should typically contain a configuration like the following:
80 |
81 | Spark::noCardUpFront()->teamTrialDays(10);
82 |
83 | Spark::freeTeamPlan()
84 | ->features([
85 | 'First', 'Second', 'Third'
86 | ]);
87 |
88 | Spark::teamPlan('Basic', 'team-basic')
89 | ->price(10)
90 | ->features([
91 | 'First', 'Second', 'Third'
92 | ]);
93 |
94 | > **Note:** You may define user and team billing plans within the same application.
95 |
96 | #### Limiting Team Members Per Plan
97 |
98 | Since it's common to limit the number of team members a given team may have for a given plan, Spark makes configuring these constraints a breeze. You may use the `maxTeamMembers` method when defining your team plan. Once this is configured, Spark will automatically validate that attempted plan changes are valid based on the number of team members allowed for the plan:
99 |
100 | Spark::teamPlan('Basic', 'team-basic')
101 | ->price(10)
102 | ->maxTeamMembers(5)
103 | ->features([
104 | 'Five Team Members',
105 | 'Feature 2',
106 | 'Feature 3',
107 | ]);
108 |
109 |
110 | ### No Credit Card Up Front
111 |
112 | By default, Spark is configured to allow users to register without providing their credit card. After registering, they may choose to fully subscribe to the application at any time before their trial period ends. The number of trial days granted to a user when they register is defined by the `trialDays` method that is called on the `Spark` instance in the `SparkServiceProvider`. Or, if you are using team billing, you should use the `teamTrialDays` method instead:
113 |
114 | // When using user billing...
115 | Spark::noCardUpFront()->trialDays(10);
116 |
117 | // When using team billing...
118 | Spark::noCardUpFront()->teamTrialDays(10);
119 |
120 | If a customer registers while Spark is configured in this way, they will be placed on a "generic trial", meaning they will not actually be subscribed to any of your plans. If you would like to know if a customer is on a "no card up front", generic trial, you may use the `onGenericTrial` method on the user (or team if using team billing) instance. This method may be used to limit access to certain features when a user is on a generic trial:
121 |
122 | // Via user...
123 | $user->onGenericTrial();
124 |
125 | // Via team...
126 | $team->onGenericTrial();
127 |
128 |
129 | ### Requiring Credit Cards Up Front
130 |
131 | By default, Spark is configured to allow users to register without providing their credit card. After registering, they may choose to fully subscribe to the application at any time before their trial period ends.
132 |
133 | However, you may wish to gather credit card details up front. To do so, remove the calls to `noCardUpFront` and `trialDays` / `teamTrialDays` from your `SparkServiceProvider`. This will instruct the registration view to gather the user's credit card details up front.
134 |
135 | If you would like to gather credit card details up front but also offer trial periods on your plans, you will need to define the `trialDays` on the plans themselves:
136 |
137 | Spark::plan('Basic', 'team-basic')
138 | ->price(10)
139 | ->trialDays(10)
140 | ->features([
141 | 'Five Team Members',
142 | 'Feature 2',
143 | 'Feature 3',
144 | ]);
145 |
146 | > **Note:** If you define your plans in this manner, users will be **automatically** billed once their trial period expires unless they cancel their subscription.
147 |
148 |
149 | ### Collecting Billing Addresses
150 |
151 | > **Note:** This feature is only supported if your application is using Stripe for subscription billing.
152 |
153 | If you would like to collect your customer's billing addresses during registration and during payment method updates, you may call the `collectBillingAddress` method on the Spark instance in the `boot` method of your `SparkServiceProvider`:
154 |
155 | Spark::collectBillingAddress();
156 |
157 |
158 | ### Constraining Access To Plans
159 |
160 | Sometimes you may wish to limit plans by a given resource. For example, perhaps your project management application's "Pro" plan only allows a user to create 20 projects, while your "Enterprise" plan allows users to create up to 50 projects. In this example, a user on the Enterprise plan could not downgrade to the Pro plan if they still have 40 projects attached to their account.
161 |
162 | Spark allows you to customize these rules using the `checkPlanEligibilityUsing` method which accepts a Closure as its single argument. This Closure receives the current user and the plan the user is attempting to subscribe to. It is up to you to either return `true` or `false` from this callback based on whether the user should be allowed to change to the given plan. You can call this method from the `boot` method of your application's `SparkServiceProvider`:
163 |
164 | Spark::checkPlanEligibilityUsing(function ($user, $plan) {
165 | if ($plan->name == 'pro' && count($user->todos) > 20) {
166 | return false;
167 | }
168 |
169 | return true;
170 | });
171 |
172 | Alternatively, you may pass a class / method reference:
173 |
174 | Spark::checkPlanEligibilityUsing('EligibilityChecker@handle');
175 |
176 | If you would like to provide a specific reason the user is not allowed to switch to a given plan, you may throw a `IneligibleForPlan` exception from the callback. The given reason will be displayed to the user on the subscription update screen:
177 |
178 | use Laravel\Spark\Exceptions\IneligibleForPlan;
179 |
180 | Spark::checkPlanEligibilityUsing(function ($user, $plan) {
181 | if ($plan->name == 'pro' && $user->todos->count() > 20) {
182 | throw IneligibleForPlan::because('You have too many to-dos.');
183 | }
184 |
185 | return true;
186 | });
187 |
188 |
189 | ### Archiving Plans
190 |
191 | If you no longer wish to offer a given plan to your customers, you should not delete it entirely from your service provider. Instead use the `archived` method when defining the plan. This will prevent new customers from choosing the plan but will allow existing customers to continue using the plan:
192 |
193 | Spark::plan('Pro', 'yearly-pro')
194 | ->archived()
195 | ->price(100)
196 | ->yearly()
197 | ->features([
198 | 'Feature 1',
199 | 'Feature 2',
200 | 'Feature 3',
201 | ]);
202 |
203 |
204 | ## Charging Per Seat
205 |
206 | Spark's per-seat pricing makes it possible to charge your customers for each team, for each team member, or by any other custom metric you wish to charge by. For example, if you are building project management software, you may wish to charge your users per project.
207 |
208 | To get started, your application should typically have **two** subscription plans: a free plan and a plan that defines the price "per seat".
209 |
210 |
211 | ### Charging Users Per Team
212 |
213 | If your application uses teams, you may charge your users based on how many teams they manage. When a team is created or removed from a team, Spark will automatically update the subscription's "quantity" on Stripe. To configure this style of billing, the `boot` method of your `SparkServiceProvider` should look like the following:
214 |
215 | Spark::useStripe()->noCardUpFront()->trialDays(10);
216 |
217 | Spark::chargePerTeam();
218 |
219 | Spark::plan('Basic', 'monthly-basic')
220 | ->price(10)
221 | ->features([
222 | 'First', 'Second', 'Third'
223 | ]);
224 |
225 |
226 | ### Charging Teams Per Member
227 |
228 | If your application uses teams, you may charge your users based on how many users they add to a team. When a team member is added or removed from a team, Spark will automatically update the subscription's "quantity" on Stripe. To configure this style of billing, the `boot` method of your `SparkServiceProvider` should look like the following:
229 |
230 | Spark::useStripe()->noCardUpFront()->teamTrialDays(10);
231 |
232 | Spark::chargeTeamsPerMember();
233 |
234 | Spark::teamPlan('Basic', 'team-basic')
235 | ->price(10)
236 | ->features([
237 | 'First', 'Second', 'Third'
238 | ]);
239 |
240 |
241 | ### Custom Per Seat Targets
242 |
243 | Next, let's take a look at at charging per a custom target. In this example, let's assume you are building project management software and you would like to charge your customers per project. First, you should call the `chargePerSeat` method within the `boot` method of the `SparkServiceProvider`:
244 |
245 | Spark::chargePerSeat('Projects', function ($user) {
246 | return $user->projects()->count();
247 | });
248 |
249 | The `chargePerSeat` method accepts two arguments: the name of the item you are charging for and a Closure that calculates the total number of items attached to the user. If you would like to charge teams per seat, you may use the `chargeTeamsPerSeat` method:
250 |
251 | Spark::chargeTeamsPerSeat('Projects', function ($team) {
252 | return $team->projects()->count();
253 | });
254 |
255 | Next, you will need to call the `addSeat` / `removeSeat` methods from the relevant places in your application. So, for this example, you would call these methods when your users create or delete projects. The `addSeat` method will "increment" your subscription plan's quantity and the `removeSeat` method will "decrement" the subscription plan's quantity:
256 |
257 | $user->addSeat();
258 |
259 | $user->removeSeat();
260 |
261 | Alternatively, you may directly provide the number of "seats" the user's subscription currently has:
262 |
263 | $user->updateSeats(5);
264 |
265 | Of course, if your application is team based, you should call these methods on a team instance:
266 |
267 | $team->addSeat();
268 |
269 | $team->removeSeat();
270 |
271 | $team->updateSeats(5);
272 |
273 |
274 | ## Checking Subscription Status Via Middleware
275 |
276 | During installation, Spark automatically registers a `subscribed` middleware in your application's `app\Http\Kernel.php` file. This middleware may be used to restrict access to your application's routes based on the user's subscription status.
277 |
278 | To prevent a user from accessing a given route when they are not subscribed to your application, assign the `subscribed` middleware to the route. If the user is not subscribed, they will be redirected to the subscription settings page:
279 |
280 | Route::get('/paid', function () {
281 | //
282 | })->middleware('subscribed');
283 |
284 | If your application is using team billing, you may check if the current team is subscribed using the `teamSubscribed` middleware:
285 |
286 | Route::get('/paid', function () {
287 | //
288 | })->middleware('teamSubscribed');
289 |
290 |
291 | ## Site Wide Promotions
292 |
293 | If you would like to define a coupon that should be applied to every new registration for your application, you may use the Spark `promotion` method. This allows you to run promotional discounts for holidays or other special occasions. However, the promotional discount may only be applied during new registrations. You may call the `promotion` method from the `boot` method of your `SparkServiceProvider`:
294 |
295 | Spark::promotion('coupon-code');
296 |
297 |
298 | ## Currency Customization
299 |
300 | Laravel Cashier, which Spark uses to provide subscription billing, supports customizing your application's billing currency. The default Cashier currency is United States Dollars (USD). You can change the default currency by setting the `CASHIER_CURRENCY` environment variable.
301 |
302 | > **Note:** The specified currency must be supported by Stripe.
303 |
304 |
305 | ## Proration
306 |
307 | By default, Spark is configured to charge a prorated amount to the customer if a subscription was changed in the middle of a billing cycle. However, you can disable proration so that no changes are made to the subscription until the beginning of the next billing cycle. To disable proration, call the `noProrate` method in the `boot` method of your `SparkServiceProvider`:
308 |
309 | Spark::noProrate();
310 |
311 |
312 | ## Billing Events
313 |
314 | Spark fires several billing related Laravel events. Several of these events already have listeners assigned to them by default. You can view a list of these listeners in your `App\Providers\EventServiceProvider` class.
315 |
316 | **All events listed in the following table are relative to the `Laravel\Spark\Events` namespace:**
317 |
318 | Event | Description
319 | ------------- | -------------
320 | `PaymentMethod\BillingAddressUpdated` | The customer's billing address has been updated.
321 | `PaymentMethod\VatIdUpdated` | The customer's European VAT ID has been updated.
322 | `Subscription\SubscriptionCancelled` | A user's subscription was cancelled.
323 | `Subscription\SubscriptionUpdated` | A user's subscription was updated.
324 | `Subscription\UserSubscribed` | A user started a new subscription to the application.
325 |
326 | In addition to these user related subscription events, they are also events for team subscriptions. **All events listed in the following table are relative to the `Laravel\Spark\Events` namespace:**
327 |
328 | Event | Description
329 | ------------- | -------------
330 | `Teams\Subscription\SubscriptionCancelled` | A team's subscription has been cancelled.
331 | `Teams\Subscription\SubscriptionUpdated` | A team's subscription has been updated.
332 | `Teams\Subscription\TeamSubscribed` | A team has begun a new subscription.
333 |
--------------------------------------------------------------------------------
/client-customization.md:
--------------------------------------------------------------------------------
1 | # Client Customization Primer
2 |
3 | - [Introduction](#introduction)
4 | - [Views](#views)
5 | - [Adding Your Own Vue Components](#adding-your-own-vue-components)
6 | - [Customizing Existing Vue Components](#customizing-existing-vue-components)
7 | - [Using Something Other Than Vue](#other-than-vue)
8 |
9 |
10 | ## Introduction
11 |
12 | Spark makes it simple to modify the Spark view templates, supplement your own Vue components, and customize the existing Vue components. In this primer we'll cover all of these subjects to help you get started making Spark your own.
13 |
14 |
15 | ## Views
16 |
17 | When you create a new application using `spark new`, all of the Spark views are automatically exported to your application's `resources/views/vendor/spark` directory. You may customize any of these views as needed.
18 |
19 | When you upgrade your application using `php artisan spark:update`, any views that have been modified will not be updated. Instead, you will simply be notified that these views were skipped.
20 |
21 |
22 | ## Adding Your Own Vue Components
23 |
24 | When you install Spark, a `resources/js/components` directory is created to hold all of your own Vue components. To learn more about writing Vue components, be sure to check out the [Vue documentation](http://vuejs.org/guide/components.html). A sample `home` component is included with Spark and can serve as the main "dashboard" for your application. The corresponding view for this component is located at `resources/views/home.blade.php`.
25 |
26 | For an example of an application with custom Vue components, check out the Spark [demo application](/docs/11.0/quickstart#demo-application).
27 |
28 | > **Note:** When you add additional components to your application, don't forget to `require` them in your `resources/js/app.js` file.
29 |
30 |
31 | ## Customizing Existing Vue Components
32 |
33 | When Spark is installed, a `resources/js/spark-components` directory will be created which contains stubs for every Vue JavaScript component included with Spark. If you open one of these components, you will notice that each of them is an empty component definition except for the `base` mixin of the component which provides the Spark core functionality.
34 |
35 | Every component in this directory leverages Vue's [mixin](http://vuejs.org/guide/mixins.html) feature, meaning you can override any of the methods defined in the base Spark component.
36 |
37 | For example, if you wish to override the `update-contact-information` component's `update` method, you would define the following method in the `resources/js/spark-components/settings/profile/update-contact-information.js` file:
38 |
39 | var base = require('settings/profile/update-contact-information');
40 |
41 | Vue.component('spark-update-contact-information', {
42 | mixins: [base],
43 |
44 | methods: {
45 | update: function () {
46 | console.log('My Custom Method!');
47 | }
48 | }
49 | });
50 |
51 | Of course, once you customize a component, don't forget to run the `npm run dev` command to re-compile your JavaScript. Otherwise, your changes will not take effect.
52 |
53 |
54 | ## Using Something Other Than Vue
55 |
56 | Using Vue is required for the registration and settings views; however, you may use any JavaScript framework you want for the "bulk" for your application outside of these views.
57 |
58 | > **Note:** Vue is required for the following features: notifications, support requests, and automatic handling of [shared API back-ends](/docs/11.0/api#sharing-your-api).
59 |
60 | To use something other than Vue, modify your `resources/views/home.blade.php` view to extend the `spark::layouts.blade.app` template. This layout does not contain any JavaScript framework initialization and the Vue application will not be attached to the page, leaving you free to build your JavaScript client however you wish in your `resources/js/app.js` file. However, a few utility libraries such as Underscore, Moment, and jQuery are still loaded even when Vue is disabled for your application.
61 |
62 | Next, remove the following line from your `resources/js/components/bootstrap.js` file:
63 |
64 | require('./../spark-components/bootstrap');
65 |
66 | Finally, you may remove the Vue app instantiation from the `resources/js/app.js` file:
67 |
68 | var app = new Vue({
69 | mixins: [require('spark')]
70 | });
71 |
--------------------------------------------------------------------------------
/customization.md:
--------------------------------------------------------------------------------
1 | # Server Customization Primer
2 |
3 | - [Introduction](#introduction)
4 | - [Model Classes](#model-classes)
5 | - [Users](#users)
6 | - [Teams](#team)
7 | - [Views](#views)
8 |
9 | ## Introduction
10 |
11 | Spark allows you to customize certain aspects of the system to better suit your needs. For example, you may wish to tweak how the current user is retrieved from the database, or how two-factor authentication is implemented.
12 |
13 | When customizing the backend, you will typically use the `Spark::swap` method, which will allow you to swap out method implementations of various Spark core classes. Generally, you should rarely be required to extend a Spark class directly.
14 |
15 |
16 | ## Model Classes
17 |
18 | If you would like to customize the model names used by Spark from the `App` namespace to another custom namespace, you may use the `useUserModel` and `useTeamModel` methods in the `register` method of your `SparkServiceProvider`. You may need to define the `register` method if it does not already exist:
19 |
20 | Spark::useUserModel('Namespace\User');
21 |
22 | Spark::useTeamModel('Namespace\Team');
23 |
24 |
25 | ## Users
26 |
27 | #### Current User
28 |
29 | You may wish to customize how the current user is retrieved and sent to your front-end JavaScript application. For example, you may wish to load extra relationships on the `User` instance before it is returned. You may do so by swapping the `UserRepository@current` method within the `boot` method of your `SparkServiceProvider`:
30 |
31 | Spark::swap('UserRepository@current', function () {
32 | // Return the current user...
33 | });
34 |
35 | If you are using Vue, the currently authenticated user is available to your application's JavaScript via `Spark.state.user`.
36 |
37 |
38 | ## Teams
39 |
40 | #### Finding Individual Teams
41 |
42 | The `Laravel\Spark\Contracts\Repositories\TeamRepository` interface contains several methods you may wish to customize. To customize how individual teams are retrieved from the database, you may swap the `find` method within the `boot` method of your `SparkServiceProvider`:
43 |
44 | Spark::swap('TeamRepository@find', function ($id) {
45 | // Return the team with the given ID...
46 | });
47 |
48 | If you are using Vue, the currently authenticated user's current team is available to your application's JavaScript via `Spark.state.currentTeam`.
49 |
50 | #### Finding All Teams For A Given User
51 |
52 | To customize how all of the teams for a given user are retrieved, you may swap the `forUser` method of the `TeamRepository` within the `boot` method of your `SparkServiceProvider`:
53 |
54 | Spark::swap('TeamRepository@forUser', function ($user) {
55 | // Return all of the given user's teams...
56 | });
57 |
58 | If you are using Vue, All of the teams for the currently authenticated user are available to your application's JavaScript via `Spark.state.teams`.
59 |
60 |
61 | ## Views
62 |
63 | When you create a new application using `spark new`, all of the Spark views are automatically exported to your application's `resources/views/vendor/spark` directory. You may customize any of these views as needed.
64 |
65 | > **Note:** When you upgrade your application using `php artisan spark:update`, any views that have been modified will not be updated.
66 |
--------------------------------------------------------------------------------
/email-verification.md:
--------------------------------------------------------------------------------
1 | # Email Verification
2 |
3 | Beginning with Spark 7.1, you may use Laravel 5.7's email verification services out of the box. This will ensure Spark sends verification emails to newly registered users that contain a link to verify their ownership of the email address.
4 |
5 | To enable email verification, verify that your `App\User` model implements the `Illuminate\Contracts\Auth\MustVerifyEmail` contract.
6 |
7 | By default, Spark will not prevent newly registered users from accessing their account before they verify their email addresses. However, you can configure Spark to redirect unverified users to a prompt screen that informs them of the need to verify their email. To do this, add the following to the `register()` method of your SparkServiceProvider:
8 |
9 |
10 | Spark::ensureEmailIsVerified();
11 |
--------------------------------------------------------------------------------
/european-vat.md:
--------------------------------------------------------------------------------
1 | # European VAT
2 |
3 | - [Introduction](#introduction)
4 | - [Enabling European VAT Collection](#enabling-european-vat-collection)
5 | - [Customizing Tax Rate Calculation](#customizing-tax-rate-calculation)
6 |
7 |
8 | ## Introduction
9 |
10 | Businesses based in the European Union are required to collect tax based on the location of the customer. In addition, you are required to gather two proofs of the customer's location and use sequential invoice numbers. Spark handles all of these things for you, truly making it a breeze to get started building your next big idea even if you have to comply with obtuse European VAT rules.
11 |
12 | > **Note:** Laravel Spark is not a replacement for a good accountant and is not liable for any accounting mistakes or oversights. Laravel Spark does not guarantee 100% compliance with EU VAT regulations. We gave it our best shot.
13 |
14 |
15 | ## Enabling European VAT Collection
16 |
17 | > **Note:** European VAT collection is only supported when using the Stripe billing provider.
18 |
19 | Before enabling European VAT collection, you will need to install the `mpociot/vat-calculator` package via Composer:
20 |
21 | composer require mpociot/vat-calculator
22 |
23 | You can enable collection of European VAT by calling the `collectEuropeanVat` method from the `boot` method of your application's `SparkServiceProvider`. The `collectEuropeanVat` method accepts the home country of your business as its only argument:
24 |
25 | Spark::collectEuropeanVat('GB');
26 |
27 | Calling this method is all you need to do to enable European VAT collection. Your customers will automatically be prompted for their billing address on registration, and their billing address will be compared to their credit card's country of origin in order to gather two form of location proofs. The customer will not be able to register or subscribe if these two pieces of information do not match. Spark will also allow customers to supply a VAT ID if they are registering on behalf of a VAT registered company.
28 |
29 | When a customer updates their billing information or VAT ID in your application, Spark will automatically call Stripe to update the subscription with the new correct tax rate percentage, so you do not have to do this manually.
30 |
31 | For more information on customizing the currency used by your application, check out the [billing documentation](/docs/11.0/billing#currency-customization).
32 |
33 | > **Note:** You should be sure to configure a webhook in your Stripe control panel to point to the `webhook/stripe` URI of your application. Otherwise, invoice information will not be gathered for customer payments.
34 |
35 |
36 | ## Customizing Tax Rate Calculation
37 |
38 | By default, Spark uses the [mpociot/vat-calculator](https://github.com/mpociot/vat-calculator) package to calculate VAT rates, but you may use any service you wish by overriding the `taxPercentage` method of your `User` and `Team` models:
39 |
40 | public function taxPercentage()
41 | {
42 | return 20; // Customers should be charged 20% tax...
43 | }
44 |
45 | Within the `taxPercentage` method you may access the customer's billing address, VAT ID, and billing card country of origin:
46 |
47 | public function taxPercentage()
48 | {
49 | // $this->billing_country;
50 | // $this->card_country;
51 | // $this->vat_id;
52 | }
53 |
--------------------------------------------------------------------------------
/faq.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 |
3 | - [Which billing providers does Spark support?](#billing-providers)
4 | - [Which billing intervals does Spark support?](#billing-intervals)
5 | - [Does Spark support one-off charges?](#one-off)
6 | - [Does Spark support user and team subscriptions at the same time?](#user-and-team-billing)
7 | - [Does Spark support limiting the resources for a given plan?](#limiting-resources)
8 | - [Does Spark support collecting European VAT?](#vat)
9 | - [Can Spark be integrated into an existing application?](#existing)
10 | - [How do I transition from a Satis-based installation to a local installation?](#move-from-satis-to-path)
11 |
12 |
13 | ### Which billing providers does Spark support?
14 |
15 | Spark only supports Stripe.
16 |
17 |
18 | ### Which billing intervals does Spark support?
19 |
20 | Spark supports monthly and yearly billing plans, as well as one-off charges.
21 |
22 |
23 | ### Does Spark support one-off charges?
24 |
25 | Yes, Spark supports making one-off charges using [Cashier's `invoiceFor` method](https://laravel.com/docs/billing#single-charges).
26 |
27 |
28 | ### Does Spark support user and team subscriptions at the same time?
29 |
30 | Yes, you can have both user and team plans at the same time.
31 |
32 |
33 | ### Does Spark support limiting the resources for a given plan?
34 |
35 | Yes, you can limit [team plans](/docs/11.0/billing#configuring-team-billing-plans) by team members. You can also limit plans by [your own arbitrary conditions](/docs/11.0/billing#constraining-access-to-plans).
36 |
37 |
38 | ### Does Spark support collecting European VAT?
39 |
40 | Yes, Spark [supports collecting European VAT](/docs/11.0/european-vat).
41 |
42 |
43 | ### Can Spark be integrated into an existing application?
44 |
45 | Spark is not designed to be integrated into existing applications. Spark is designed for new applications.
46 |
47 |
48 | ### How do I transition from a Satis-based installation to a local installation?
49 |
50 | First, follow the [installation instructions](https://spark.laravel.com/docs/7.0/installation) for the "Spark Installer" package. Once the package has been installed, register your API token using the `register` command. If you do not have an API token, it can be generated from your Spark account dashboard on this website:
51 |
52 | spark register token-value
53 |
54 | Next, you should copy the Spark source directory from `vendor/laravel/spark` to `/spark` so that it resides in the root directory of your project. Once you have copied the files, you need to change the Spark dependency version in your `composer.json` file to `@dev`:
55 |
56 | "laravel/spark-aurelius": "@dev",
57 |
58 | Finally, update your `composer.json` file to use a `path` repository for Spark. Once this has been completed, run the `composer update` command:
59 |
60 | "repositories": [
61 | {
62 | "type": "path",
63 | "url": "./spark"
64 | }
65 | ],
66 |
--------------------------------------------------------------------------------
/forms.md:
--------------------------------------------------------------------------------
1 | # Forms
2 |
3 | - [Introduction](#introduction)
4 | - [Usage](#usage)
5 |
6 |
7 | ## Introduction
8 |
9 | Spark includes a helper class for working with forms and form errors in your JavaScript application. You are not required to use these helpers but may find them useful when building the forms for your application.
10 |
11 |
12 | ## Usage
13 |
14 | #### Defining A Form
15 |
16 | In your Vue component, you may define a form by instantiating a new instance of the `SparkForm` class. This would be defined in the `data` method of your component, which contains the entire data definition for your Vue component:
17 |
18 | Vue.component('example', {
19 | data() {
20 | return {
21 | form: new SparkForm({
22 | name: '',
23 | age: ''
24 | })
25 | };
26 | }
27 | });
28 |
29 | #### Submitting A Form
30 |
31 | The `SparkForm` class provides a few helpful properties such as `busy`, `successful`, and `errors` which let you inspect the state of the form. The `busy` property will be set automatically when the form is sent to the server using the `post`, `put`, or `delete` methods. This allows you to easily disable the "submit" button when the form is submitted:
32 |
33 |
36 |
37 | Then, you may submit the form from your Vue component:
38 |
39 | methods: {
40 | register() {
41 | Spark.post('/example', this.form)
42 | .then(response => {
43 | console.log(response);
44 | });
45 | }
46 | }
47 |
48 | #### Displaying Validation Errors
49 |
50 | You may use the `errors` property of the form to retrieve and display validation errors:
51 |
52 |
65 |
66 | #### Displaying Success Messages
67 |
68 | You may use the `successful` property to determine when to show a success message:
69 |
70 |
71 | Your contact information has been updated!
72 |
73 |
--------------------------------------------------------------------------------
/installation.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | - [Requirements](#requirements)
4 | - [Installation](#installation)
5 | - [Installation Via Composer](#installation-via-composer)
6 | - [Linking The Storage Directory](#linking-the-storage-directory)
7 | - [Installation Types](#installation-types)
8 |
9 |
10 | ## Requirements
11 |
12 | > If you need support for Laravel 10.x or higher, please upgrade to the [current generation of Spark](https://spark.laravel.com).
13 |
14 | Laravel Spark has a few requirements you should be aware of before installing:
15 |
16 | - Composer
17 | - Laravel Framework 9.0
18 | - Laravel Mix
19 | - Laravel Cashier
20 | - Laravel UI
21 | - Bootstrap 4 (SASS)
22 | - Node.js & NPM
23 |
24 | Before installing Spark, make sure you have the latest version of Node and NPM. You can download a graphical installer for Node on the [Node website](https://nodejs.org).
25 |
26 | The [Vue.js](http://vuejs.org) JavaScript framework is utilized on the registration and settings pages; however, you are free to build the "bulk" of your application using the JavaScript framework of your choice, or no JavaScript framework at all.
27 |
28 |
29 | ## Installation
30 |
31 |
32 | ### Installation Via Composer
33 |
34 | Spark provides a [Satis repository](https://spark-satis.laravel.com) which makes it simple to install Spark just like any other Composer package. First, make sure you have purchased a Spark license and [joined the Spark GitHub repository](/settings#/github).
35 |
36 | Create a new Laravel project using the [Laravel installer](https://laravel.com/docs/installation):
37 |
38 | laravel new project-name
39 |
40 | Next, add the following dependencies to your `composer.json` file's `require` section:
41 |
42 | "laravel/spark-aurelius": "~12.0",
43 | "laravel/ui": "^3.0",
44 |
45 | Next, run the `composer update` command. You may be prompted for a GitHub token in order to install the private Spark repository. Composer will provide a link where you can create this token. Once the dependencies are installed, add the following service providers to your `app.php` configuration file:
46 |
47 | Laravel\Spark\Providers\SparkServiceProvider::class,
48 | Laravel\Cashier\CashierServiceProvider::class,
49 |
50 | Next, run the `spark:install --force` command:
51 |
52 | php artisan spark:install --force
53 |
54 | Once Spark is installed, add the following provider to your `app.php` configuration file:
55 |
56 | App\Providers\SparkServiceProvider::class,
57 |
58 | Finally, you are ready to run the `npm install`, `npm run dev`, and `php artisan migrate` commands. Once these commands have completed, you are ready to enjoy Spark!
59 |
60 |
61 | ### Linking The Storage Directory
62 |
63 | Once Spark is installed, you should link the `public/storage` directory to your `storage/app/public` directory. Otherwise, user profile photos stored on the local disk will not be available:
64 |
65 | php artisan storage:link
66 |
67 |
68 | ## Installation Types
69 |
70 | The default `spark` command will generate a project that supports individual user plans. However, you may also create projects that use team billing.
71 |
72 | spark new project-name --team-billing
73 |
--------------------------------------------------------------------------------
/kiosk.md:
--------------------------------------------------------------------------------
1 | # Kiosk
2 |
3 | - [Introduction](#introduction)
4 | - [Configuration](#configuration)
5 | - [Included Components](#included-components)
6 | - [Metrics](#metrics)
7 | - [Customization](#customization)
8 |
9 |
10 | ## Introduction
11 |
12 | The Spark developer Kiosk is a special area of your Spark application that is only accessible to developers and provides unique, developer-only features such as [creating announcements](/docs/11.0/announcements), viewing application revenue, impersonating other users, and more.
13 |
14 | #### Developer Middleware
15 |
16 | Any routes that should only be accessible by developers may use the `dev` middleware. All of the default Kiosk routes included with Spark are automatically configured to use this middleware:
17 |
18 | Route::get('/dev', function () {
19 | //
20 | })->middleware('dev');
21 |
22 |
23 | ## Configuration
24 |
25 | The user accounts which have access to the Kiosk are defined in the `$developers` property of the `App\Providers\SparkServiceProvider` class. You should add the e-mail addresses of the accounts you wish to be considered as "developers" to this property.
26 |
27 | If you would like to dynamically set your developer list, you may use the `Spark::developers` method which accepts an array of developer e-mail addresses:
28 |
29 | Spark::developers($developers);
30 |
31 |
32 | ## Included Components
33 |
34 | Spark includes several Kiosk components out of the box. We'll review each of them and their purpose below.
35 |
36 | #### Announcements
37 |
38 | This component allows you to create announcements for your users. These announcements can be used to announce status updates, new features, links to blog posts, etc. Announcements are a great way to keep your users up to speed on what is going on with your application.
39 |
40 | #### Metrics
41 |
42 | This component displays a variety of performance / revenue metrics for your application, such as monthly recurring revenue, total revenue, new registrations, as well as the number of user subscriptions per plan. This component may be used to get a basic overview of the growth of your application.
43 |
44 | #### User Search / Profile
45 |
46 | This component allows you to search for users by name or e-mail address. The `*` character may be used when searching to represent a wildcard. For example, searching for `matt*` will return all users with a name that begins with `matt`.
47 |
48 | You may click the view / magnifying glass icon on a user search result to view that user's profile, which includes a button to impersonate that user, as well as the total revenue generated by that customer.
49 |
50 |
51 | ## Metrics
52 |
53 | To capture nightly revenue metrics for your application, make sure to schedule the `spark:kpi` Artisan command to run nightly in your application's `app/Console/Kernel.php` file. Of course, you'll also need to schedule a "Cron" job to run the `schedule:run` Artisan command every minute. For more information on scheduled commands, check out the [relevant Laravel documentation](https://laravel.com/docs/scheduling):
54 |
55 | $schedule->command('spark:kpi')->dailyAt('23:55');
56 |
57 |
58 | ## Customization
59 |
60 | Adding your own panels to the Kiosk is a breeze. To get started, customize the `resources/views/vendor/spark/kiosk.blade.php` view to include an additional tab link and tab panel. You are free to check out the included views as an example of how to write your own Kiosk components. However, you are not required to make your Kiosk panel a Vue component.
61 |
--------------------------------------------------------------------------------
/localization.md:
--------------------------------------------------------------------------------
1 | # Localization
2 |
3 | - [Translating Strings](#translating-strings)
4 | - [Translating The Terms Of Service](#translating-terms-of-service)
5 | - [Right-To-Left Theme](#right-to-left-theme)
6 |
7 |
8 | ## Translating Strings
9 |
10 | Spark utilizes the powerful [translation component shipped with Laravel](https://laravel.com/docs/localization). By default, Spark is shipped with an English interface and a left-to-right theme.
11 |
12 | You may easily support another language in your application by copying the `resources/lang/en.json` file into a new file named after the language you prefer (such as `sp.json`). You'll also need to copy the `resources/lang/en/teams.php` file, which contains team-related string translations, into a translation folder corresponding to your desired language (such as `resources/lang/sp/teams.php`).
13 |
14 |
15 | ## Translating The Terms Of Service
16 |
17 | To translate your application's "Terms of Service" file, you should create a `terms.[lang].md` file and provide your translated content. For example, if you wish to support the Spanish language, you should create a `terms.sp.md` file. Spark will display the content of this file based on the application's configured language.
18 |
19 | If a file with the requested language is not found, Spark will use the default `terms.md` file.
20 |
21 |
22 | ## Right-To-Left Theme
23 |
24 | If you would like your application to use a "right-to-left" theme, you should call the `useRightToLeftTheme` method in the `boot` method of your `SparkServiceProvider`:
25 |
26 | Spark::useRightToLeftTheme();
27 |
28 | You may further customize how the right-to-left theme appears by modifying the `resources/assets/sass/app-rtl.scss` file and re-compiling your assets using `npm run dev` in your terminal.
29 |
--------------------------------------------------------------------------------
/notifications.md:
--------------------------------------------------------------------------------
1 | # Notifications
2 |
3 | - [Introduction](#introduction)
4 | - [Creating Notifications](#creating-notifications)
5 | - [Sending Laravel Notifications](#sending-laravel-notifications)
6 |
7 |
8 | ## Introduction
9 |
10 | Notifications are a great way to inform your users of things that are happening in your application. For example, you might use a notification to let a user know when a team member has completed a given to-do list task. These notifications are viewable by clicking on the "notification bell" icon in the application's navigation bar. The notification bell will have an unread count indicator when there are unread announcements or notifications.
11 |
12 |
13 | ## Creating Notifications
14 |
15 | To create a notification, inject the `Laravel\Spark\Contracts\Repositories\NotificationRepository` into your controller or any other class which is being resolved by the Laravel service container:
16 |
17 | use Laravel\Spark\Contracts\Repositories\NotificationRepository;
18 |
19 | public function __construct(NotificationRepository $notifications)
20 | {
21 | $this->notifications = $notifications;
22 | }
23 |
24 | Then, you may use the `create` method to create the notification:
25 |
26 | $this->notifications->create($user, [
27 | 'icon' => 'fa-users',
28 | 'body' => 'A team member completed a task!',
29 | 'action_text' => 'View Task',
30 | 'action_url' => '/link/to/task',
31 | ]);
32 |
33 | The `action_text` and `action_url` attributes are optional so you do not need to pass them in order to create a notification. However, providing these attributes will create a button on the notification where the user can be directed to some other location for information relevant to the notification.
34 |
35 | When a notification is created, Spark will fire the `Laravel\Spark\Events\NotificationCreated` event, which your application can listen for to do work after a notification is created.
36 |
37 |
38 | ## Sending Laravel Notifications
39 |
40 | > **Note:** Before using this feature, check out the [Laravel notification documentation](https://laravel.com/docs/notifications).
41 |
42 | Spark also allows you to send notifications using the Laravel \notification system. To create a notification, you may use the following Artisan command:
43 |
44 | ```
45 | php artisan make:notification TaskCompleted
46 | ```
47 |
48 | This command will place a fresh notification in your `app/Notifications` directory. You may add the notification to Spark's notification table by specifying the `SparkChannel` channel in your notification's `via` method. The `SparkChannel` may be thought of as a replacement to Laravel's default `database` channel:
49 |
50 | ```php
51 | use Laravel\Spark\Notifications\SparkChannel;
52 |
53 | public function via($notifiable)
54 | {
55 | return [SparkChannel::class];
56 | }
57 | ```
58 |
59 | ### Formatting Notifications
60 |
61 | Before using the `SparkChannel`, you should define a `toSpark` method on the notification class. This method will receive a `$notifiable` entity and should return a SparkNotification object:
62 |
63 | ```php
64 | use Laravel\Spark\Notifications\SparkNotification;
65 |
66 | public function toSpark($notifiable)
67 | {
68 | return (new SparkNotification)
69 | ->action('View Task', '/link/to/task')
70 | ->icon('fa-users')
71 | ->body('A team member completed a task!');
72 | }
73 | ```
74 |
75 | ### Sending Notifications
76 |
77 | Notifications may be sent in two ways: using the `notify` method of the `Notifiable` trait or by using the `Notification` facade. You may take a look at the Laravel [notification documentation](https://laravel.com/docs/notifications#sending-notifications) to get more details regarding these two approaches to sending notifications.
78 |
79 | Here's an example of sending notifications to a Spark user using the `notify` method:
80 |
81 | ```php
82 | $user->notify(new TaskCompleted);
83 | ```
84 |
85 | When sending a notification to a team, all members of that team will be notified:
86 |
87 | ```php
88 | $team->notify(new TaskCompleted);
89 | ```
90 |
--------------------------------------------------------------------------------
/quickstart.md:
--------------------------------------------------------------------------------
1 | # Quickstart
2 |
3 | - [Introduction](#introduction)
4 | - [Installing Spark](#installing-spark)
5 | - [Configuring Billing Plans](#configuring-billing-plans)
6 | - [Building Your Application](#building-your-application)
7 |
8 |
9 |
10 | ## Introduction
11 |
12 | Spark provides all of the scaffolding you need to get started developing your next big idea. Authentication, API tokens and authentication, subscription billing, payment method updates, invoicing, password reset, and more is included out of the box.
13 |
14 | In this guide, we'll walk through installing Spark and writing the first view for your application.
15 |
16 |
17 | ## Installing Spark
18 |
19 | To install Spark, follow the instructions in the [installation guide](/docs/11.0/installation).
20 |
21 | #### Post Installation Setup
22 |
23 | Once Spark is installed, make sure the NPM dependencies have been installed via the `npm install` command, the `npm run dev` command has been executed, and the database migrations have run. You should also configure your e-mail address as a "developer" so that you have access to the [Kiosk](/docs/11.0/kiosk). To do this, add your e-mail address to the `$developers` property in the `App\Providers\SparkServiceProvider`.
24 |
25 |
26 | ## Configuring Billing Plans
27 |
28 | Once your Spark project has been created, take a look at the `App\Providers\SparkServiceProvider` class. The `boot` method of this class is used to define your application's subscription plans. By default, one free plan and one paid plan is defined. You should change the ID of the paid plan from `provider-id-1` to match the ID of one of your plans that is actually defined in Stripe.
29 |
30 | > **Note:** Spark does not automatically define plans within Stripe. You must define those manually on the provider of your choice.
31 |
32 | By default, Spark is configured to require no credit-card up front and to grant new users a free trial period of 10 days. This configuration should work perfectly for the majority of applications. For more information on configuring billing plans, check out the [billing documentation](/docs/11.0/billing).
33 |
34 |
35 | ## Building Your Application
36 |
37 | Once Spark has been installed and your billing plans are configured, you're ready to start building your application. By default, Spark installs a `/home` route in your `routes/web.php` file which displays the `home` Blade template. You are free to edit the `home.blade.php` template as needed to build your application.
38 |
39 | The `home.blade.php` file also represents the `home` [Vue component](https://vuejs.org), which is defined at `resources/assets/js/components/home.js`. You may add your own JavaScript code to this component as needed. Of course, if you change this code, don't forget to run `npm run dev` to re-compile your application's JavaScript.
40 |
41 | Of course, at this point, you may simply build your Laravel application however you wish. Spark has already installed scaffolding for all of the subscription management, authentication, and other settings views. Now it's time for you to build your dream!
42 |
43 | ### Read The Documentation
44 |
45 | For more information on using Spark, check out the rest of this documentation, which includes information on [back-end customization](/docs/11.0/customization) and [front-end customization](/docs/11.0/client-customization), as well as documentation pages covering many other areas of Spark. **It's very important that you read through this documentation in its entirety.**
46 |
--------------------------------------------------------------------------------
/releases.md:
--------------------------------------------------------------------------------
1 | # Release Notes
2 |
3 | - [Support Policy](#support-policy)
4 | - [Releases](#releases)
5 | - [11.0.0](#11.0.0)
6 | - [10.0.0](#10.0.0)
7 | - [9.0.0](#9.0.0)
8 | - [8.0.0](#8.0.0)
9 | - [7.0.0](#7.0.0)
10 | - [6.0.0](#6.0.0)
11 | - [5.0.0](#5.0.0)
12 | - [4.0.0](#4.0.0)
13 | - [3.0.0](#3.0.0)
14 | - [2.0.0](#2.0.0)
15 | - [1.0.0](#1.0.0)
16 |
17 |
18 | ## Support Policy
19 |
20 | Only the latest major Spark release is maintained and will receive bug and security fixes for one year.
21 |
22 | | Version | Release |
23 | | --- | --- |
24 | | 6.0 | February 6th, 2018 |
25 | | 7.0 | September 6th, 2018 |
26 | | 8.0 | February 26th, 2019 |
27 | | 9.0 | September 4th, 2019 |
28 | | 10.0 | May 19th, 2020 |
29 | | 11.0 | September 8th, 2020 |
30 |
31 |
32 | ## Releases
33 |
34 |
35 | ## 11.0.0
36 |
37 | The 11.0 release of Spark provides Laravel 8.x and Cashier 12.0 compatibility.
38 |
39 |
40 | ## 10.0.0
41 |
42 | The 10.0 release of Spark provides Cashier 11.0 compatibility.
43 |
44 |
45 | ## 9.0.0
46 |
47 | The 9.0 release of Spark provides Laravel 6.x / 7.x and Cashier 10.0 compatibility. In addition, Spark 9.0 switched to Laravel Mix 4.0 and SweetAlert2.
48 |
49 | Starting Spark 9.0, support for the Braintree provider was dropped.
50 |
51 |
52 | ## 8.0.0
53 |
54 | The 8.0 release of Spark provides Laravel 5.8 compatibility.
55 |
56 | Spark 8.0 is a simple maintenance release to provide compatibility with Laravel 5.8 and Cashier 9.0. As such, there are no Spark specific upgrade instructions. You should simply upgrade your application using the [Laravel 5.8 upgrade guide](https://laravel.com/docs/5.8/upgrade). In addition, ensure that your application's `composer.json` file is requiring Laravel Cashier `^9.0`.
57 |
58 |
59 | ### 7.0.0
60 |
61 | The 7.0 release of Spark provides Laravel 5.7 compatibility.
62 |
63 |
64 | ### 6.0.0
65 |
66 | The 6.0 release of Spark provides Laravel 5.6 compatibility. In addition, Spark 6.0 introduces Bootstrap 4, localization, per-seat pricing, Stripe Elements, and UI enhancements.
67 |
68 |
69 | ### 4.0.0
70 |
71 | The 4.0 release of Spark upgraded the front-end HTTP library to Axios. In addition, new Spark 4.0 applications are configured to use [Laravel Mix](https://laravel.com/docs/mix) and Webpack instead of Laravel Elixir. To learn more about upgrading your application to Spark 4.0, please consult the [upgrade guide](/docs/4.0/upgrade).
72 |
73 |
74 | ### 3.0.0
75 |
76 | The 3.0 release of Spark upgraded the front-end Vue.js dependencies to Vue 2.0. To learn more about upgrading your application to Spark 3.0, please consult the [upgrade guide](/docs/3.0/upgrade).
77 |
78 |
79 | ### 2.0.0
80 |
81 | The 2.0 release of Spark provides compatibility with Laravel 5.3.
82 |
83 | For the 2.0 release, the Spark installer has been deprecated in favor of simply [installing Spark via Composer](/docs/3.0/installation).
84 |
85 |
86 | ### 1.0.0
87 |
88 | The initial release of Laravel Spark. Spark provides instant scaffolding for subscription billing applications including authentication, password reset, billing plans, payment method updates, invoices, coupons, user impersonation, and more with support for Stripe and Braintree.
89 |
--------------------------------------------------------------------------------
/support.md:
--------------------------------------------------------------------------------
1 | # Support Requests
2 |
3 | - [Introduction](#introduction)
4 | - [Customization](#customization)
5 |
6 |
7 | ## Introduction
8 |
9 | > **Note:** This feature is not supported if you do not use Vue as your application's JavaScript framework.
10 |
11 | Spark includes a simple way for your customers to contact you with support requests. After installing Spark and registering a new account, the "Email Us" link will be available from the user's account drop-down menu.
12 |
13 | To specify where these e-mails should be sent, you should set the `$sendSupportEmailsTo` property on your `SparkServiceProvider` class. Don't forget to also configure your mail settings in Laravel's `config/mail.php` configuration file:
14 |
15 | /**
16 | * The address where customer support e-mails should be sent.
17 | *
18 | * @var string
19 | */
20 | protected $sendSupportEmailsTo = 'support@your-application.com';
21 |
22 |
23 | ## Customization
24 |
25 | If you would like to have more control over how support requests are delivered to your development team, you may swap the `handle` method of the `SendSupportEmail` interaction with your own custom implementation. This will allow you to deliver support requests to the help desk of your choice using a third party API, etc.
26 |
27 | To get started, use the `Spark::swap` method within the `boot` method of your `SparkServiceProvider`:
28 |
29 | Spark::swap('SendSupportEmail@handle', function (array $data) {
30 | // $data['from']
31 | // $data['subject']
32 | // $data['message'],
33 | });
34 |
--------------------------------------------------------------------------------
/teams.md:
--------------------------------------------------------------------------------
1 | # Teams
2 |
3 | - [Introduction](#introduction)
4 | - [Changing How Spark Refers To Teams](#changing-how-spark-refers-to-teams)
5 | - [Accessing The User's Teams](#accessing-the-users-teams)
6 | - [Accessing Teams By Path](#accessing-teams-by-path)
7 | - [Team Roles](#team-roles)
8 | - [Team Billing](#team-billing)
9 | - [Using Teams Without Team Billing](#using-teams-without-team-billing)
10 | - [Team Events](#team-events)
11 |
12 |
13 | ## Introduction
14 |
15 | Spark includes support for allowing your users to create and join teams. Teams provide a great way for users to share access to resources with other users of your application. Once a team has been created, users may invite other users to their team as well assign them roles.
16 |
17 | To use teams, initialize your Spark project using the `--team-billing` flag:
18 |
19 | spark new project-name --team-billing
20 |
21 | If you installed your application without the `--team-billing` flag but still want to enable teams later, you may simply add the `Laravel\Spark\CanJoinTeams` trait to your `User` model. In addition, you may wish to review the documentation on [team billing](/docs/11.0/billing#configuring-team-billing-plans):
22 |
23 |
40 | ### Changing How Spark Refers To Teams
41 |
42 | By default, Spark uses the "/teams/" segment in URIs to refer to teams. However, you may customize this using the `prefixTeamsAs` method in the `register` method of your `SparkServiceProvider`:
43 |
44 | Spark::prefixTeamsAs('bands');
45 |
46 | > Be sure to call this method in the `register` method of your service provider, as Spark will not function correctly if it is called in the `boot` method. Additionally, make sure you pass the plural, lowercase form of the word.
47 |
48 | To change the word used to refer to "teams" in views, you should update the `resources/lang/en/teams.php` [language file](/docs/11.0/localization).
49 |
50 |
51 | ## Accessing The User's Teams
52 |
53 | The `CanJoinTeams` trait provides several methods to assist you in accessing a given user's teams. The trait defines a `teams` relation to the `App\Team` model allows you to iterate over all of the user's teams:
54 |
55 | foreach ($user->teams as $team) {
56 | echo $team->name;
57 | }
58 |
59 | The trait also provides several other helper methods that are useful when developing team based applications:
60 |
61 | if ($user->hasTeams()) {
62 | // This user belongs to at least one team...
63 | }
64 |
65 | if ($user->onTeam($team)) {
66 | // The user belongs to the given team...
67 | }
68 |
69 | if ($user->ownsTeam($team)) {
70 | // The user owns the given team...
71 | }
72 |
73 | foreach ($user->ownedTeams as $team) {
74 | // Iterate through all of the user's owned teams...
75 | }
76 |
77 | foreach ($team->invitations as $invitation) {
78 | // Iterate through all active invitations for the team...
79 | }
80 |
81 | ### The Current Team
82 |
83 | When building team based applications in Spark, users will almost always belong to a "current team". This is the team that is currently selected from the team selection list from the user profile drop-down menu at the top right of the screen.
84 |
85 | The team listing allows users to switch between team contexts in your application. So, for example, if you are building a helpdesk application, switching teams allows users to switch between team inboxes.
86 |
87 | You may access the user's "current team" using the `currentTeam` property on a `App\User` instance:
88 |
89 | echo $user->currentTeam->name;
90 |
91 | If the user does not belong to any team, the `currentTeam` property will be `null`, so you may wish to check that the property is not null before accessing it:
92 |
93 | if ($user->currentTeam) {
94 | //
95 | }
96 |
97 | However, by default, when a user does not belong to any teams, they will be redirected to a warning notice informing them that they should create a team to continue using the application. To view this notice, simply register a test user, delete all of their teams, and then attempt to access the application `/home` URI. This redirection is provided by the `VerifyUserHasTeam` middleware.
98 |
99 |
100 | ## Accessing Teams By Path
101 |
102 | Spark also supports disabling the "team switcher" located in the top-right navigation menu and allowing you to have full customization of determining which team a user is currently viewing. To enable this option, call the `Spark::identifyTeamsByPath()` option in the `boot` method of your `SparkServiceProvider`:
103 |
104 | Spark::identifyTeamsByPath();
105 |
106 | Once this option has been enabled, the team creation screen will include a new field where the user may choose a team "slug" that can be used in your application's route URIs to identify the team resources the user wishes to view. The team slug must be unique across your entire application for each team. Validation rules to ensure this uniqueness are already included in Spark. Once this option has been enabled you might define application routes like so in order to determine which team a user wishes to view:
107 |
108 | Route::get('/{team_slug}/projects', 'ProjectController@index');
109 |
110 |
111 | ## Team Roles
112 |
113 | Spark allows you to define roles for your team's members. By default, Spark has two roles: `owner` and `member`. However, you may define additional roles which the owner of a team can then assign to users from the team membership screen.
114 |
115 | To define roles, call the `useRoles` method from the `boot` method of your `SparkServiceProvider`. The `useRoles` method accepts an array where the keys are the role "slugs" that will be stored in the database, while the values are the displayable name of the role:
116 |
117 | Spark::useRoles([
118 | 'member' => 'Member',
119 | 'vip' => 'VIP',
120 | ]);
121 |
122 | If you would like to get the role that a user has for a given team, you may use the `roleOn` method on a user instance:
123 |
124 | if ($user->roleOn($team) === 'vip') {
125 | // This user is a VIP...
126 | }
127 |
128 | You may also use the `ownsTeam` method to determine if a user owns a given team:
129 |
130 | if ($user->ownsTeam($team)) {
131 | // This user owns the team...
132 | }
133 |
134 | The `ownedTeams` method returns all of the user's owned teams:
135 |
136 | foreach ($user->ownedTeams as $team) {
137 | echo $team->name;
138 | }
139 |
140 |
141 | ## Team Billing
142 |
143 | Team billing allows your Spark applications to provide billing plans on a per-team basis, meaning users may subscribe to different billing plans for each team they own. For more information on configuring team billing, please refer to the [billing documentation](/docs/11.0/billing#configuring-team-billing-plans)
144 |
145 |
146 | ## Using Teams Without Team Billing
147 |
148 | If you would like to offer teams in your application but do not want to use team billing, Spark makes it a breeze. First, use the `Laravel\Spark\CanJoinTeams` trait on your `User` model:
149 |
150 | price(100)
166 | ->yearly()
167 | ->maxTeams(5);
168 |
169 |
170 | ## Team Events
171 |
172 | Spark fires several team related events. These may be used to perform various actions when a user joins or leaves a team, such as incrementing the subscription "quantity" if you are using Stripe to implement "per-user" pricing.
173 |
174 | **All events listed in the following table are relative to the `Laravel\Spark\Events` namespace:**
175 |
176 | Event | Description
177 | ------------- | -------------
178 | `Teams\DeletingTeam` | A team is about to be deleted. You may use this to remove all of the team's data.
179 | `Teams\TeamCreated` | A team has been created.
180 | `Teams\TeamDeleted` | A team has been deleted.
181 | `Teams\TeamMemberAdded` | A new user has joined a team.
182 | `Teams\TeamMemberRemoved` | A user has left or been removed from a team.
183 | `Teams\UserInvitedToTeam` | A user has been invited to join a team.
184 | `Teams\Subscription\SubscriptionCancelled` | A team's subscription has been cancelled.
185 | `Teams\Subscription\SubscriptionUpdated` | A team's subscription has been updated.
186 | `Teams\Subscription\TeamSubscribed` | A team has begun a new subscription.
187 |
--------------------------------------------------------------------------------
/two-factor.md:
--------------------------------------------------------------------------------
1 | # Two-Factor Authentication
2 |
3 | - [Introduction](#introduction)
4 | - [Usage](#usage)
5 | - [Customization](#customization)
6 |
7 |
8 | ## Introduction
9 |
10 | Spark makes it simple to offer two-factor authentication to your users. Two-factor authentication provides your users additional account security by requiring them to provide a token during login in addition to their username and password. This token is generally retrieved from an application or SMS on their cellphone.
11 |
12 | By default, Spark uses [Authy](https://authy.com) as the two-factor authentication provider. However, you are free to implement your own two-factor authentication provider if you wish.
13 |
14 | Before enabling two-factor authentication, you should populate the `AUTHY_SECRET` environment variable in your application's `.env` file with the value of your Authy API token.
15 |
16 |
17 | ## Usage
18 |
19 | After configuring your `AUTHY_SECRET` environment variable, you should call the `useTwoFactorAuth` method from the `boot` method of your `SparkServiceProvider`:
20 |
21 | Spark::useTwoFactorAuth();
22 |
23 | Calling this method will add the proper two-factor authentication views to the "Security" tab of your user's account profiles. From these views, your users may configure, enable, and disable two-factor authentication for their account.
24 |
25 | When two-factor authentication is initially enabled on an account, an emergency login token will be displayed to the user which they should store in a secure password manager. This token may be used to log into the application in the event that the user loses their phone.
26 |
27 |
28 | ## Customization
29 |
30 | If you would like to implement your own two-factor authentication provider, you may do so by "swapping" the two-factor interactions using the `Spark::swap` method. You will need to swap the following interactions: `EnableTwoFactorAuth`, `DisableTwoFactorAuth`, and `VerifyTwoFactorAuthToken`. You may add these customizations in the `boot` method of your `SparkServiceProvider`:
31 |
32 | Spark::swap('EnableTwoFactorAuth', function ($user, $country, $phone) {
33 | //
34 | });
35 |
36 | Spark::swap('DisableTwoFactorAuth', function ($user) {
37 | //
38 | });
39 |
40 | Spark::swap('VerifyTwoFactorAuthToken', function ($user, $token) {
41 | //
42 | });
43 |
44 | You may also swap the interactions with a class and method rather than a Closure:
45 |
46 | Spark::swap('EnableTwoFactorAuth@handle', 'EnableTwoFactorAuthUsingGoogle@handle');
47 |
48 | Within these methods, you do not need to worry about persisting the country code and phone number to your database. This will be handled automatically by Spark. Your customized provider methods only need to enable / disable two-factor authentication with the third-party provider of your choice.
49 |
50 | For an example of a provider implementation, check out the following classes that are included with Spark:
51 |
52 | - `EnableTwoFactorAuthUsingAuthy`
53 | - `DisableTwoFactorAuthUsingAuthy`
54 | - `VerifyTwoFactorAuthTokenUsingAuthy`
55 |
--------------------------------------------------------------------------------
/upgrade.md:
--------------------------------------------------------------------------------
1 | # Upgrade Guide
2 |
3 | - [Upgrading To Spark 11.0](#upgrade-spark-11.0)
4 | - [Upgrading To Spark 12.0](#upgrade-spark-12.0)
5 |
6 |
7 | ## Upgrading To Spark 12.0
8 |
9 | Spark 12.0 provides compatibility with Cashier 13.
10 |
11 | ### Upgrading Via Spark CLI
12 |
13 | If you installed Spark via the `spark` CLI tool, you may run the `spark:update` Artisan command:
14 |
15 | php artisan spark:update --major
16 |
17 | ### Upgrading Via Composer
18 |
19 | If you installed Spark via Composer, you may simply update your dependency version in your `composer.json` file and run the `composer update` command. Of course, in order for your GitHub user to access the repository, you should first join this repository in the Spark dashboard:
20 |
21 | "laravel/spark-aurelius": "~12.0"
22 |
23 | ### Adding a tax_rates Table
24 |
25 | Add the following migration in your project and then run `php artisan migrate`:
26 |
27 | class CreateTaxRatesTable extends Migration
28 | {
29 | public function up()
30 | {
31 | Schema::create('tax_rates', function (Blueprint $table) {
32 | $table->id();
33 | $table->string('stripe_id')->index();
34 | $table->double('percentage')->index();
35 | $table->timestamps();
36 | });
37 | }
38 |
39 | public function down()
40 | {
41 | Schema::dropIfExists('tax_rates');
42 | }
43 | }
44 |
45 |
46 |
47 | ### Cashier Upgrade Guide
48 |
49 | After updating your Spark application, please review and make the necessary changes for Cashier 13.0 based on the [Cashier upgrade guide](https://github.com/laravel/cashier/blob/13.x/UPGRADE.md).
50 |
51 |
52 | ## Upgrading To Spark 11.0
53 |
54 | Spark 11.0 provides compatibility with Laravel 8 and Cashier 12.
55 |
56 | ### Upgrading Via Spark CLI
57 |
58 | If you installed Spark via the `spark` CLI tool, you may run the `spark:update` Artisan command:
59 |
60 | php artisan spark:update --major
61 |
62 | ### Upgrading Via Composer
63 |
64 | If you installed Spark via Composer, you may simply update your dependency version in your `composer.json` file and run the `composer update` command. Of course, in order for your GitHub user to access the repository, you should first join this repository in the Spark dashboard:
65 |
66 | "laravel/spark-aurelius": "~11.0"
67 |
68 | ### Updating Your SparkServiceProvider
69 |
70 | Rename the `booted()` method of the `SparkServiceProvider` to `boot()` and call `parent::boot()`.
71 |
72 | public function boot()
73 | {
74 | parent::boot();
75 |
76 | Spark::noCardUpFront()->trialDays(10);
77 |
78 | Spark::freePlan()
79 | ->features([
80 | 'First', 'Second', 'Third'
81 | ]);
82 |
83 | Spark::plan('Basic', 'provider-id-1')
84 | ->price(10)
85 | ->features([
86 | 'First', 'Second', 'Third'
87 | ]);
88 | }
89 |
90 | Next, if you would like to keep your model classes in the `App` namespace, you may use the `useUserModel` and `useTeamModel` methods in the `register` method of your `SparkServiceProvider`:
91 |
92 | Spark::useUserModel('App\User');
93 |
94 | Spark::useTeamModel('App\Team');
95 |
96 | ### Cashier Upgrade Guide
97 |
98 | After updating your Spark application, please review and make the necessary changes for Cashier 12.0 based on the [Cashier upgrade guide](https://github.com/laravel/cashier/blob/12.x/UPGRADE.md).
99 |
100 |
101 |
--------------------------------------------------------------------------------