From 84bdc98255bb125e40907d15c1190798faa54831 Mon Sep 17 00:00:00 2001 From: Atila Silva Date: Tue, 5 Nov 2024 00:21:22 -0300 Subject: [PATCH] Change all namespace (#24) --- .github/FUNDING.yml | 1 + .github/ISSUE_TEMPLATE/bug.yml | 66 +++++++ .github/ISSUE_TEMPLATE/config.yml | 11 ++ .github/dependabot.yml | 19 ++ .github/workflows/dependabot-auto-merge.yml | 33 ++++ .../workflows/fix-php-code-style-issues.yml | 28 +++ .github/workflows/phpstan.yml | 28 +++ .github/workflows/run-tests.yml | 58 ++++++ .gitignore | 35 +++- CHANGELOG.md | 1 + LICENSE => LICENSE.md | 12 +- README.md | 74 +++++++- composer.json | 81 +++++--- config/filament-saas.php | 16 ++ config/octo.php | 12 -- database/factories/ModelFactory.php | 19 ++ .../create_filament_saas_table.php.stub | 19 ++ phpstan-baseline.neon | 0 phpstan.neon.dist | 12 ++ phpunit.xml.dist | 41 ++-- resources/views/.gitkeep | 0 .../views/pages/tenant-user-profile.blade.php | 8 +- resources/views/user/livewire/phone.blade.php | 6 +- .../views/user/livewire/username.blade.php | 6 +- .../FilamentSaasCommand.php} | 20 +- src/Facades/FilamentSaas.php | 16 ++ src/Features/Features.php | 2 +- src/Features/FeaturesPlugin.php | 8 +- src/Features/FeaturesServiceProvider.php | 20 +- .../Filament/Components/SwitchLanguage.php | 8 +- src/Features/Filament/Pages/FeaturesPage.php | 20 +- src/Features/Filament/Pages/Policy.php | 8 +- src/Features/Filament/Pages/Terms.php | 8 +- src/FilamentSaas.php | 16 ++ src/FilamentSaasServiceProvider.php | 42 ++++ src/Middleware/Http/Middleware/LogViewer.php | 2 +- .../Http/Middleware/RestrictIps.php | 4 +- src/Middleware/MiddlewareServiceProvider.php | 4 +- src/Octo.php | 13 -- src/OctoServiceProvider.php | 38 ---- .../Filament/Pages/MainSettingsPage.php | 10 +- src/Settings/Http/Middleware/Locale.php | 4 +- src/Settings/Settings.php | 2 +- src/Settings/SettingsPlugin.php | 8 +- src/Settings/SettingsServiceProvider.php | 8 +- src/Settings/TermsSettings.php | 2 +- src/Settings/WebhooksSettings.php | 2 +- src/Settings/reCAPTCHASettings.php | 2 +- src/System/Filament/ExceptionResource.php | 2 +- src/System/Filament/LoggerResource.php | 2 +- src/System/SystemPlugin.php | 9 +- .../FilamentCompanies/AddCompanyEmployee.php | 6 +- .../FilamentCompanies/CreateCompany.php | 6 +- .../CreateConnectedAccount.php | 2 +- .../FilamentCompanies/CreateNewUser.php | 8 +- .../CreateUserFromProvider.php | 8 +- .../FilamentCompanies/DeleteCompany.php | 4 +- .../Actions/FilamentCompanies/DeleteUser.php | 10 +- .../FilamentCompanies/HandleInvalidState.php | 2 +- .../InviteCompanyEmployee.php | 6 +- .../RemoveCompanyEmployee.php | 6 +- .../ResolveSocialiteUser.php | 4 +- .../FilamentCompanies/SetUserPassword.php | 4 +- .../FilamentCompanies/UpdateCompanyName.php | 2 +- .../UpdateConnectedAccount.php | 2 +- .../FilamentCompanies/UpdateUserPassword.php | 4 +- .../UpdateUserProfileInformation.php | 4 +- src/Tenant/Company.php | 179 ++++++++++++++++++ src/Tenant/CompanyInvitation.php | 28 +++ src/Tenant/ConnectedAccount.php | 42 ++++ src/Tenant/Employeeship.php | 18 ++ .../Http/Middleware/TenancyInitialize.php | 2 +- src/Tenant/TenantPlugin.php | 5 +- src/Tenant/TenantServiceProvider.php | 16 +- src/User/Filament/Components/Phone.php | 14 +- src/User/Filament/Components/Username.php | 13 +- src/User/Filament/Pages/BannedUser.php | 8 +- src/User/Filament/Pages/CreateUser.php | 4 +- src/User/Filament/Pages/EditUser.php | 4 +- src/User/Filament/Pages/ListUsers.php | 4 +- src/User/Filament/Pages/Register.php | 13 +- src/User/Filament/Pages/TenantRegister.php | 14 +- .../Filament/Pages/TentantUserProfilePage.php | 4 +- src/User/Filament/Pages/ViewUser.php | 4 +- src/User/Filament/UserResource.php | 12 +- src/User/Filament/Widgets/UsersChart.php | 4 +- src/User/Filament/Widgets/UsersOverview.php | 4 +- src/User/Settings.php | 2 +- src/User/Stats/UserStats.php | 2 +- src/User/User.php | 105 ++++++++++ src/User/UserObserver.php | 24 --- src/User/UserPlugin.php | 8 +- src/User/UserServiceProvider.php | 29 +-- src/Webhook/Filament/Pages/WebhookHistory.php | 2 +- src/Webhook/Filament/Pages/Webhooks.php | 2 +- src/Webhook/WebhookServiceProvider.php | 4 +- src/helpers.php | 12 +- tests/ArchTest.php | 5 + tests/ExampleTest.php | 2 +- tests/Pest.php | 44 +---- tests/TestCase.php | 55 ++++++ .../Providers/WorkbenchServiceProvider.php | 25 +++ 102 files changed, 1246 insertions(+), 411 deletions(-) create mode 100644 .github/FUNDING.yml create mode 100644 .github/ISSUE_TEMPLATE/bug.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/dependabot-auto-merge.yml create mode 100644 .github/workflows/fix-php-code-style-issues.yml create mode 100644 .github/workflows/phpstan.yml create mode 100644 .github/workflows/run-tests.yml rename LICENSE => LICENSE.md (85%) create mode 100644 config/filament-saas.php delete mode 100644 config/octo.php create mode 100644 database/factories/ModelFactory.php create mode 100644 database/migrations/create_filament_saas_table.php.stub create mode 100644 phpstan-baseline.neon create mode 100644 phpstan.neon.dist create mode 100644 resources/views/.gitkeep rename src/{Console/OctoInstallCommand.php => Commands/FilamentSaasCommand.php} (86%) create mode 100644 src/Facades/FilamentSaas.php create mode 100644 src/FilamentSaas.php create mode 100644 src/FilamentSaasServiceProvider.php delete mode 100644 src/Octo.php delete mode 100644 src/OctoServiceProvider.php create mode 100644 src/Tenant/Company.php create mode 100644 src/Tenant/CompanyInvitation.php create mode 100644 src/Tenant/ConnectedAccount.php create mode 100644 src/Tenant/Employeeship.php create mode 100644 src/User/User.php delete mode 100644 src/User/UserObserver.php create mode 100644 tests/ArchTest.php create mode 100644 tests/TestCase.php create mode 100644 workbench/app/Providers/WorkbenchServiceProvider.php diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..c65c94a --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: a2insights diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 0000000..fe4cfe6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,66 @@ +name: Bug Report +description: Report an Issue or Bug with the Package +title: "[Bug]: " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + We're sorry to hear you have a problem. Can you help us solve it by providing the following details. + - type: textarea + id: what-happened + attributes: + label: What happened? + description: What did you expect to happen? + placeholder: I cannot currently do X thing because when I do, it breaks X thing. + validations: + required: true + - type: textarea + id: how-to-reproduce + attributes: + label: How to reproduce the bug + description: How did this occur, please add any config values used and provide a set of reliable steps if possible. + placeholder: When I do X I see Y. + validations: + required: true + - type: input + id: package-version + attributes: + label: Package Version + description: What version of our Package are you running? Please be as specific as possible + placeholder: 2.0.0 + validations: + required: true + - type: input + id: php-version + attributes: + label: PHP Version + description: What version of PHP are you running? Please be as specific as possible + placeholder: 8.2.0 + validations: + required: true + - type: input + id: laravel-version + attributes: + label: Laravel Version + description: What version of Laravel are you running? Please be as specific as possible + placeholder: 9.0.0 + validations: + required: true + - type: dropdown + id: operating-systems + attributes: + label: Which operating systems does with happen with? + description: You may select more than one. + multiple: true + options: + - macOS + - Windows + - Linux + - type: textarea + id: notes + attributes: + label: Notes + description: Use this field to provide any other notes that you feel might be relevant to the issue. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..7e144ad --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Ask a question + url: https://github.com/a2insights/filament-saas/discussions/new?category=q-a + about: Ask the community for help + - name: Request a feature + url: https://github.com/a2insights/filament-saas/discussions/new?category=ideas + about: Share ideas for new features + - name: Report a security issue + url: https://github.com/a2insights/filament-saas/security/policy + about: Learn how to notify us for sensitive bugs diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..39b1580 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,19 @@ +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependencies" + + - package-ecosystem: "composer" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependencies" diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml new file mode 100644 index 0000000..14bb9d3 --- /dev/null +++ b/.github/workflows/dependabot-auto-merge.yml @@ -0,0 +1,33 @@ +# name: dependabot-auto-merge +# on: pull_request_target + +# permissions: +# pull-requests: write +# contents: write + +# jobs: +# dependabot: +# runs-on: ubuntu-latest +# timeout-minutes: 5 +# if: ${{ github.actor == 'dependabot[bot]' }} +# steps: + +# - name: Dependabot metadata +# id: metadata +# uses: dependabot/fetch-metadata@v2.2.0 +# with: +# github-token: "${{ secrets.GITHUB_TOKEN }}" + +# - name: Auto-merge Dependabot PRs for semver-minor updates +# if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor'}} +# run: gh pr merge --auto --merge "$PR_URL" +# env: +# PR_URL: ${{github.event.pull_request.html_url}} +# GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + +# - name: Auto-merge Dependabot PRs for semver-patch updates +# if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}} +# run: gh pr merge --auto --merge "$PR_URL" +# env: +# PR_URL: ${{github.event.pull_request.html_url}} +# GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/fix-php-code-style-issues.yml b/.github/workflows/fix-php-code-style-issues.yml new file mode 100644 index 0000000..56d54d3 --- /dev/null +++ b/.github/workflows/fix-php-code-style-issues.yml @@ -0,0 +1,28 @@ +name: Fix PHP code style issues + +on: + push: + paths: + - '**.php' + +permissions: + contents: write + +jobs: + php-code-styling: + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + + - name: Fix PHP code style issues + uses: aglipanci/laravel-pint-action@2.4 + + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: Fix styling diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml new file mode 100644 index 0000000..f576af5 --- /dev/null +++ b/.github/workflows/phpstan.yml @@ -0,0 +1,28 @@ +# name: PHPStan + +# on: +# push: +# paths: +# - '**.php' +# - 'phpstan.neon.dist' +# - '.github/workflows/phpstan.yml' + +# jobs: +# phpstan: +# name: phpstan +# runs-on: ubuntu-latest +# timeout-minutes: 5 +# steps: +# - uses: actions/checkout@v4 + +# - name: Setup PHP +# uses: shivammathur/setup-php@v2 +# with: +# php-version: '8.2' +# coverage: none + +# - name: Install composer dependencies +# uses: ramsey/composer-install@v3 + +# - name: Run PHPStan +# run: ./vendor/bin/phpstan --error-format=github diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 0000000..de91133 --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,58 @@ +# name: run-tests + +# on: +# push: +# paths: +# - '**.php' +# - '.github/workflows/run-tests.yml' +# - 'phpunit.xml.dist' +# - 'composer.json' +# - 'composer.lock' + +# jobs: +# test: +# runs-on: ${{ matrix.os }} +# timeout-minutes: 5 +# strategy: +# fail-fast: true +# matrix: +# os: [ubuntu-latest, windows-latest] +# php: [8.3, 8.2] +# laravel: [11.*, 10.*] +# stability: [prefer-lowest, prefer-stable] +# include: +# - laravel: 11.* +# testbench: 9.* +# carbon: ^2.63 +# - laravel: 10.* +# testbench: 8.* +# carbon: ^2.63 + +# name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} + +# steps: +# - name: Checkout code +# uses: actions/checkout@v4 + +# - name: Setup PHP +# uses: shivammathur/setup-php@v2 +# with: +# php-version: ${{ matrix.php }} +# extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo +# coverage: none + +# - name: Setup problem matchers +# run: | +# echo "::add-matcher::${{ runner.tool_cache }}/php.json" +# echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + +# - name: Install dependencies +# run: | +# composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" "nesbot/carbon:${{ matrix.os == 'windows-latest' && '^^^' || '' }}${{ matrix.carbon }}" --no-interaction --no-update +# composer update --${{ matrix.stability }} --prefer-dist --no-interaction + +# - name: List Installed Dependencies +# run: composer show -D + +# - name: Execute tests +# run: vendor/bin/pest --ci diff --git a/.gitignore b/.gitignore index 6a7cb1b..b60507f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,32 @@ -vendor -.idea -.env +# Composer Related composer.lock +/vendor + +# Frontend Assets +/node_modules + +# Logs +npm-debug.log +yarn-error.log + +# Caches +.phpunit.cache .phpunit.result.cache -tests/database.sqlite -.tool-versions +/build + +# IDE Helper +_ide_helper.php +_ide_helper_models.php +.phpstorm.meta.php + +# Editors +/.idea +/.fleet +/.vscode + +# Misc +phpunit.xml +phpstan.neon +testbench.yaml +/docs +/coverage diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dc68c6..9fb3bd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,3 @@ # Changelog +All notable changes to `filament-saas` will be documented in this file. diff --git a/LICENSE b/LICENSE.md similarity index 85% rename from LICENSE rename to LICENSE.md index 64a0f75..86e0211 100644 --- a/LICENSE +++ b/LICENSE.md @@ -1,6 +1,6 @@ -MIT License +The MIT License (MIT) -Copyright (c) Atila Silva +Copyright (c) a2insights Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -9,13 +9,13 @@ 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 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. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md index c29d689..6a7f275 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,83 @@ -# octo-core +# This is my package filament-saas -# Don't try install this package, it's not ready yet to use directly in your project +[![Latest Version on Packagist](https://img.shields.io/packagist/v/a2insights/filament-saas.svg?style=flat-square)](https://packagist.org/packages/a2insights/filament-saas) +[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/a2insights/filament-saas/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/a2insights/filament-saas/actions?query=workflow%3Arun-tests+branch%3Amain) +[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/a2insights/filament-saas/fix-php-code-style-issues.yml?branch=main&label=code%20style&style=flat-square)](https://github.com/a2insights/filament-saas/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amain) +[![Total Downloads](https://img.shields.io/packagist/dt/a2insights/filament-saas.svg?style=flat-square)](https://packagist.org/packages/a2insights/filament-saas) -# Instead, use [octo](https://github.com/a2insights/octo) template +This is where your description should go. Limit it to a paragraph or two. Consider adding a small example. -[![GitHub license](https://img.shields.io/github/license/gothinkster/laravel-realworld-example-app.svg)](https://raw.githubusercontent.com/a2insights/octo-core/main/LICENSE) +## Support us + +[](https://spatie.be/github-ad-click/filament-saas) + +We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us). + +We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards). + +## Installation + +You can install the package via composer: + +```bash +composer require a2insights/filament-saas +``` + +You can publish and run the migrations with: + +```bash +php artisan vendor:publish --tag="filament-saas-migrations" +php artisan migrate +``` + +You can publish the config file with: + +```bash +php artisan vendor:publish --tag="filament-saas-config" +``` + +This is the contents of the published config file: + +```php +return [ +]; +``` + +Optionally, you can publish the views using + +```bash +php artisan vendor:publish --tag="filament-saas-views" +``` + +## Usage + +```php +$filamentSaas = new A2insights\FilamentSaas(); +echo $filamentSaas->echoPhrase('Hello, A2insights!'); +``` + +## Testing + +```bash +composer test +``` ## Changelog -Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. +Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. ## Contributing Please see [CONTRIBUTING](CONTRIBUTING.md) for details. -## Security +## Security Vulnerabilities -If you discover any security related issues, please email atila.danvi@outlook.com instead of using the issue tracker. +Please review [our security policy](../../security/policy) on how to report security vulnerabilities. ## Credits -- [Atila Silva](https://github.com/a21ns1g4ts) -- [All Contributors](../../contributors) +- [a21ns1g4ts](https://github.com/a21ns1g4ts) +- [All Contributors](../../contributors) ## License diff --git a/composer.json b/composer.json index 476a4aa..8cbfe87 100644 --- a/composer.json +++ b/composer.json @@ -1,34 +1,26 @@ { "name": "a2insights/filament-saas", - "description": "Saas package for Filament", + "description": "Filament Saas for A2insights", "keywords": [ + "a2insights", "laravel", - "php", - "filament", - "sass" + "filament-saas" ], - "minimum-stability": "dev", "homepage": "https://github.com/a2insights/filament-saas", "license": "MIT", - "type": "library", "authors": [ { - "name": "Atila Silva", + "name": "a21ns1g4ts", "email": "atila.danvi@outlook.com", "role": "Developer" } ], "require": { - "php": "^8.1", - "ext-json": "*", + "php": "^8.2", "amidesfahani/filament-tinyeditor": "^2.0", - "bezhansalleh/filament-panel-switch": "^1.0", "andrewdwallo/filament-companies": "^4.0", "bezhansalleh/filament-exceptions": "^2.1", - "filament/spatie-laravel-media-library-plugin": "^3.2", - "icetalker/filament-picker": "^0.1.1", - "joaopaulolndev/filament-pdf-viewer": "^1.0", - "solution-forest/filament-field-group": "^1.0", + "bezhansalleh/filament-panel-switch": "^1.0", "bezhansalleh/filament-shield": "^3.2", "blade-ui-kit/blade-heroicons": "^2.1", "blade-ui-kit/blade-icons": "^1.6", @@ -40,22 +32,30 @@ "croustibat/filament-jobs-monitor": "^2.0", "filament/filament": "^3.2", "filament/notifications": "^3.2", + "filament/spatie-laravel-media-library-plugin": "^3.2", "filament/spatie-laravel-settings-plugin": "^3.2", "filament/tables": "^3.2", "hasnayeen/themes": "^3.0", "husam-tariq/filament-database-schedule": "^2.0", + "icetalker/filament-picker": "^0.1.1", + "illuminate/contracts": "^10.0||^11.0", "illuminate/support": "^10.0|^11.0", "jeffgreco13/filament-breezy": "^2.4", + "joaopaulolndev/filament-pdf-viewer": "^1.0", + "laravel/sanctum": "^4.0", "league/flysystem-aws-s3-v3": "^3.0", + "livewire/livewire": "^3.5", "malzariey/filament-daterangepicker-filter": "^2.2", "marjose123/filament-webhook-server": "^2.1", "opcodesio/log-viewer": "^3.10", "openai-php/laravel": "^0.10.1", "pxlrbt/filament-environment-indicator": "^2.0", "pxlrbt/filament-spotlight": "^1.2", + "solution-forest/filament-field-group": "^1.0", "solution-forest/filament-firewall": "^2.0", "spatie/laravel-data": "^3.6", "spatie/laravel-enum": "^3.0", + "spatie/laravel-package-tools": "^1.16", "spatie/laravel-stats": "^2.1", "stancl/tenancy": "^3.8", "symfony/intl": "^6.2", @@ -66,42 +66,69 @@ "z3d0x/filament-logger": "^0.7" }, "require-dev": { - "laravel/pint": "dev-main", - "nunomaduro/larastan": "^2.6", - "pestphp/pest": "^3.4" - }, - "suggest": { - "doctrine/dbal": "Required by Cashier to modify tables in the database.", - "laravel/cashier": "Required to use with the Stripe scaffolding." + "laravel/pint": "^1.14", + "nunomaduro/collision": "^8.1.1||^7.10.0", + "larastan/larastan": "^2.9", + "orchestra/testbench": "^9.0.0||^8.22.0", + "pestphp/pest": "^2.34", + "pestphp/pest-plugin-arch": "^2.7", + "pestphp/pest-plugin-laravel": "^2.3", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "spatie/laravel-ray": "^1.35" }, "autoload": { "files": [ "src/helpers.php" ], "psr-4": { - "Octo\\": "src" + "A2insights\\FilamentSaas\\": "src/", + "A2insights\\FilamentSaas\\Database\\Factories\\": "database/factories/" } }, "autoload-dev": { "psr-4": { - "Octo\\Tests\\": "tests" + "A2insights\\FilamentSaas\\Tests\\": "tests/", + "Workbench\\App\\": "workbench/app/" } }, "scripts": { - "test": "vendor/bin/phpunit" + "post-autoload-dump": "@composer run prepare", + "clear": "@php vendor/bin/testbench package:purge-filament-saas --ansi", + "prepare": "@php vendor/bin/testbench package:discover --ansi", + "build": [ + "@composer run prepare", + "@php vendor/bin/testbench workbench:build --ansi" + ], + "start": [ + "Composer\\Config::disableProcessTimeout", + "@composer run build", + "@php vendor/bin/testbench serve" + ], + "analyse": "vendor/bin/phpstan analyse", + "test": "vendor/bin/pest", + "test-coverage": "vendor/bin/pest --coverage", + "format": "vendor/bin/pint" }, "config": { "sort-packages": true, "allow-plugins": { "pestphp/pest-plugin": true, + "phpstan/extension-installer": true, "php-http/discovery": true } }, "extra": { "laravel": { "providers": [ - "Octo\\OctoServiceProvider" - ] + "A2insights\\FilamentSaas\\FilamentSaasServiceProvider" + ], + "aliases": { + "FilamentSaas": "A2insights\\FilamentSaas\\Facades\\FilamentSaas" + } } - } + }, + "minimum-stability": "dev", + "prefer-stable": true } diff --git a/config/filament-saas.php b/config/filament-saas.php new file mode 100644 index 0000000..8bd9996 --- /dev/null +++ b/config/filament-saas.php @@ -0,0 +1,16 @@ + 'admin', + 'tenant_path' => 'company', + + 'users' => [ + 'model' => A2insights\FilamentSaas\User\User::class, + 'resource' => A2insights\FilamentSaas\User\Filament\UserResource::class, + 'tenant_scope' => false, + ], + + 'companies' => [ + 'model' => A2insights\FilamentSaas\Tenant\Company::class, + ], +]; diff --git a/config/octo.php b/config/octo.php deleted file mode 100644 index 81d5f37..0000000 --- a/config/octo.php +++ /dev/null @@ -1,12 +0,0 @@ - 'admin', - 'tenant_path' => 'company', - - 'users' => [ - 'model' => App\Models\User::class, - 'resource' => Octo\User\Filament\UserResource::class, - 'tenant_scope' => false, - ], -]; diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php new file mode 100644 index 0000000..b95a972 --- /dev/null +++ b/database/factories/ModelFactory.php @@ -0,0 +1,19 @@ +id(); + + // add fields + + $table->timestamps(); + }); + } +}; diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000..e69de29 diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..ab1b4c3 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,12 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: 5 + paths: + - src + - config + - database + tmpDir: build/phpstan + checkOctaneCompatibility: true + checkModelProperties: true diff --git a/phpunit.xml.dist b/phpunit.xml.dist index f2eebe0..6e9c719 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,22 +1,31 @@ - + - + tests - - - src/ - - + + + + + + ./src + + diff --git a/resources/views/.gitkeep b/resources/views/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/resources/views/pages/tenant-user-profile.blade.php b/resources/views/pages/tenant-user-profile.blade.php index ec09f2c..2b4bd61 100644 --- a/resources/views/pages/tenant-user-profile.blade.php +++ b/resources/views/pages/tenant-user-profile.blade.php @@ -14,16 +14,16 @@ "Wallo\FilamentCompanies\Http\Livewire\LogoutOtherBrowserSessionsForm", "Wallo\FilamentCompanies\Http\Livewire\DeleteUserForm", "Jeffgreco13\FilamentBreezy\Livewire\PersonalInfo", - "Octo\User\Filament\Components\Phone", - "Octo\User\Filament\Components\Username", + "A2insights\FilamentSaas\User\Filament\Components\Phone", + "A2insights\FilamentSaas\User\Filament\Components\Username", "Jeffgreco13\FilamentBreezy\Livewire\UpdatePassword", "Jeffgreco13\FilamentBreezy\Livewire\TwoFactorAuthentication", ]; $showComponents = [ "Jeffgreco13\FilamentBreezy\Livewire\PersonalInfo", - "Octo\User\Filament\Components\Username", - "Octo\User\Filament\Components\Phone", + "A2insights\FilamentSaas\User\Filament\Components\Username", + "A2insights\FilamentSaas\User\Filament\Components\Phone", "Jeffgreco13\FilamentBreezy\Livewire\UpdatePassword", "Jeffgreco13\FilamentBreezy\Livewire\TwoFactorAuthentication", "Wallo\FilamentCompanies\Http\Livewire\ConnectedAccountsForm", diff --git a/resources/views/user/livewire/phone.blade.php b/resources/views/user/livewire/phone.blade.php index 403c7c5..16aeaac 100644 --- a/resources/views/user/livewire/phone.blade.php +++ b/resources/views/user/livewire/phone.blade.php @@ -1,5 +1,5 @@ - +
@@ -7,7 +7,7 @@
- {{ __('octo-core::default.user.profile.phone.submit') }} + {{ __('filament-saas::default.user.profile.phone.submit') }}
diff --git a/resources/views/user/livewire/username.blade.php b/resources/views/user/livewire/username.blade.php index 23774ee..eaf71b0 100644 --- a/resources/views/user/livewire/username.blade.php +++ b/resources/views/user/livewire/username.blade.php @@ -1,5 +1,5 @@ - +
@@ -7,7 +7,7 @@
- {{ __('octo-core::default.user.profile.username.submit') }} + {{ __('filament-saas::default.user.profile.username.submit') }}
diff --git a/src/Console/OctoInstallCommand.php b/src/Commands/FilamentSaasCommand.php similarity index 86% rename from src/Console/OctoInstallCommand.php rename to src/Commands/FilamentSaasCommand.php index 53fa25a..eda4412 100644 --- a/src/Console/OctoInstallCommand.php +++ b/src/Commands/FilamentSaasCommand.php @@ -1,34 +1,34 @@ self::DEFAULT_SUPER_ADMIN_NAME, 'email' => self::DEFAULT_SUPER_ADMIN_EMAIL, 'password' => Hash::make(self::DEFAULT_SUPER_ADMIN_PASSWORD), @@ -94,7 +94,7 @@ private function setUpSuperAdminAccount() private function setUpAdminAccount() { - $user = Octo::getUserModel()::forceCreate([ + $user = FilamentSaas::getUserModel()::forceCreate([ 'name' => self::DEFAULT_ADMIN_NAME, 'email' => self::DEFAULT_ADMIN_EMAIL, 'password' => Hash::make(self::DEFAULT_ADMIN_PASSWORD), @@ -118,7 +118,7 @@ private function setUpAdminAccount() private function setUpUserAccount() { - $user = Octo::getUserModel()::forceCreate([ + $user = FilamentSaas::getUserModel()::forceCreate([ 'name' => self::DEFAULT_USER_NAME, 'email' => self::DEFAULT_USER_EMAIL, 'password' => Hash::make(self::DEFAULT_USER_PASSWORD), diff --git a/src/Facades/FilamentSaas.php b/src/Facades/FilamentSaas.php new file mode 100644 index 0000000..8c900a6 --- /dev/null +++ b/src/Facades/FilamentSaas.php @@ -0,0 +1,16 @@ +features = Cache::remember('octo.features', now()->addHours(10), fn () => app(Features::class)); + $this->features = Cache::remember('filament-saas.features', now()->addHours(10), fn () => app(Features::class)); $switchLanguage = $this->features->switch_language; if ($switchLanguage) { Filament::registerRenderHook( diff --git a/src/Features/FeaturesServiceProvider.php b/src/Features/FeaturesServiceProvider.php index 8cdaf73..dafa022 100644 --- a/src/Features/FeaturesServiceProvider.php +++ b/src/Features/FeaturesServiceProvider.php @@ -1,17 +1,17 @@ name('octo.features'); + $package->name('filament-saas.features'); Route::get('/terms-of-service', Terms::class) ->middleware('web') @@ -41,7 +41,7 @@ public function packageBooted(): void return; } - $this->features = Cache::remember('octo.features', now()->addHours(10), fn () => App::make(Features::class)); + $this->features = Cache::remember('filament-saas.features', now()->addHours(10), fn () => App::make(Features::class)); Livewire::component('switch-language', SwitchLanguage::class); @@ -55,7 +55,7 @@ public function packageBooted(): void private function syncRecaptcha(): void { if ($this->features->recaptcha) { - $recaptchaSettings = Cache::remember('octo.recaptcha', now()->addHours(10), fn () => App::make(reCAPTCHASettings::class)); + $recaptchaSettings = Cache::remember('filament-saas.recaptcha', now()->addHours(10), fn () => App::make(reCAPTCHASettings::class)); // Prevents login page from breaking if recaptcha is enabled but no keys are set if (! $recaptchaSettings->site_key || ! $recaptchaSettings->secret_key) { @@ -83,7 +83,7 @@ private function syncWebhooks(): void Config::set('filament-webhook-server.pages', []); Config::set('filament-webhook-server.models', []); } else { - $webhookSettings = Cache::remember('octo.webhooks', now()->addHours(10), fn () => App::make(WebhooksSettings::class)); + $webhookSettings = Cache::remember('filament-saas.webhooks', now()->addHours(10), fn () => App::make(WebhooksSettings::class)); Config::set('filament-webhook-server.models', $webhookSettings->models); Config::set('filament-webhook-server.polling', $webhookSettings->poll_interval); diff --git a/src/Features/Filament/Components/SwitchLanguage.php b/src/Features/Filament/Components/SwitchLanguage.php index 0fbc4f5..9da55a4 100644 --- a/src/Features/Filament/Components/SwitchLanguage.php +++ b/src/Features/Filament/Components/SwitchLanguage.php @@ -1,11 +1,11 @@ save(); } - cache()->forget('octo.features'); - cache()->forget('octo.settings'); - cache()->forget('octo.webhooks'); + cache()->forget('filament-saas.features'); + cache()->forget('filament-saas.settings'); + cache()->forget('filament-saas.webhooks'); } protected function mutateFormDataBeforeFill(array $data): array @@ -134,7 +134,7 @@ protected function getFormSchema(): array ->label('Webhooks Models available') ->multiple() ->options([ - Octo::getUserModel() => 'user', + FilamentSaas::getUserModel() => 'user', \Cog\Laravel\Ban\Models\Ban::class => 'ban', \HusamTariq\FilamentDatabaseSchedule\Models\Schedule::class => 'schedule', \Spatie\LaravelSettings\Models\SettingsProperty::class => 'settings', diff --git a/src/Features/Filament/Pages/Policy.php b/src/Features/Filament/Pages/Policy.php index 3dc9dc4..079326e 100644 --- a/src/Features/Filament/Pages/Policy.php +++ b/src/Features/Filament/Pages/Policy.php @@ -1,12 +1,12 @@ redirect(config('filament-saas.admin_path'))); + + /* + * This class is a Package Service Provider + * + * More info: https://github.com/spatie/laravel-package-tools + */ + $package + ->name('filament-saas') + ->hasViews('filament-saas') + ->hasConfigFile('filament-saas') + ->hasTranslations() + ->hasCommand(FilamentSaasCommand::class); + } + + public function bootingPackage() + { + $this->app->register(UserServiceProvider::class); + $this->app->register(FeaturesServiceProvider::class); + $this->app->register(SettingsServiceProvider::class); + $this->app->register(MiddlewareServiceProvider::class); + $this->app->register(TenantServiceProvider::class); + } +} diff --git a/src/Middleware/Http/Middleware/LogViewer.php b/src/Middleware/Http/Middleware/LogViewer.php index 7ae31e5..cc7964b 100644 --- a/src/Middleware/Http/Middleware/LogViewer.php +++ b/src/Middleware/Http/Middleware/LogViewer.php @@ -1,6 +1,6 @@ ip(), $settings->restrict_ips)) { abort(403); diff --git a/src/Middleware/MiddlewareServiceProvider.php b/src/Middleware/MiddlewareServiceProvider.php index 75ad29f..dc55e55 100644 --- a/src/Middleware/MiddlewareServiceProvider.php +++ b/src/Middleware/MiddlewareServiceProvider.php @@ -1,6 +1,6 @@ name('octo.middleware'); + $package->name('filament-saas.middleware'); } } diff --git a/src/Octo.php b/src/Octo.php deleted file mode 100644 index 499e765..0000000 --- a/src/Octo.php +++ /dev/null @@ -1,13 +0,0 @@ -app->register(UserServiceProvider::class); - $this->app->register(FeaturesServiceProvider::class); - $this->app->register(SettingsServiceProvider::class); - $this->app->register(MiddlewareServiceProvider::class); - $this->app->register(TenantServiceProvider::class); - - Route::get('/', fn() => redirect(config('octo.admin_path'))); - - /* - * This class is a Package Service Provider - * - * More info: https://github.com/spatie/laravel-package-tools - */ - $package - ->name('octo-core') - ->hasViews('octo') - ->hasConfigFile('octo') - ->hasTranslations() - ->hasCommand(Console\OctoInstallCommand::class); - } -} diff --git a/src/Settings/Filament/Pages/MainSettingsPage.php b/src/Settings/Filament/Pages/MainSettingsPage.php index 41ed4f7..44ed860 100644 --- a/src/Settings/Filament/Pages/MainSettingsPage.php +++ b/src/Settings/Filament/Pages/MainSettingsPage.php @@ -1,7 +1,8 @@ forget('octo.features'); - cache()->forget('octo.settings'); - cache()->forget('octo.webhooks'); + cache()->forget('filament-saas.features'); + cache()->forget('filament-saas.settings'); + cache()->forget('filament-saas.webhooks'); } protected function getFormSchema(): array diff --git a/src/Settings/Http/Middleware/Locale.php b/src/Settings/Http/Middleware/Locale.php index 4bd399f..08e3aa8 100644 --- a/src/Settings/Http/Middleware/Locale.php +++ b/src/Settings/Http/Middleware/Locale.php @@ -1,6 +1,6 @@ user()?->settings; - $settings = Cache::remember('octo.settings', now()->addHours(10), fn () => app(\Octo\Settings\Settings::class)); + $settings = Cache::remember('filament-saas.settings', now()->addHours(10), fn () => app(\A2insights\FilamentSaas\Settings\Settings::class)); $locale = $userSettings?->locale ?? $settings->locale; diff --git a/src/Settings/Settings.php b/src/Settings/Settings.php index 7953b85..85b666f 100644 --- a/src/Settings/Settings.php +++ b/src/Settings/Settings.php @@ -1,6 +1,6 @@ settings = Cache::remember('octo.settings', now()->addHours(10), fn() => app(Settings::class)); + $this->settings = Cache::remember('filament-saas.settings', now()->addHours(10), fn () => app(Settings::class)); $favicon = $this->settings->favicon; $logo = $this->settings->logo; diff --git a/src/Settings/SettingsServiceProvider.php b/src/Settings/SettingsServiceProvider.php index 002676e..0146212 100644 --- a/src/Settings/SettingsServiceProvider.php +++ b/src/Settings/SettingsServiceProvider.php @@ -1,6 +1,6 @@ name('octo.settings'); + $package->name('filament-saas.settings'); } public function packageBooted(): void @@ -30,10 +30,10 @@ public function packageBooted(): void } Event::listen(function (SettingsSaved $event) { - Cache::forget('octo.settings'); + Cache::forget('filament-saas.settings'); }); - $this->settings = Cache::remember('octo.settings', now()->addHours(10), fn () => app(Settings::class)); + $this->settings = Cache::remember('filament-saas.settings', now()->addHours(10), fn () => app(Settings::class)); $this->syncName(); $this->syncTimezone(); diff --git a/src/Settings/TermsSettings.php b/src/Settings/TermsSettings.php index 4f39cb5..010ecf1 100644 --- a/src/Settings/TermsSettings.php +++ b/src/Settings/TermsSettings.php @@ -1,6 +1,6 @@ navigationItems([ NavigationItem::make('Logs') ->url(config('log-viewer.route_path')) - ->hidden(fn() => ! Auth::user()?->hasRole('super_admin')) + ->hidden(fn () => ! Auth::user()?->hasRole('super_admin')) ->icon('iconpark-log') - ->group('System') + ->group('System'), ]); } diff --git a/src/Tenant/Actions/FilamentCompanies/AddCompanyEmployee.php b/src/Tenant/Actions/FilamentCompanies/AddCompanyEmployee.php index 1b47018..ca8abd8 100644 --- a/src/Tenant/Actions/FilamentCompanies/AddCompanyEmployee.php +++ b/src/Tenant/Actions/FilamentCompanies/AddCompanyEmployee.php @@ -1,9 +1,9 @@ ownedCompanies()->save(Company::forceCreate([ 'user_id' => $user->id, - 'name' => explode(' ', $user->name, 2)[0] . "'s Company", + 'name' => explode(' ', $user->name, 2)[0]."'s Company", 'personal_company' => true, ])); } diff --git a/src/Tenant/Actions/FilamentCompanies/CreateUserFromProvider.php b/src/Tenant/Actions/FilamentCompanies/CreateUserFromProvider.php index 14a2cc2..8a935e9 100644 --- a/src/Tenant/Actions/FilamentCompanies/CreateUserFromProvider.php +++ b/src/Tenant/Actions/FilamentCompanies/CreateUserFromProvider.php @@ -1,11 +1,11 @@ ownedCompanies()->save(Company::forceCreate([ 'user_id' => $user->id, - 'name' => explode(' ', $user->name, 2)[0] . "'s Company", + 'name' => explode(' ', $user->name, 2)[0]."'s Company", 'personal_company' => true, ])); } diff --git a/src/Tenant/Actions/FilamentCompanies/DeleteCompany.php b/src/Tenant/Actions/FilamentCompanies/DeleteCompany.php index ee65cc1..cdc3082 100644 --- a/src/Tenant/Actions/FilamentCompanies/DeleteCompany.php +++ b/src/Tenant/Actions/FilamentCompanies/DeleteCompany.php @@ -1,8 +1,8 @@ deleteCompanies($user); $user->deleteProfilePhoto(); - $user->connectedAccounts->each(static fn($account) => $account->delete()); - $user->tokens->each(static fn($token) => $token->delete()); + $user->connectedAccounts->each(static fn ($account) => $account->delete()); + $user->tokens->each(static fn ($token) => $token->delete()); $user->delete(); }); } diff --git a/src/Tenant/Actions/FilamentCompanies/HandleInvalidState.php b/src/Tenant/Actions/FilamentCompanies/HandleInvalidState.php index b6705de..b6b42c8 100644 --- a/src/Tenant/Actions/FilamentCompanies/HandleInvalidState.php +++ b/src/Tenant/Actions/FilamentCompanies/HandleInvalidState.php @@ -1,6 +1,6 @@ user(); if (Feature::GenerateMissingEmails->isEnabled()) { - $user->email = $user->getEmail() ?? ("{$user->id}@{$provider}" . config('app.domain')); + $user->email = $user->getEmail() ?? ("{$user->id}@{$provider}".config('app.domain')); } return $user; diff --git a/src/Tenant/Actions/FilamentCompanies/SetUserPassword.php b/src/Tenant/Actions/FilamentCompanies/SetUserPassword.php index 36f40bd..356c048 100644 --- a/src/Tenant/Actions/FilamentCompanies/SetUserPassword.php +++ b/src/Tenant/Actions/FilamentCompanies/SetUserPassword.php @@ -1,8 +1,8 @@ + */ + protected $fillable = [ + 'user_id', + 'name', + 'personal_company', + 'data', + ]; + + /** + * The event map for the model. + * + * @var array + */ + protected $dispatchesEvents = [ + 'created' => CompanyCreated::class, + 'updated' => CompanyUpdated::class, + 'deleted' => CompanyDeleted::class, + ]; + + /** + * Get the attributes that should be cast. + * + * @return array + */ + protected function casts(): array + { + return [ + 'personal_company' => 'boolean', + 'data' => 'array', + ]; + } + + public function getFilamentAvatarUrl(): string + { + /* @phpstan-ignore-next-line */ + return $this->owner->profile_photo_url; + } + + public function getIncrementing() + { + return true; + } + + public static function getCustomColumns(): array + { + return [ + 'id', + 'user_id', + 'name', + 'personal_company', + ]; + } + + public function initialize() + { + tenancy()->initialize($this); + } + + public function end() + { + tenancy()->end(); + } + + /** + * Get the owner of the company. + */ + public function owner(): BelongsTo + { + return $this->belongsTo(FilamentCompanies::userModel(), 'user_id'); + } + + /** + * Get all the company's users including its owner. + */ + public function allUsers(): Collection + { + return $this->users->merge([$this->owner]); + } + + /** + * Get all the users that belong to the company. + */ + public function users(): BelongsToMany + { + return $this->belongsToMany(FilamentCompanies::userModel(), FilamentCompanies::employeeshipModel()) + ->withPivot('role') + ->withTimestamps() + ->as('employeeship'); + } + + /** + * Determine if the given user belongs to the company. + */ + public function hasUser(mixed $user): bool + { + return $this->users->contains($user) || $user->ownsCompany($this); + } + + /** + * Determine if the given email address belongs to a user on the company. + */ + public function hasUserWithEmail(string $email): bool + { + return $this->allUsers()->contains(static function ($user) use ($email) { + return $user->email === $email; + }); + } + + /** + * Determine if the given user has the given permission on the company. + */ + public function userHasPermission(mixed $user, string $permission): bool + { + return $user->hasCompanyPermission($this, $permission); + } + + /** + * Get all the pending user invitations for the company. + */ + public function companyInvitations(): HasMany + { + return $this->hasMany(FilamentCompanies::companyInvitationModel()); + } + + /** + * Remove the given user from the company. + */ + public function removeUser(mixed $user): void + { + if ($user->current_company_id === $this->id) { + $user->forceFill([ + 'current_company_id' => null, + ])->save(); + } + + $this->users()->detach($user); + } + + /** + * Purge all the company's resources. + */ + public function purge(): void + { + $this->owner()->where('current_company_id', $this->id) + ->update(['current_company_id' => null]); + + $this->users()->where('current_company_id', $this->id) + ->update(['current_company_id' => null]); + + $this->users()->detach(); + + $this->delete(); + } +} diff --git a/src/Tenant/CompanyInvitation.php b/src/Tenant/CompanyInvitation.php new file mode 100644 index 0000000..2e8bf0c --- /dev/null +++ b/src/Tenant/CompanyInvitation.php @@ -0,0 +1,28 @@ + + */ + protected $fillable = [ + 'email', + 'role', + ]; + + /** + * Get the company that the invitation belongs to. + */ + public function company(): BelongsTo + { + return $this->belongsTo(FilamentCompanies::companyModel()); + } +} diff --git a/src/Tenant/ConnectedAccount.php b/src/Tenant/ConnectedAccount.php new file mode 100644 index 0000000..5584b20 --- /dev/null +++ b/src/Tenant/ConnectedAccount.php @@ -0,0 +1,42 @@ + + */ + protected $fillable = [ + 'provider', + 'provider_id', + 'name', + 'nickname', + 'email', + 'avatar_path', + 'token', + 'refresh_token', + 'expires_at', + ]; + + /** + * The event map for the model. + * + * @var array + */ + protected $dispatchesEvents = [ + 'created' => ConnectedAccountCreated::class, + 'updated' => ConnectedAccountUpdated::class, + 'deleted' => ConnectedAccountDeleted::class, + ]; +} diff --git a/src/Tenant/Employeeship.php b/src/Tenant/Employeeship.php new file mode 100644 index 0000000..f72b483 --- /dev/null +++ b/src/Tenant/Employeeship.php @@ -0,0 +1,18 @@ +simple() @@ -18,7 +24,7 @@ public function bootingPackage(): void { ])); }); - Company::created(function (Company $company) { + FilamentSaas::getCompanyModel()::created(function (Model $company) { $company->initialize(); $cachePath = storage_path('framework/cache'); @@ -35,6 +41,6 @@ public function bootingPackage(): void { public function configurePackage(Package $package): void { - $package->name('octo.user'); + $package->name('filament-saas.user'); } } diff --git a/src/User/Filament/Components/Phone.php b/src/User/Filament/Components/Phone.php index bf76090..775f5bc 100644 --- a/src/User/Filament/Components/Phone.php +++ b/src/User/Filament/Components/Phone.php @@ -1,19 +1,19 @@ schema([ PhoneInput::make('phone') ->defaultCountry('BR') - ->label(__('octo-core::default.user.register.phone')) - ->unique(Octo::getUserModel(), ignorable: $this->user) + ->label(__('filament-saas::default.user.register.phone')) + ->unique(FilamentSaas::getUserModel(), ignorable: $this->user) ->validateFor( lenient: true, ) @@ -57,7 +57,7 @@ public function submit() Notification::make() ->success() - ->title(__('octo-core::default.user.profile.phone.notify')) + ->title(__('filament-saas::default.user.profile.phone.notify')) ->send(); } } diff --git a/src/User/Filament/Components/Username.php b/src/User/Filament/Components/Username.php index 54b96bf..70f2951 100644 --- a/src/User/Filament/Components/Username.php +++ b/src/User/Filament/Components/Username.php @@ -1,19 +1,18 @@ schema([ TextInput::make('username') - ->label(__('octo-core::default.user.profile.username.title')) + ->label(__('filament-saas::default.user.profile.username.title')) ->prefixIcon('heroicon-m-at-symbol') - ->unique(Octo::getUserModel(), ignorable: $this->user) + ->unique(A2insights\FilamentSaas::getUserModel(), ignorable: $this->user) ->required() ->rules(['required', 'max:100', 'min:4', 'string']), ])->statePath('data'); @@ -55,7 +54,7 @@ public function submit() Notification::make() ->success() - ->title(__('octo-core::default.user.profile.username.notify')) + ->title(__('filament-saas::default.user.profile.username.notify')) ->send(); } } diff --git a/src/User/Filament/Pages/BannedUser.php b/src/User/Filament/Pages/BannedUser.php index f9ca840..1916941 100644 --- a/src/User/Filament/Pages/BannedUser.php +++ b/src/User/Filament/Pages/BannedUser.php @@ -1,6 +1,6 @@ isBanned() || ! Filament::auth()->check()) { - return redirect(config('octo.admin_path')); + return redirect(config('filament-saas.admin_path')); } $this->ban = Auth::user()->bans->first(); @@ -56,7 +56,7 @@ public function logout() session()->invalidate(); session()->regenerateToken(); - return redirect(config('octo.admin_path')); + return redirect(config('filament-saas.admin_path')); } protected function getFormActions(): array diff --git a/src/User/Filament/Pages/CreateUser.php b/src/User/Filament/Pages/CreateUser.php index abf9b8b..ea19a92 100644 --- a/src/User/Filament/Pages/CreateUser.php +++ b/src/User/Filament/Pages/CreateUser.php @@ -1,9 +1,9 @@ label(__('octo-core::default.user.profile.username.title')) + ->label(__('filament-saas::default.user.profile.username.title')) ->prefixIcon('heroicon-m-at-symbol') - ->unique(Octo::getUserModel()) + ->unique(A2insights\FilamentSaas::getUserModel()) ->required() ->rules(['required', 'max:100', 'min:4', 'string']); } private function getTermsFormComponent(): Component { - $html = new HtmlString(trans('octo-core::default.user.register.accept_terms', ['terms_url' => route('terms'), 'policies_url' => route('policy')])); + $html = new HtmlString(trans('filament-saas::default.user.register.accept_terms', ['terms_url' => route('terms'), 'policies_url' => route('policy')])); return Checkbox::make('terms') ->label($html) @@ -76,7 +75,7 @@ private function getTermsFormComponent(): Component private function getPhoneFormComponent(): Component { return PhoneInput::make('phone') - ->label(__('octo-core::default.user.register.phone')) + ->label(__('filament-saas::default.user.register.phone')) ->required(); } } diff --git a/src/User/Filament/Pages/TenantRegister.php b/src/User/Filament/Pages/TenantRegister.php index 9952e76..2b6ce0f 100644 --- a/src/User/Filament/Pages/TenantRegister.php +++ b/src/User/Filament/Pages/TenantRegister.php @@ -1,15 +1,15 @@ label(__('octo-core::default.user.profile.username.title')) + ->label(__('filament-saas::default.user.profile.username.title')) ->prefixIcon('heroicon-m-at-symbol') - ->unique(Octo::getUserModel()) + ->unique(FilamentSaas::getUserModel()) ->required() ->rules(['required', 'max:100', 'min:4', 'string']); } protected function getTermsFormComponent(): Component { - $html = new HtmlString(trans('octo-core::default.user.register.accept_terms', ['terms_url' => route('terms'), 'policies_url' => route('policy')])); + $html = new HtmlString(trans('filament-saas::default.user.register.accept_terms', ['terms_url' => route('terms'), 'policies_url' => route('policy')])); return Checkbox::make('terms') ->label($html) @@ -81,7 +81,7 @@ protected function getTermsFormComponent(): Component private function getPhoneFormComponent(): Component { return PhoneInput::make('phone') - ->label(__('octo-core::default.user.register.phone')) + ->label(__('filament-saas::default.user.register.phone')) ->required(); } } diff --git a/src/User/Filament/Pages/TentantUserProfilePage.php b/src/User/Filament/Pages/TentantUserProfilePage.php index a4adf17..aa52557 100644 --- a/src/User/Filament/Pages/TentantUserProfilePage.php +++ b/src/User/Filament/Pages/TentantUserProfilePage.php @@ -1,6 +1,6 @@ + */ + protected $fillable = [ + 'name', + 'email', + 'phone', + 'username', + 'avatar_url', + 'password', + ]; + + /** + * The attributes that should be hidden for serialization. + * + * @var array + */ + protected $hidden = [ + 'password', + 'remember_token', + ]; + + /** + * Get the attributes that should be cast. + * + * @return array + */ + protected function casts(): array + { + return [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + 'settings' => Settings::class, + ]; + } + + public function canAccessPanel(Panel $panel): bool + { + return true; + } + + public function canAccessTenant(Model $tenant): bool + { + return $this->belongsToCompany($tenant); + } + + public function getFilamentAvatarUrl(): ?string + { + if ($this->avatar_url && config('filament.default_filesystem_disk') === 's3') { + return Storage::disk('avatars')->temporaryUrl( + $this->avatar_url, + now()->addMinutes(60), + ); + } + + return $this->avatar_url ? Storage::url($this->avatar_url) : null; + } + + public function getTenants(Panel $panel): array|Collection + { + return $this->allCompanies(); + } + + public function getDefaultTenant(Panel $panel): ?Model + { + return $this->currentCompany; + } +} diff --git a/src/User/UserObserver.php b/src/User/UserObserver.php deleted file mode 100644 index 8fc4392..0000000 --- a/src/User/UserObserver.php +++ /dev/null @@ -1,24 +0,0 @@ -created_at); - } - - public function deleted(User $user) - { - UserStats::decrease(); - } - - public function restored(User $user) - { - UserStats::increase(1, $user->created_at); - } -} diff --git a/src/User/UserPlugin.php b/src/User/UserPlugin.php index bdff032..dce9bec 100644 --- a/src/User/UserPlugin.php +++ b/src/User/UserPlugin.php @@ -1,11 +1,11 @@ resources([ - config('octo.users.resource', UserResource::class), + config('filament-saas.users.resource', UserResource::class), ]); } } diff --git a/src/User/UserServiceProvider.php b/src/User/UserServiceProvider.php index 452d3b6..e97434b 100644 --- a/src/User/UserServiceProvider.php +++ b/src/User/UserServiceProvider.php @@ -1,15 +1,13 @@ registerLivewireComponents(); Route::get('banned/user', BannedUser::class) ->middleware('web') @@ -38,6 +31,14 @@ public function bootingPackage(): void public function configurePackage(Package $package): void { - $package->name('octo.user'); + $package->name('filament-saas.user'); } + + // public function registerLivewireComponents(): void + // { + // Livewire::component('BannedUser', BannedUser::class); + // Livewire::component('Register', Register::class); + // Livewire::component('phone', Phone::class); + // Livewire::component('username', Username::class); + // } } diff --git a/src/Webhook/Filament/Pages/WebhookHistory.php b/src/Webhook/Filament/Pages/WebhookHistory.php index b344d0d..9769b69 100644 --- a/src/Webhook/Filament/Pages/WebhookHistory.php +++ b/src/Webhook/Filament/Pages/WebhookHistory.php @@ -1,6 +1,6 @@ name('octo.webhook'); + $package->name('filament-saas.webhook'); } } diff --git a/src/helpers.php b/src/helpers.php index d4eb987..a4916a4 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -1,16 +1,16 @@ expect(['dd', 'dump', 'ray']) + ->each->not->toBeUsed(); diff --git a/tests/ExampleTest.php b/tests/ExampleTest.php index 61cd84c..5d36321 100644 --- a/tests/ExampleTest.php +++ b/tests/ExampleTest.php @@ -1,5 +1,5 @@ toBeTrue(); }); diff --git a/tests/Pest.php b/tests/Pest.php index 5949c61..9f7d448 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,45 +1,5 @@ in('Feature'); - -/* -|-------------------------------------------------------------------------- -| Expectations -|-------------------------------------------------------------------------- -| -| When you're writing tests, you often need to check that values meet certain conditions. The -| "expect()" function gives you access to a set of "expectations" methods that you can use -| to assert different things. Of course, you may extend the Expectation API at any time. -| -*/ - -expect()->extend('toBeOne', function () { - return $this->toBe(1); -}); - -/* -|-------------------------------------------------------------------------- -| Functions -|-------------------------------------------------------------------------- -| -| While Pest is very powerful out-of-the-box, you may have some testing code specific to your -| project that you don't want to repeat in every file. Here you can also expose helpers as -| global functions to help you to reduce the number of lines of code in your test files. -| -*/ - -function something() -{ - // .. -} +uses(TestCase::class)->in(__DIR__); diff --git a/tests/TestCase.php b/tests/TestCase.php new file mode 100644 index 0000000..a875700 --- /dev/null +++ b/tests/TestCase.php @@ -0,0 +1,55 @@ + 'A2insights\\FilamentSaas\\Database\\Factories\\'.class_basename($modelName).'Factory' + ); + + $this->registerLivewireComponents(); + } + + protected function getPackageProviders($app) + { + return [ + LivewireServiceProvider::class, + FilamentSaasServiceProvider::class, + ]; + } + + public function getEnvironmentSetUp($app) + { + config()->set('database.default', 'testing'); + + /* + $migration = include __DIR__.'/../database/migrations/create_filament-saas_table.php.stub'; + $migration->up(); + */ + } + + private function registerLivewireComponents(): self + { + Livewire::component('BannedUser', BannedUser::class); + Livewire::component('Register', Register::class); + Livewire::component('phone', Phone::class); + Livewire::component('username', Username::class); + + return $this; + } +} diff --git a/workbench/app/Providers/WorkbenchServiceProvider.php b/workbench/app/Providers/WorkbenchServiceProvider.php new file mode 100644 index 0000000..001d06d --- /dev/null +++ b/workbench/app/Providers/WorkbenchServiceProvider.php @@ -0,0 +1,25 @@ +