Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Smef committed May 14, 2022
0 parents commit 018247b
Show file tree
Hide file tree
Showing 16 changed files with 787 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.idea
/vendor
composer.lock
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 Blue Feather Group, LLC.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
118 changes: 118 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Jetstream-FileMaker
## Introduction
[Laravel Jetstream](https://jetstream.laravel.com/2.x/introduction.html) is a great starting point for building web applications. Laravel and Elqouent-FileMaker make it easy to store and retrieve data from a FileMaker database through the FileMaker Data API and then integrate that data into a Laravel/Jetstream app. The default behavior for Jetstream, however, is to use a SQL database such as MySQL or SQLite. It's not normally possible to exclusively use a FileMaker database for everything with Jetstream.

This package is designed to allow you to exclusively use a FileMaker database and the FileMaker Data API as your data source for a Jetstream application. With this package, you no longer need to have a primary SQL database and then use FileMaker for additional data. FileMaker can be the sole database used by your Jetstream app.

## Support

This package is built and maintained by [Blue Feather](https://www.bluefeathergroup.com/). We build fantastic web apps with technologies like Laravel, Vue, React, and Node. If you would like assistance building your own web app, either using this package or other technologies, please [contact us](https://www.bluefeathergroup.com/contact/) for a free introductory consultation to discuss your project.

## Prepare your FileMaker database

### Quickstart with an example FileMaker database
If you just want to see an example of Jetstream working with FileMaker you can unzip and use the `Jetstream-FileMaker.fmp12` file included in the `dist` folder as an example data source. This file has been configured with the minimum necessary fields to work with Jetstream and already has layouts ready for accessing through the Data API. You can host this file on your FileMaker Server and use it as a testing ground to see Laravel Jetstream running using a FileMaker database as a data source.

Otherwise, read the directions below for how to configure your existing FileMaker database to work with Jetstream. The example file is a great reference for configuring your own database.

A Data API user is preconfigured with the username `jetstream` and the password also set to `jetstream`. You can set these credentials in your `.env` to configure your app for access to this sample file.

### Prepare tables and fields
Laravel Jetstream requires certain tables and fields to function. Normally this would be a SQL database and the tables and fields would be created through migrations, but we're going to be using FileMaker as a data source instead. Your FileMaker database will need to be configured to have the minimum required tables to be able to work with Jetstream.

You will need the following tables:
* User
* PasswordReset
* PersonalAccessToken

These tables must also have the minimum required fields to support the features of the Jetstream starter kit. The required tables and fields for your FileMaker database can be found in the `Jetstream-FileMaker.fmp12` file included in the `dist` folder of this package. You can either copy these tables/fields to your database, rename your existing fields, or use the [Eloquent-FileMaker field mapping feature](https://github.com/BlueFeatherGroup/eloquent-filemaker) to map your existing fields to these expected field names.

### Set up layouts for Data API access
The The FileMaker Data API allows access to your tables through layouts in your FileMaker database. Only fields which are on the layouts accessed through the Data API are visible. This means that you MUST include all the fields you want to access through the data API on your layouts.

As a starting point, we recommend creating one layout per table with the minimum number of fields you need one each of the layouts for each of the tables. Again, the example `Jetstream-FileMaker.fmp12` is a great reference for setting up some basic access.

We recommend prefixing layout names you plan on using with the data API so that you can make sure that they're both simple and unique. The example file uses `web_` as a layout name prefix to make sure layout names don't conflict with other common layout names.

By default, Laravel looks for pluralized versions of each of the tables. If you are also using a layout name prefix your layout names, your layout names would need to be:
* `web_users`
* `web_passwordresets`
* `web_personalaccesstokens`

The example `Jetstream-FileMaker.fmp12` file has these prepared as a demonstration, so you can always look at that for reference.

If you don't want to use the pluralized table names Laravel will be searching for by default, the layout names used for the models can also be configured in each model file by setting the table name directly using the `$table` property. Do not include any configured table prefix, such as `web_` when setting table/layout names. You can refer to the [Laravel](https://laravel.com/docs/9.x/eloquent#table-names) and [Eloquent-FileMaker](https://github.com/BlueFeatherGroup/eloquent-filemaker#setting-a-layout) documentation for more information about layout and table naming.

## Install and configure Laravel
Laravel should be installed and configured as normal. You can follow the instructions on the [official Laravel website](https://laravel.com/docs/9.x/installation) to get started.
If you already know what you're doing, installation is easy using composer.

```
composer create-project laravel/laravel example-app
```
## Install Laravel Jetstream
Similar to the base Laravel install, you should follow the instructions for installing Jetstream as normal from the [offical Jetstream documentation](https://jetstream.laravel.com/2.x/introduction.html).

Our recommendation is to use the Inertia stack with Jetstream. The steps for a quick installation would go as follows:
```
composer require laravel/jetstream
php artisan jetstream:install inertia
npm install
npm run dev
```

## Install Jetstream-FileMaker
With the basic Jetstream installed it is now time to install the Jetstream-FileMaker package to make Jetstream work with FileMaker as a data source.

Install Jetstream-FileMaker using Composer
```
composer require bluefeather/jetstream-filemaker
```

Jetstream-FileMaker needs to update the default Jetstream `User` model and add new, custom models for `PasswordReset` and `PersonalAccessToken`. Install these models using artisan.
```
php artisan jetstream-filemaker:install
```

## Update the Laravel configuration
All the basic dependencies are now installed and it's time to configure Laravel to point to your FileMaker database. Update `config/auth.php` and change the existing providers->users->driver value from `eloquent` to `filemaker`. This will tell Laravel to use the custom FileMakerUserProvider included with this package to connect to FileMaker to read and write user credentials.
```
'providers' => [
'users' => [
'driver' => 'filemaker',
'model' => App\Models\User::class,
],
],
```

You also need to add a new FileMaker database connection to `config/database.php` in the `connections` array. This sets some defaults which will be overwritten by settings in the `.env` file.
```
'connections' => [
'filemaker' => [
'driver' => 'filemaker',
'host' => env('DB_HOST', 'bluefeathergroup.com'),
'database' => env('DB_DATABASE', 'MyDatabaseName'),
'username' => env('DB_USERNAME', 'MyUsername'),
'password' => env('DB_PASSWORD', ''),
'prefix' => env('DB_PREFIX', ''),
'version' => env('DB_VERSION', 'vLatest'),
'protocol' => env('DB_PROTOCOL', 'https'),
],
```

Finally, set update the session driver and database connection information in the `.env` file. If you're using the example file included with this package you would configure your `.env` as follows (with your real server address in `DB_HOST`):
```
# Use a session driver other than 'database'
SESSION_DRIVER=file
DB_CONNECTION=filemaker
DB_HOST=fms.mycompany.com
DB_DATABASE=Jetstream-FileMaker
DB_USERNAME=jetstream
DB_PASSWORD=jetstream
DB_PREFIX=web_
```

## License
Jetstream-FileMaker is open-sourced software licensed under the MIT license.
35 changes: 35 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "bluefeather/jetstream-filemaker",
"description": "An extension for Laravel Jetstream to make it work with FileMaker as a primary data source",
"license": "MIT",
"authors": [
{
"name": "David Nahodyl",
"email": "david@bluefeathergroup.com"
}
],
"require": {
"php": "^7.3|^8.0",
"ext-json": "*",
"bluefeather/eloquent-filemaker": "^0.0.28",
"laravel/jetstream": "^2.8",
"laravel/sanctum": "^2.15"
},
"autoload": {
"psr-4": {
"BlueFeather\\JetstreamFileMaker\\": "src/"
}
},
"extra": {
"laravel": {
"providers": [
"BlueFeather\\JetstreamFileMaker\\Providers\\JetstreamFileMakerServiceprovider",
"BlueFeather\\JetstreamFileMaker\\Providers\\PasswordResetServiceProvider",
"BlueFeather\\JetstreamFileMaker\\Providers\\FileMakerValidationServiceProvider"
]
}
},
"require-dev": {
"orchestra/testbench": "^7.5"
}
}
Binary file added dist/Jetstream-FileMaker.fmp12.zip
Binary file not shown.
97 changes: 97 additions & 0 deletions src/Auth/Passwords/DatabaseTokenRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

namespace BlueFeather\JetstreamFileMaker\Auth\Passwords;

use App\Models\PasswordReset;
use Carbon\Carbon;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;

class DatabaseTokenRepository extends \Illuminate\Auth\Passwords\DatabaseTokenRepository
{

/**
* Create a new token record.
*
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
* @return string
*/
public function create(CanResetPasswordContract $user)
{
$email = $user->getEmailForPasswordReset();

$this->deleteExisting($user);

// We will create a new, random token for the user so that we can e-mail them
// a safe link to the password reset form. Then we will insert a record in
// the database so that we can verify the token within the actual reset.
$token = $this->createNewToken();

(new PasswordReset([
'email' => $email,
'token' => $this->hasher->make($token),
'created_at' => new Carbon(),
]))->save();

return $token;
}

/**
* Delete all existing reset tokens from the database.
*
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
* @return int
*/
protected function deleteExisting(CanResetPasswordContract $user)
{
$resets = PasswordReset::where('email', "==", $user->getEmailForPasswordReset())->get();

foreach ($resets as $reset){
$reset->delete();
}
return $resets->count();
}

/**
* Determine if a token record exists and is valid.
*
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
* @param string $token
* @return bool
*/
public function exists(CanResetPasswordContract $user, $token)
{

$record = PasswordReset::where('email', '==', $user->getEmailForPasswordReset())->first();

return $record &&
! $this->tokenExpired($record->created_at) &&
$this->hasher->check($token, $record->token);
}

/**
* Determine if the token has expired.
*
* @param string $createdAt
* @return bool
*/
protected function tokenExpired($createdAt)
{
return $createdAt->addSeconds($this->expires)->isPast();
}

/**
* Determine if the given user recently created a password reset token.
*
* @param \Illuminate\Contracts\Auth\CanResetPassword $user
* @return bool
*/
public function recentlyCreatedToken(CanResetPasswordContract $user)
{
$record = PasswordReset::where(
'email', '==', $user->getEmailForPasswordReset()
)->first();

return $record && $this->tokenRecentlyCreated($record->created_at);
}

}
33 changes: 33 additions & 0 deletions src/Auth/Passwords/PasswordBrokerManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace BlueFeather\JetstreamFileMaker\Auth\Passwords;

class PasswordBrokerManager extends \Illuminate\Auth\Passwords\PasswordBrokerManager
{

/**
* Create a token repository instance based on the given configuration.
*
* @param array $config
* @return \Illuminate\Auth\Passwords\TokenRepositoryInterface
*/
protected function createTokenRepository(array $config)
{
$key = $this->app['config']['app.key'];

if (str_starts_with($key, 'base64:')) {
$key = base64_decode(substr($key, 7));
}

$connection = $config['connection'] ?? null;

return new DatabaseTokenRepository(
$this->app['db']->connection($connection),
$this->app['hash'],
$config['table'],
$key,
$config['expire'],
$config['throttle'] ?? 0
);
}
}
33 changes: 33 additions & 0 deletions src/Console/InstallCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace BlueFeather\JetstreamFileMaker\Console;

use Illuminate\Console\Command;

class InstallCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'jetstream-filemaker:install';


/**
* The console command description.
*
* @var string
*/
protected $description = 'Install the Jetstream-FileMaker resources';

public function handle(){
// Models...
copy(__DIR__.'/../../stubs/app/Models/PasswordReset.php', app_path('Models/PasswordReset.php'));
copy(__DIR__.'/../../stubs/app/Models/PersonalAccessToken.php', app_path('Models/PersonalAccessToken.php'));
copy(__DIR__.'/../../stubs/app/Models/User.php', app_path('Models/User.php'));



}
}
Loading

0 comments on commit 018247b

Please sign in to comment.