diff --git a/.env.example b/.env.example index 309916257..04df77c44 100644 --- a/.env.example +++ b/.env.example @@ -85,6 +85,7 @@ RABBITMQ_HOST=rabbitmq #GRAPHQL CONFIGURATION LIGHTHOUSE_CACHE_ENABLE=false +LIGHTHOUSE_SCHEMA_CACHE_ENABLE=false LIGHTHOUSE_CACHE_VERSION=2 #SEACH CONFIGURATION diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index 8fc653825..ca2197dca 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -13,7 +13,7 @@ jobs: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@v1.4.0 + uses: dependabot/fetch-metadata@v1.6.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/deploy-gcp.yml b/.github/workflows/deploy-gcp.yml index a002ea593..6496e4abd 100644 --- a/.github/workflows/deploy-gcp.yml +++ b/.github/workflows/deploy-gcp.yml @@ -12,6 +12,7 @@ jobs: runs-on: ubuntu-latest environment: ${{ github.ref_name }} permissions: + id-token: write contents: read packages: write steps: @@ -19,12 +20,13 @@ jobs: name: Checkout uses: actions/checkout@v3 - - id: auth - name: "Authenticate to Google Cloud" - uses: "google-github-actions/auth@v1" + - id: 'auth' + name: 'Authenticate to Google Cloud' + uses: 'google-github-actions/auth@v1' with: - credentials_json: "${{ secrets.GOOGLE_CREDENTIALS }}" token_format: 'access_token' + workload_identity_provider: "${{secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}}" + service_account: "${{secrets.GCP_SERVICE_ACCOUNT}}" - name: Login to Artifact Registry uses: docker/login-action@v2 @@ -38,6 +40,7 @@ jobs: uses: docker/build-push-action@v4 with: push: true + file: ${{ github.ref_name }}.Dockerfile tags: | ${{ secrets.GCP_IMAGE_TAG }}:${{ github.run_number }} ${{ secrets.GCP_IMAGE_TAG }}:latest @@ -47,17 +50,20 @@ jobs: environment: ${{ github.ref_name }} needs: Build permissions: + id-token: write contents: read packages: write steps: - name: Checkout repository uses: actions/checkout@v3 - - id: auth - name: "Authenticate to Google Cloud" - uses: "google-github-actions/auth@v1" + - id: 'auth' + name: 'Authenticate to Google Cloud' + uses: 'google-github-actions/auth@v1' with: - credentials_json: "${{ secrets.GOOGLE_CREDENTIALS }}" + token_format: 'access_token' + workload_identity_provider: "${{secrets.GCP_WORKLOAD_IDENTITY_PROVIDER}}" + service_account: "${{secrets.GCP_SERVICE_ACCOUNT}}" - name: 'Set up Cloud SDK' uses: 'google-github-actions/setup-gcloud@v1' diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6140e1353..4f3aba028 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -35,6 +35,7 @@ jobs: region: ${{ secrets.AWS_REGION }} create_repo: true tags: latest,${{ github.run_number }}, + dockerfile: ${{ github.ref_name }}.Dockerfile Deploy: runs-on: ubuntu-latest diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index fb52e3b44..322932853 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -104,29 +104,8 @@ jobs: - name: Install Composer dependencies run: composer install --prefer-dist --no-interaction --no-progress - - name: Run Migrations - run: php artisan migrate - - - name: Run Inventory Migrations - run: php artisan migrate --path database/migrations/Inventory/ --database inventory - - - name: Run Social Migrations - run: php artisan migrate --path database/migrations/Social/ --database social - - - name: Run Guild Migrations - run: php artisan migrate --path database/migrations/Guild/ --database crm - - - name: Run Seeders - run: php artisan db:seed - - - name: Create Role Admin - run: php artisan kanvas:create-role Admin - - - name: Create Role Users - run: php artisan kanvas:create-role Users - - - name: Create Role Agents - run: php artisan kanvas:create-role Agents + - name: Setup Kanvas Ecosystem + run: php artisan kanvas:setup-ecosystem - name: Execute type checking run: vendor/bin/phpstan --configuration="phpstan.src.neon.dist" --xdebug diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fc717016d..523de85e7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -39,11 +39,14 @@ jobs: AWS_DEFAULT_REGION_CICD: ${{ secrets.AWS_DEFAULT_REGION_CICD }} AWS_BUCKET_CICD: ${{ secrets.AWS_BUCKET_CICD }} AWS_URL: ${{ secrets.AWS_URL }} - SCOUT_DRIVER: database MODEL_CACHE_STORE: model MODEL_CACHE_ENABLED: false LIGHTHOUSE_CACHE_ENABLE: true LIGHTHOUSE_CACHE_VERSION: 2 + SCOUT_DRIVER: meilisearch + MEILISEARCH_HOST: http://localhost:7700 + MEILISEARCH_KEY: masterKey + SCOUT_QUEUE: false #APP_DEBUG: true strategy: fail-fast: false @@ -73,6 +76,15 @@ jobs: image: rabbitmq ports: - 5672:5672 + meilisearch: + image: getmeili/meilisearch:latest + env: + MEILI_MASTER_KEY: masterKey + MEILI_NO_ANALYTICS: true + MEILI_ENV: development + MEILI_DB_PATH: data.ms + ports: + - 7700:7700 steps: - uses: actions/checkout@v3 @@ -109,32 +121,8 @@ jobs: - name: Install Composer dependencies run: composer install --prefer-dist --no-interaction --no-progress - - name: Run Migrations - run: php artisan migrate - - - name: Run Inventory Migrations - run: php artisan migrate --path database/migrations/Inventory/ --database inventory - - - name: Run Social Migrations - run: php artisan migrate --path database/migrations/Social/ --database social - - - name: Run Guild Migrations - run: php artisan migrate --path database/migrations/Guild/ --database crm - - - name: Run Seeders - run: php artisan db:seed - - - name: Create Role Admin - run: php artisan kanvas:create-role Admin - - - name: Create Role Users - run: php artisan kanvas:create-role Users - - - name: Create Role Agents - run: php artisan kanvas:create-role Agents - - - name: Set filesystem configs - run: php artisan kanvas:filesystem-setup + - name: Setup Kanvas Ecosystem + run: php artisan kanvas:setup-ecosystem - name: Run Tests if: success() diff --git a/1.x.Dockerfile b/1.x.Dockerfile new file mode 100644 index 000000000..3e5ea75fb --- /dev/null +++ b/1.x.Dockerfile @@ -0,0 +1,21 @@ +FROM mctekk/kanvasapp:8.2-alpine + +# Set working directory +WORKDIR /app + +# Add user for laravel application +RUN addgroup -g 1000 www +RUN adduser -u 1000 -s /bin/sh --disabled-password -G www www + +# Copy code to /var/www +COPY --chown=www:www-data . /app + +RUN composer install --no-dev --optimize-autoloader + +# add root to www group +RUN chmod -R ug+w /app/storage + +RUN cp docker/docker-php-ext-opcache-prod.ini /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini +RUN cp docker/php.ini /usr/local/etc/php/conf.d/zx-app-config.ini + +WORKDIR /var/www/html \ No newline at end of file diff --git a/README.md b/README.md index 77a9d5546..a8527ca27 100644 --- a/README.md +++ b/README.md @@ -44,13 +44,17 @@ Todo: 3. Get inside the php container using ```docker exec -it php bash```. -4. Use the command ```php artisan migrate``` to migrate all kanvas migrations file. +4. Create 3 databases `inventory`, `social`, `crm`, update your .env with the connection info -5. Use the command ```php artisan db:seed --class=DatabaseSeeder``` to seed the database with an app, role and default system modules. +5. Check the .env and setup correctly the `REDIS` parameters and your database connections before running the setup-ecosystem -6. Generate app keys `php artisan key:generate` +6. Use the command ```php artisan kanvas:setup-ecosystem``` to run the kanvas setup -7. To check if the API is working just make a GET request to ```http://localhost:80/v1/``` and see if the response returns ```"Woot Kanvas"``` +7. If you're presenting some errors after running the command from before, drop all the tables from the schema `kanvas_laravel` and run it again + +8. Generate app keys `php artisan key:generate` + +9. To check if the API is working just make a GET request to ```http://localhost:80/v1/``` and see if the response returns ```"Woot Kanvas"``` ### Setup Inventory 1. php artisan migrate --path database/migrations/Inventory/ --database inventory @@ -97,6 +101,7 @@ After doing all the steps above, you could run the project with Laravel Octane b Use `--watch` in development allowing you to refresh modified files , this works assuming to have `npm install chokidar` installed in the project. **** + Note: - To install Swoole you can use the command ```pecl install swoole``` - For production remove `--watch` from the command. diff --git a/app/Console/Commands/CreateRoleCommand.php b/app/Console/Commands/CreateRoleCommand.php index 022993c74..bee21141f 100644 --- a/app/Console/Commands/CreateRoleCommand.php +++ b/app/Console/Commands/CreateRoleCommand.php @@ -4,8 +4,9 @@ namespace App\Console\Commands; -use Bouncer; use Illuminate\Console\Command; +use Kanvas\AccessControlList\Actions\CreateRoleAction; +use Kanvas\Apps\Models\Apps; class CreateRoleCommand extends Command { @@ -14,7 +15,7 @@ class CreateRoleCommand extends Command * * @var string */ - protected $signature = 'kanvas:create-role {name}'; + protected $signature = 'kanvas:create-role {name} {app_id?}'; /** * The console command description. @@ -25,9 +26,15 @@ class CreateRoleCommand extends Command public function handle(): void { - $role = Bouncer::role()->firstOrCreate([ - 'name' => $this->argument('name'), - 'title' => $this->argument('name'), - ]); + $roleName = $this->argument('name'); + $appId = $this->argument('app_id') ?? Apps::first()->getId(); + $createRole = new CreateRoleAction( + $roleName, + $roleName, + Apps::getById($appId) + ); + $createRole->execute(); + + $this->info('Role ' . $roleName . ' created successfully.'); } } diff --git a/app/Console/Commands/GuildSetupCommand.php b/app/Console/Commands/GuildSetupCommand.php index 0c83c1e2b..ee1559c32 100644 --- a/app/Console/Commands/GuildSetupCommand.php +++ b/app/Console/Commands/GuildSetupCommand.php @@ -7,6 +7,7 @@ use Illuminate\Console\Command; use Kanvas\Apps\Models\Apps; use Kanvas\Companies\Models\Companies; +use Kanvas\Guild\Support\Setup; use Kanvas\Users\Models\Users; class GuildSetupCommand extends Command @@ -37,6 +38,11 @@ public function handle() $user = Users::getById((int) $this->argument('user_id')); //todo: add setup class + (new Setup( + $app, + $user, + $company + ))->run(); $this->newLine(); $this->info('Guild setup for Company ' . $company->name . ' completed successful'); diff --git a/app/Console/Commands/KanvasAppSetupCommand.php b/app/Console/Commands/KanvasAppSetupCommand.php index d09d2fce2..23ec238a0 100644 --- a/app/Console/Commands/KanvasAppSetupCommand.php +++ b/app/Console/Commands/KanvasAppSetupCommand.php @@ -16,7 +16,7 @@ class KanvasAppSetupCommand extends Command * * @var string */ - protected $signature = 'kanvas:setup'; + protected $signature = 'kanvas:app-create'; /** * The console command description. diff --git a/app/Console/Commands/KanvasAppUserMigration.php b/app/Console/Commands/KanvasAppUserMigration.php index 6d5a4578c..031932356 100644 --- a/app/Console/Commands/KanvasAppUserMigration.php +++ b/app/Console/Commands/KanvasAppUserMigration.php @@ -8,6 +8,7 @@ use Kanvas\Apps\Models\Apps; use Kanvas\Auth\Actions\RegisterUsersAppAction; use Kanvas\Users\Models\UsersAssociatedApps; +use Throwable; class KanvasAppUserMigration extends Command { @@ -35,13 +36,18 @@ public function handle() $appUid = $this->argument('app_uuid'); $app = Apps::getByUuid($appUid); - $users = UsersAssociatedApps::fromApp($app)->notDeleted()->get(); + $users = UsersAssociatedApps::fromApp($app)->notDeleted()->orderBy('users_id', 'desc')->get(); foreach ($users as $user) { - $userRegisterInApp = new RegisterUsersAppAction( - $user, - $app - ); - $userRegisterInApp->execute($user->password); + try { + $userData = $user->user()->firstOrFail(); + $userRegisterInApp = new RegisterUsersAppAction( + $userData, + $app + ); + $userRegisterInApp->execute($userData->password); + } catch(Throwable $e) { + $this->error('Error creating user : ' . $user->user_id . ' ' . $e->getMessage()); + } } return; diff --git a/app/Console/Commands/KanvasSetupCommand.php b/app/Console/Commands/KanvasSetupCommand.php new file mode 100644 index 000000000..1dc38491d --- /dev/null +++ b/app/Console/Commands/KanvasSetupCommand.php @@ -0,0 +1,67 @@ +info('Some migrations have already been run. Meaning the ecosystem is already setup, Skipping setup.'); + + return; + } + + $commands = [ + 'migrate', + 'migrate --path database/migrations/Inventory/ --database inventory', + 'migrate --path database/migrations/Social/ --database social', + 'migrate --path database/migrations/Guild/ --database crm', + 'db:seed', + 'db:seed --class=Database\\\Seeders\\\GuildSeeder --database crm', + 'kanvas:create-role Admin', + 'kanvas:create-role Users', + 'kanvas:create-role Agents', + 'kanvas:filesystem-setup', + ]; + + foreach ($commands as $command) { + $this->line('Running command: ' . $command); + $exitCode = Artisan::call($command); + + if ($exitCode !== 0) { + $this->error('Command failed: ' . $command); + + break; + } + } + + $this->info('All commands executed successfully - Welcome to Kanvas Ecosystem ' . AppEnums::VERSION->getValue()); + + return; + } +} diff --git a/app/GraphQL/Directives/GuardByAdminDirective.php b/app/GraphQL/Directives/GuardByAdminDirective.php new file mode 100644 index 000000000..9ddb16867 --- /dev/null +++ b/app/GraphQL/Directives/GuardByAdminDirective.php @@ -0,0 +1,50 @@ +wrapResolver( + fn (callable $previousResolver) => function ( + $root, + array $args, + GraphQLContext $context, + ResolveInfo $resolveInfo + ) use ($previousResolver) { + $with = (array) $this->directiveArgValue('with', current(AuthServiceProvider::guards())); + $user = $this->authenticate($with); + + if (! $user->isAn((string) DefaultRoles::ADMIN->getValue())) { + throw new AuthorizationException('You are not authorized to perform this action please contact your administrator'); + } + + return $previousResolver($root, $args, $context, $resolveInfo); + } + ); + } +} diff --git a/app/GraphQL/Ecosystem/Mutations/AccessControlList/AccessControlListManagementMutation.php b/app/GraphQL/Ecosystem/Mutations/AccessControlList/AccessControlListManagementMutation.php deleted file mode 100644 index 52f19abe0..000000000 --- a/app/GraphQL/Ecosystem/Mutations/AccessControlList/AccessControlListManagementMutation.php +++ /dev/null @@ -1,115 +0,0 @@ -user()->defaultCompany->id), - $request['role'] - ); - $assign->execute(); - return true; - } - - /** - * removeRoleFromUser. - * - * @param mixed $rootValue - * @param array $request - * - * @return void - */ - public function removeRoleFromUser(mixed $rootValue, array $request): bool - { - $role = $request['role']; - $user = UsersRepository::getById($request['userId'], auth()->user()->defaultCompany->id); - $user->retract($role); - return true; - } - - /** - * givePermissionToUser. - * - * @param mixed $rootValue - * @param array $request - * - * @return bool - */ - public function givePermissionToUser(mixed $rootValue, array $request): bool - { - $user = UsersRepository::getById($request['userId'], auth()->user()->defaultCompany->id); - Bouncer::allow($user)->to($request['permission']); - return true; - } - - /** - * removePermissionToUser. - * - * @param mixed $rootValue - * @param array $request - * - * @return bool - */ - public function removePermissionToUser(mixed $rootValue, array $request): bool - { - $user = UsersRepository::getById($request['userId'], auth()->user()->defaultCompany->id); - Bouncer::disallow($user)->to($request['permission']); - return true; - } - - /** - * createRole. - * - * @param mixed $rootValue - * @param array $request - * - * @return void - */ - public function createRole(mixed $rootValue, array $request): SilberRole - { - $role = new CreateRoleAction( - $request['name'], - $request['title'] - ); - return $role->execute(Companies::getById(auth()->user()->currentCompanyId())); - } - - /** - * updateRole. - * - * @param mixed $rootValue - * @param array $request - * - * @return void - */ - public function updateRole(mixed $rootValue, array $request): SilberRole - { - $role = new UpdateRoleAction( - $request['id'], - $request['name'], - $request['title'] ?? null - ); - return $role->execute(Companies::getById(auth()->user()->currentCompanyId())); - } -} diff --git a/app/GraphQL/Ecosystem/Mutations/Auth/AuthManagementMutation.php b/app/GraphQL/Ecosystem/Mutations/Auth/AuthManagementMutation.php index 092bf99b3..b9256d63b 100644 --- a/app/GraphQL/Ecosystem/Mutations/Auth/AuthManagementMutation.php +++ b/app/GraphQL/Ecosystem/Mutations/Auth/AuthManagementMutation.php @@ -27,43 +27,6 @@ class AuthManagementMutation use TokenTrait; use AuthTrait; - /** - * @param array $args - * - * @throws \Exception - */ - public function forgot( - mixed $rootValue, - array $request, - GraphQLContext $context = null, - ResolveInfo $resolveInfo - ): bool { - $user = new ForgotPasswordService(); - - $registeredUser = $user->forgot($request['data']['email']); - $tokenResponse = $registeredUser->createToken('kanvas-login')->toArray(); - - $request = request(); - - return true; - } - - /** - * Reset user password. - */ - public function reset( - mixed $rootValue, - array $request, - GraphQLContext $context = null, - ResolveInfo $resolveInfo - ): bool { - $user = new ForgotPasswordService(); - - $user->reset($request['data']['new_password'], $request['data']['hash_key']); - - return true; - } - /** * @param array $args * @@ -193,4 +156,41 @@ public function socialLogin(mixed $root, array $req): array return $tokenResponse; } + + /** + * @param array $args + * + * @throws \Exception + */ + public function forgot( + mixed $rootValue, + array $request, + GraphQLContext $context = null, + ResolveInfo $resolveInfo + ): bool { + $user = new ForgotPasswordService(); + + $registeredUser = $user->forgot($request['data']['email']); + $tokenResponse = $registeredUser->createToken('kanvas-login')->toArray(); + + $request = request(); + + return true; + } + + /** + * Reset user password. + */ + public function reset( + mixed $rootValue, + array $request, + GraphQLContext $context = null, + ResolveInfo $resolveInfo + ): bool { + $user = new ForgotPasswordService(); + + $user->reset($request['data']['new_password'], $request['data']['hash_key']); + + return true; + } } diff --git a/app/GraphQL/Ecosystem/Mutations/CustomFields/CustomFieldMutation.php b/app/GraphQL/Ecosystem/Mutations/CustomFields/CustomFieldMutation.php index f1c6a9c4b..2e716ba17 100644 --- a/app/GraphQL/Ecosystem/Mutations/CustomFields/CustomFieldMutation.php +++ b/app/GraphQL/Ecosystem/Mutations/CustomFields/CustomFieldMutation.php @@ -32,7 +32,7 @@ public function create(mixed $rootValue, array $request): bool } /** - * Get custom field + * @deprecated use query */ public function get(mixed $rootValue, array $request): mixed { @@ -50,7 +50,7 @@ public function get(mixed $rootValue, array $request): mixed } /** - * Get custom field + * @deprecated use query */ public function getAll(mixed $rootValue, array $request): array { diff --git a/app/GraphQL/Ecosystem/Mutations/Roles/RolesManagementMutation.php b/app/GraphQL/Ecosystem/Mutations/Roles/RolesManagementMutation.php new file mode 100644 index 000000000..33ef741ef --- /dev/null +++ b/app/GraphQL/Ecosystem/Mutations/Roles/RolesManagementMutation.php @@ -0,0 +1,107 @@ +user()->getCurrentCompany(), + (int) $request['userId'] + ), + $role + ); + $assign->execute(); + + return true; + } + + /** + * removeRoleFromUser. + */ + public function removeRoleFromUser(mixed $rootValue, array $request): bool + { + $role = RolesRepository::getByMixedParamFromCompany($request['role']); + + $user = UsersRepository::getUserOfCompanyById( + auth()->user()->getCurrentCompany(), + (int) $request['userId'] + ); + $user->retract($role->name); + + return true; + } + + /** + * givePermissionToUser. + */ + public function givePermissionToUser(mixed $rootValue, array $request): bool + { + $user = UsersRepository::getUserOfCompanyById( + auth()->user()->getCurrentCompany(), + (int) $request['userId'] + ); + Bouncer::allow($user)->to(Str::slug($request['permission'])); + + return true; + } + + /** + * removePermissionToUser. + */ + public function removePermissionToUser(mixed $rootValue, array $request): bool + { + $user = UsersRepository::getUserOfCompanyById( + auth()->user()->getCurrentCompany(), + (int) $request['userId'] + ); + Bouncer::disallow($user)->to($request['permission']); + + return true; + } + + /** + * createRole. + */ + public function createRole(mixed $rootValue, array $request): SilberRole + { + $role = new CreateRoleAction( + $request['name'], + $request['title'] + ); + + return $role->execute(auth()->user()->getCurrentCompany()); + } + + /** + * updateRole. + */ + public function updateRole(mixed $rootValue, array $request): SilberRole + { + $role = new UpdateRoleAction( + $request['id'], + $request['name'], + $request['title'] ?? null + ); + + return $role->execute(auth()->user()->getCurrentCompany()); + } +} diff --git a/app/GraphQL/Ecosystem/Mutations/Users/UserDeviceMutation.php b/app/GraphQL/Ecosystem/Mutations/Users/UserDeviceMutation.php new file mode 100644 index 000000000..5cecf76d0 --- /dev/null +++ b/app/GraphQL/Ecosystem/Mutations/Users/UserDeviceMutation.php @@ -0,0 +1,47 @@ +firstOrFail(); + $user = auth()->user(); + + UserLinkedSources::updateOrCreate([ + 'users_id' => $user->getId(), + 'source_id' => $source->getId(), + 'source_users_id_text' => $req['device_id'], + ], [ + 'source_users_id' => $user->getId(), + 'source_username' => $user->displayname . ' ' . $source->title, + 'is_deleted' => 0, + ]); + + return true; + } + + public function remove(mixed $root, array $req): bool + { + $req = $req['data']; + $source = Sources::where('title', $req['source_site'])->firstOrFail(); + $user = auth()->user(); + + return (bool) UserLinkedSources::where('users_id', $user->getId()) + ->where('source_id', $source->getId()) + ->where('source_users_id_text', $req['device_id']) + ->update([ + 'is_deleted' => 1, + ]); + } +} diff --git a/app/GraphQL/Ecosystem/Mutations/Users/UserManagementMutation.php b/app/GraphQL/Ecosystem/Mutations/Users/UserManagementMutation.php index 4f50059da..32a6b136d 100644 --- a/app/GraphQL/Ecosystem/Mutations/Users/UserManagementMutation.php +++ b/app/GraphQL/Ecosystem/Mutations/Users/UserManagementMutation.php @@ -8,24 +8,19 @@ use Illuminate\Support\Facades\Hash; use Kanvas\Auth\Services\UserManagement as UserManagementService; use Kanvas\Notifications\Templates\ChangePasswordUserLogged; -use Kanvas\Users\Models\Users; -use Kanvas\Users\Repositories\UsersRepository; use Kanvas\Users\Actions\CreateInviteAction; +use Kanvas\Users\Actions\ProcessInviteAction; +use Kanvas\Users\DataTransferObject\CompleteInviteInput; use Kanvas\Users\DataTransferObject\Invite as InviteDto; +use Kanvas\Users\Models\Users; use Kanvas\Users\Models\UsersInvite; use Kanvas\Users\Repositories\UsersInviteRepository; -use Kanvas\Users\Actions\ProcessInviteAction; -use Kanvas\Users\DataTransferObject\CompleteInviteInput; +use Kanvas\Users\Repositories\UsersRepository; class UserManagementMutation { /** * changePassword. - * - * @param mixed $root - * @param array $req - * - * @return bool */ public function changePassword(mixed $root, array $req): bool { @@ -39,15 +34,14 @@ public function changePassword(mixed $root, array $req): bool /** * Update user information. - * - * @param mixed $rootValue - * @param array $request - * - * @return Users */ public function updateUser(mixed $rootValue, array $request): Users { - $userManagement = new UserManagementService(Users::getById(auth()->user()->id)); + $user = auth()->user(); + $userId = $user->isAppOwner() && (int) $request['id'] > 0 ? $request['id'] : $user->getId(); + $userToEdit = UsersRepository::getUserOfCompanyById($user->getCurrentCompany(), $userId); + + $userManagement = new UserManagementService($userToEdit); $user = $userManagement->update($request['data']); return $user; @@ -57,9 +51,6 @@ public function updateUser(mixed $rootValue, array $request): Users * insertInvite. * * @param mixed $rootValue - * @param array $request - * - * @return UsersInvite */ public function insertInvite($rootValue, array $request): UsersInvite { @@ -75,6 +66,7 @@ public function insertInvite($rootValue, array $request): UsersInvite ), auth()->user() ); + return $invite->execute(); } @@ -82,9 +74,6 @@ public function insertInvite($rootValue, array $request): UsersInvite * deleteInvite. * * @param mixed $rootValue - * @param array $request - * - * @return bool */ public function deleteInvite($rootValue, array $request): bool { @@ -94,6 +83,7 @@ public function deleteInvite($rootValue, array $request): bool ); $invite->softDelete(); + return true; } @@ -101,9 +91,6 @@ public function deleteInvite($rootValue, array $request): bool * processInvite. * * @param mixed $rootValue - * @param array $request - * - * @return UsersInvite */ public function getInvite($rootValue, array $request): UsersInvite { @@ -115,15 +102,13 @@ public function getInvite($rootValue, array $request): UsersInvite * Process User invite. * * @param mixed $rootValue - * @param array $request - * - * @return Users */ public function process($rootValue, array $request): Users { $action = new ProcessInviteAction( CompleteInviteInput::from($request['input']) ); + return $action->execute(); } } diff --git a/app/GraphQL/Ecosystem/Queries/Apps/AppUserManagement.php b/app/GraphQL/Ecosystem/Queries/Apps/AppUserManagementQuery.php similarity index 89% rename from app/GraphQL/Ecosystem/Queries/Apps/AppUserManagement.php rename to app/GraphQL/Ecosystem/Queries/Apps/AppUserManagementQuery.php index 9dd667dcf..d4daed5d1 100644 --- a/app/GraphQL/Ecosystem/Queries/Apps/AppUserManagement.php +++ b/app/GraphQL/Ecosystem/Queries/Apps/AppUserManagementQuery.php @@ -11,20 +11,17 @@ use Kanvas\Users\Models\Users; use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; -class AppUserManagement +class AppUserManagementQuery { /** * all. - * - * @param mixed $root - * @param array $args - * @param GraphQLContext $context - * @param ResolveInfo $resolveInfo - * - * @return Builder */ - public function getAllAppUsers(mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): Builder - { + public function getAllAppUsers( + mixed $root, + array $args, + GraphQLContext $context, + ResolveInfo $resolveInfo + ): Builder { /** * @var Builder */ diff --git a/app/GraphQL/Ecosystem/Queries/Apps/AppsList.php b/app/GraphQL/Ecosystem/Queries/Apps/AppsListQuery.php similarity index 96% rename from app/GraphQL/Ecosystem/Queries/Apps/AppsList.php rename to app/GraphQL/Ecosystem/Queries/Apps/AppsListQuery.php index 82d19c53d..15427f9bc 100644 --- a/app/GraphQL/Ecosystem/Queries/Apps/AppsList.php +++ b/app/GraphQL/Ecosystem/Queries/Apps/AppsListQuery.php @@ -6,7 +6,7 @@ use Kanvas\Apps\Repositories\AppsRepository; -class AppsList +class AppsListQuery { /** * Get user from the current company. diff --git a/app/GraphQL/Ecosystem/Queries/Companies/CompanySettings.php b/app/GraphQL/Ecosystem/Queries/Companies/CompanySettingQuery.php similarity index 95% rename from app/GraphQL/Ecosystem/Queries/Companies/CompanySettings.php rename to app/GraphQL/Ecosystem/Queries/Companies/CompanySettingQuery.php index f13e7e23f..7df91a063 100644 --- a/app/GraphQL/Ecosystem/Queries/Companies/CompanySettings.php +++ b/app/GraphQL/Ecosystem/Queries/Companies/CompanySettingQuery.php @@ -4,7 +4,7 @@ namespace App\GraphQL\Ecosystem\Queries\Companies; -class CompanySettings +class CompanySettingQuery { /** * Get user from the current company. diff --git a/app/GraphQL/Ecosystem/Queries/Companies/UserManagement.php b/app/GraphQL/Ecosystem/Queries/Companies/UserManagementQuery.php similarity index 98% rename from app/GraphQL/Ecosystem/Queries/Companies/UserManagement.php rename to app/GraphQL/Ecosystem/Queries/Companies/UserManagementQuery.php index 097a43801..03cccd98b 100644 --- a/app/GraphQL/Ecosystem/Queries/Companies/UserManagement.php +++ b/app/GraphQL/Ecosystem/Queries/Companies/UserManagementQuery.php @@ -10,7 +10,7 @@ use Kanvas\Users\Models\Users; use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; -class UserManagement +class UserManagementQuery { /** * all. diff --git a/app/GraphQL/Ecosystem/Queries/CustomFields/CustomFieldQueries.php b/app/GraphQL/Ecosystem/Queries/CustomFields/CustomFieldQueries.php deleted file mode 100644 index 05597dde9..000000000 --- a/app/GraphQL/Ecosystem/Queries/CustomFields/CustomFieldQueries.php +++ /dev/null @@ -1,38 +0,0 @@ -getKey()) - ->where('model_name', '=', $root::class) - ->where('is_deleted', '=', StateEnums::NO->getValue()); - - //@todo allow to share media between company only of it the apps specifies it - $files->when(isset($root->companies_id), function ($query) use ($root) { - $query->where('companies_id', $root->companies_id); - }); - - return $files; - } -} diff --git a/app/GraphQL/Ecosystem/Queries/CustomFields/CustomFieldQuery.php b/app/GraphQL/Ecosystem/Queries/CustomFields/CustomFieldQuery.php new file mode 100644 index 000000000..2b88ae30d --- /dev/null +++ b/app/GraphQL/Ecosystem/Queries/CustomFields/CustomFieldQuery.php @@ -0,0 +1,81 @@ +getKey()) + ->where('model_name', '=', $root::class) + ->where('is_deleted', '=', StateEnums::NO->getValue()); + + //@todo allow to share media between company only of it the apps specifies it + $customFields->when(isset($root->companies_id), function ($query) use ($root) { + $query->where('companies_id', $root->companies_id); + }); + + return $customFields; + } + + /** + * Get custom field + */ + public function get(mixed $rootValue, array $request): mixed + { + $customFieldInput = new CustomFieldInput( + $request['name'], + $request['system_module_uuid'], + $request['entity_id'] + ); + + $entity = SystemModulesRepository::getEntityFromInput($customFieldInput, auth()->user()); + + if (method_exists($entity, 'get')) { + return $entity->get( + $customFieldInput->name + ); + } + + return null; + } + + /** + * Get custom field + */ + public function getAll(mixed $rootValue, array $request): array + { + $customFieldInput = new CustomFieldInput( + $request['name'], + $request['system_module_uuid'], + $request['entity_id'] + ); + $entity = SystemModulesRepository::getEntityFromInput($customFieldInput, auth()->user()); + + if (method_exists($entity, 'getAll')) { + return $entity->getAll(); + } + + return []; + } +} diff --git a/app/GraphQL/Ecosystem/Queries/CustomFields/HashFieldsQuery.php b/app/GraphQL/Ecosystem/Queries/CustomFields/HashFieldsQuery.php new file mode 100644 index 000000000..fd8dec753 --- /dev/null +++ b/app/GraphQL/Ecosystem/Queries/CustomFields/HashFieldsQuery.php @@ -0,0 +1,33 @@ +getKey()); + } else { + $customFields = CompaniesSettings::where('companies_id', '=', $root->getKey()); + } + + return $customFields; + } +} diff --git a/app/GraphQL/Ecosystem/Queries/Filesystem/FilesystemQueries.php b/app/GraphQL/Ecosystem/Queries/Filesystem/FilesystemQuery.php similarity index 99% rename from app/GraphQL/Ecosystem/Queries/Filesystem/FilesystemQueries.php rename to app/GraphQL/Ecosystem/Queries/Filesystem/FilesystemQuery.php index 45e757674..50fa6895c 100644 --- a/app/GraphQL/Ecosystem/Queries/Filesystem/FilesystemQueries.php +++ b/app/GraphQL/Ecosystem/Queries/Filesystem/FilesystemQuery.php @@ -12,7 +12,7 @@ use Kanvas\SystemModules\Repositories\SystemModulesRepository; use Nuwave\Lighthouse\Support\Contracts\GraphQLContext; -class FilesystemQueries +class FilesystemQuery { /** * Get all file from a entity tied to the graph diff --git a/app/GraphQL/Ecosystem/Queries/AccessControlList/AccessControlList.php b/app/GraphQL/Ecosystem/Queries/Roles/RoleAbilitiesQuery.php similarity index 56% rename from app/GraphQL/Ecosystem/Queries/AccessControlList/AccessControlList.php rename to app/GraphQL/Ecosystem/Queries/Roles/RoleAbilitiesQuery.php index 3f1da209d..db64d2b95 100644 --- a/app/GraphQL/Ecosystem/Queries/AccessControlList/AccessControlList.php +++ b/app/GraphQL/Ecosystem/Queries/Roles/RoleAbilitiesQuery.php @@ -2,19 +2,19 @@ declare(strict_types=1); -namespace App\GraphQL\Ecosystem\Queries\AccessControlList; +namespace App\GraphQL\Ecosystem\Queries\Roles; use Kanvas\Users\Repositories\UsersRepository; -class AccessControlList +class RoleAbilitiesQuery { - /** - * getAllAbilities - - * */ public function getAllAbilities(mixed $root, array $query): array { - $abilities = UsersRepository::getById($query['userId'], auth()->user()->defaultCompany->id)->getAbilities(); + $abilities = UsersRepository::getUserOfCompanyById( + auth()->user()->defaultCompany, + $query['userId'] + )->getAbilities(); + $mapAbilities = $abilities->map(function ($ability) { return $ability->name; }); diff --git a/app/GraphQL/Ecosystem/Queries/Roles/RolePermissionQuery.php b/app/GraphQL/Ecosystem/Queries/Roles/RolePermissionQuery.php new file mode 100644 index 000000000..b45fc200a --- /dev/null +++ b/app/GraphQL/Ecosystem/Queries/Roles/RolePermissionQuery.php @@ -0,0 +1,25 @@ +user()->getCurrentCompany(), $request['userId']); + + if ($user->isAn((string) DefaultRoles::ADMIN->getValue())) { + return true; + } + + return $user->can($request['permission']); + } +} diff --git a/app/GraphQL/Ecosystem/Resolvers/AccessControlList/RolesResolver.php b/app/GraphQL/Ecosystem/Queries/Roles/RoleQuery.php similarity index 55% rename from app/GraphQL/Ecosystem/Resolvers/AccessControlList/RolesResolver.php rename to app/GraphQL/Ecosystem/Queries/Roles/RoleQuery.php index f6c5bb3d3..5e317f18a 100644 --- a/app/GraphQL/Ecosystem/Resolvers/AccessControlList/RolesResolver.php +++ b/app/GraphQL/Ecosystem/Queries/Roles/RoleQuery.php @@ -2,18 +2,16 @@ declare(strict_types=1); -namespace App\GraphQL\Ecosystem\Resolvers\AccessControlList; +namespace App\GraphQL\Ecosystem\Queries\Roles; use Illuminate\Database\Eloquent\Collection; use Kanvas\AccessControlList\Repositories\RolesRepository; use Kanvas\Users\Repositories\UsersRepository; -class RolesResolver +class RoleQuery { /** * getAllRoles. - * - * @return Collection */ public function getAllRoles(): ?Collection { @@ -22,15 +20,16 @@ public function getAllRoles(): ?Collection /** * hasRole. - * - * @param mixed $_ - * @param array $request - * - * @return bool */ public function hasRole(mixed $_, array $request): bool { - $user = UsersRepository::getById($request['userId'], auth()->user()->defaultCompany->id); - return $user->isAn($request['role']); + $role = RolesRepository::getByMixedParamFromCompany($request['role']); + + $user = UsersRepository::getUserOfCompanyById( + auth()->user()->getCurrentCompany(), + $request['userId'] + ); + + return $user->isAn($role->name); } } diff --git a/app/GraphQL/Ecosystem/Queries/Users/UsersList.php b/app/GraphQL/Ecosystem/Queries/Users/UsersListQuery.php similarity index 86% rename from app/GraphQL/Ecosystem/Queries/Users/UsersList.php rename to app/GraphQL/Ecosystem/Queries/Users/UsersListQuery.php index f424c3b04..a669b13e8 100644 --- a/app/GraphQL/Ecosystem/Queries/Users/UsersList.php +++ b/app/GraphQL/Ecosystem/Queries/Users/UsersListQuery.php @@ -7,15 +7,12 @@ use Kanvas\Users\Models\Users; use Kanvas\Users\Repositories\UsersRepository; -final class UsersList +class UsersListQuery { /** * Get user from the current company. * * @param mixed $rootValue - * @param array $request - * - * @return Users */ public function getFromCurrentCompany($rootValue, array $request): Users { diff --git a/app/GraphQL/Ecosystem/Resolvers/AccessControlList/PermissionsResolver.php b/app/GraphQL/Ecosystem/Resolvers/AccessControlList/PermissionsResolver.php deleted file mode 100644 index dd4373338..000000000 --- a/app/GraphQL/Ecosystem/Resolvers/AccessControlList/PermissionsResolver.php +++ /dev/null @@ -1,24 +0,0 @@ -user()->defaultCompany->id); - return $user->can($request['permission']); - } -} diff --git a/app/GraphQL/Guild/Mutations/Leads/LeadManagementMutation.php b/app/GraphQL/Guild/Mutations/Leads/LeadManagementMutation.php new file mode 100644 index 000000000..537958c42 --- /dev/null +++ b/app/GraphQL/Guild/Mutations/Leads/LeadManagementMutation.php @@ -0,0 +1,89 @@ +user(); + $leadAttempt = new CreateLeadAttemptAction( + $req, + request()->headers->all(), + $user->getCurrentCompany(), + request()->ip(), + 'API' + ); + $attempt = $leadAttempt->execute(); + + $createLead = new CreateLeadAction( + Lead::viaRequest($user, $req['input']), + $attempt + ); + $lead = $createLead->execute(); + + return $lead; + } + + public function update(mixed $root, array $req): ModelsLead + { + $user = auth()->user(); + + $lead = ModelsLead::getByIdFromBranch( + $req['id'], + $user->getCurrentBranch() + ); + + $leadAttempt = new CreateLeadAttemptAction( + $req, + request()->headers->all(), + $user->getCurrentCompany(), + request()->ip(), + 'API - Update' + ); + $attempt = $leadAttempt->execute(); + + $leadInputData = LeadUpdateInput::from($req['input']); + $updateLeadAction = new UpdateLeadAction( + $lead, + $leadInputData, + $user, + $attempt + ); + + return $updateLeadAction->execute(); + } + + public function delete(mixed $root, array $req): bool + { + $user = auth()->user(); + $lead = ModelsLead::getByIdFromBranch( + $req['id'], + $user->getCurrentBranch() + ); + + return $lead->softDelete(); + } + + public function restore(mixed $root, array $req): bool + { + $user = auth()->user(); + $lead = ModelsLead::where('id', $req['id']) + ->where('companies_branches_id', $user->getCurrentBranch()->getId()) + ->firstOrFail(); + + return $lead->restoreRecord(); + } +} diff --git a/app/GraphQL/Guild/Mutations/Leads/Participants.php b/app/GraphQL/Guild/Mutations/Leads/ParticipantMutation.php similarity index 81% rename from app/GraphQL/Guild/Mutations/Leads/Participants.php rename to app/GraphQL/Guild/Mutations/Leads/ParticipantMutation.php index c1bd328be..e627b744d 100644 --- a/app/GraphQL/Guild/Mutations/Leads/Participants.php +++ b/app/GraphQL/Guild/Mutations/Leads/ParticipantMutation.php @@ -8,15 +8,10 @@ use Kanvas\Guild\Leads\Actions\RemoveLeadParticipantAction; use Kanvas\Guild\Leads\DataTransferObject\LeadsParticipant; -class Participants +class ParticipantMutation { /** * Add participant to a lead. - * - * @param mixed $root - * @param array $req - * - * @return bool */ public function add(mixed $root, array $req): bool { @@ -29,11 +24,6 @@ public function add(mixed $root, array $req): bool /** * Remove participant - * - * @param mixed $root - * @param array $req - * - * @return bool */ public function remove(mixed $root, array $req): bool { diff --git a/app/GraphQL/Guild/Mutations/Organizations/OrganizationManagementMutation.php b/app/GraphQL/Guild/Mutations/Organizations/OrganizationManagementMutation.php new file mode 100644 index 000000000..fe7a787bc --- /dev/null +++ b/app/GraphQL/Guild/Mutations/Organizations/OrganizationManagementMutation.php @@ -0,0 +1,72 @@ +user(); + $data = $req['input']; + + $organizationData = new DataTransferObjectOrganization( + $user->getCurrentCompany(), + $user, + $data['name'], + $data['address'] ?? null + ); + + $createOrganization = new CreateOrganizationAction($organizationData); + + return $createOrganization->execute(); + } + + public function update(mixed $root, array $req): Organization + { + $user = auth()->user(); + $data = $req['input']; + + $organization = Organization::getByIdFromCompany((int) $req['id'], $user->getCurrentCompany()); + + $organizationData = new DataTransferObjectOrganization( + $user->getCurrentCompany(), + $user, + $data['name'], + $data['address'] ?? null + ); + + $createOrganization = new UpdateOrganizationAction($organization, $organizationData); + + return $createOrganization->execute(); + } + + public function delete(mixed $root, array $req): bool + { + $user = auth()->user(); + + $organization = Organization::getByIdFromCompany((int) $req['id'], $user->getCurrentCompany()); + + return $organization->softDelete(); + } + + public function restore(mixed $root, array $req): bool + { + $user = auth()->user(); + + $organization = Organization::where('id', (int) $req['id']) + ->where('companies_id', $user->getCurrentCompany()->getId()) + ->firstOrFail(); + + return $organization->restoreRecord(); + } +} diff --git a/app/GraphQL/Guild/Mutations/Organizations/PeopleOrganizationMutation.php b/app/GraphQL/Guild/Mutations/Organizations/PeopleOrganizationMutation.php new file mode 100644 index 000000000..f9215df6f --- /dev/null +++ b/app/GraphQL/Guild/Mutations/Organizations/PeopleOrganizationMutation.php @@ -0,0 +1,51 @@ +user(); + $data = $req['input']; + + $total = 0; + + $organization = Organization::getByIdFromCompany((int) $data['organization_id'], $user->getCurrentCompany()); + foreach ($data['peoples_id'] as $peopleId) { + $people = People::getByIdFromCompany($peopleId, $user->getCurrentCompany()); + + $organization->addPeople($people); + $total++; + } + + return $total > 0; + } + + public function remove(mixed $root, array $req): bool + { + $user = auth()->user(); + $data = $req['input']; + + $total = 0; + $organization = Organization::getByIdFromCompany((int) $data['organization_id'], $user->getCurrentCompany()); + + foreach ($data['peoples_id'] as $peopleId) { + $people = People::getByIdFromCompany($peopleId, $user->getCurrentCompany()); + + OrganizationPeople::where('organizations_id', $organization->getId()) + ->where('peoples_id', $people->getId()) + ->delete(); + + $total++; + } + + return $total > 0; + } +} diff --git a/app/GraphQL/Guild/Mutations/Peoples/PeopleManagementMutation.php b/app/GraphQL/Guild/Mutations/Peoples/PeopleManagementMutation.php new file mode 100644 index 000000000..40f88affe --- /dev/null +++ b/app/GraphQL/Guild/Mutations/Peoples/PeopleManagementMutation.php @@ -0,0 +1,100 @@ +user(); + $data = $req['input']; + + $people = People::from([ + 'app' => app(Apps::class), + 'branch' => $user->getCurrentBranch(), + 'user' => $user, + 'firstname' => $data['firstname'], + 'lastname' => $data['lastname'], + 'contacts' => Contact::collection($data['contacts']), + 'address' => Address::collection($data['address']), + 'id' => $data['id'] ?? 0, + 'dob' => $data['dob'] ?? null, + 'facebook_contact_id' => $data['facebook_contact_id'] ?? null, + 'google_contact_id' => $data['google_contact_id'] ?? null, + 'apple_contact_id' => $data['apple_contact_id'] ?? null, + 'linkedin_contact_id' => $data['linkedin_contact_id'] ?? null, + ]); + + $createPeople = new CreatePeopleAction($people); + + return $createPeople->execute(); + } + + public function update(mixed $root, array $req): ModelsPeople + { + $user = auth()->user(); + $data = $req['input']; + + $people = PeoplesRepository::getById((int) $req['id'], $user->getCurrentCompany()); + + $peopleData = People::from([ + 'app' => app(Apps::class), + 'branch' => $user->getCurrentBranch(), + 'user' => $user, + 'firstname' => $data['firstname'], + 'lastname' => $data['lastname'], + 'contacts' => Contact::collection($data['contacts']), + 'address' => Address::collection($data['address']), + 'id' => $people->getId(), + 'dob' => $data['dob'] ?? null, + 'facebook_contact_id' => $data['facebook_contact_id'] ?? null, + 'google_contact_id' => $data['google_contact_id'] ?? null, + 'apple_contact_id' => $data['apple_contact_id'] ?? null, + 'linkedin_contact_id' => $data['linkedin_contact_id'] ?? null, + ]); + + $updatePeople = new UpdatePeopleAction($people, $peopleData); + + return $updatePeople->execute(); + } + + /** + * @psalm-suppress MixedReturnStatement + */ + public function delete(mixed $root, array $req): bool + { + $user = auth()->user(); + + return PeoplesRepository::getById( + (int) $req['id'], + $user->getCurrentCompany() + )->softDelete(); + } + + /** + * @psalm-suppress MixedReturnStatement + */ + public function restore(mixed $root, array $req): bool + { + $user = auth()->user(); + + return ModelsPeople::where('id', (int) $req['id']) + ->where('companies_id', $user->getCurrentCompany()->getId()) + ->firstOrFail()->restoreRecord(); + } +} diff --git a/app/GraphQL/Inventory/Mutations/Attributes/Attributes.php b/app/GraphQL/Inventory/Mutations/Attributes/AttributeMutation.php similarity index 85% rename from app/GraphQL/Inventory/Mutations/Attributes/Attributes.php rename to app/GraphQL/Inventory/Mutations/Attributes/AttributeMutation.php index b72a95b7c..7c4c6b08b 100644 --- a/app/GraphQL/Inventory/Mutations/Attributes/Attributes.php +++ b/app/GraphQL/Inventory/Mutations/Attributes/AttributeMutation.php @@ -4,12 +4,13 @@ namespace App\GraphQL\Inventory\Mutations\Attributes; +use Kanvas\Inventory\Attributes\Actions\AddAttributeValue; use Kanvas\Inventory\Attributes\Actions\CreateAttribute; use Kanvas\Inventory\Attributes\DataTransferObject\Attributes as AttributeDto; use Kanvas\Inventory\Attributes\Models\Attributes as AttributeModel; use Kanvas\Inventory\Attributes\Repositories\AttributesRepository; -class Attributes +class AttributeMutation { /** * create. @@ -23,7 +24,11 @@ public function create(mixed $root, array $req): AttributeModel { $dto = AttributeDto::viaRequest($req['input']); $action = new CreateAttribute($dto, auth()->user()); - return $action->execute(); + $attributeModel = $action->execute(); + + (new AddAttributeValue($attributeModel, $dto->value))->execute(); + + return $attributeModel; } /** diff --git a/app/GraphQL/Social/Builders/Follows/GetFollowersBuilder.php b/app/GraphQL/Social/Builders/Follows/GetFollowersBuilder.php index 1916c2a79..528ffec1a 100644 --- a/app/GraphQL/Social/Builders/Follows/GetFollowersBuilder.php +++ b/app/GraphQL/Social/Builders/Follows/GetFollowersBuilder.php @@ -1,6 +1,6 @@ where('is_public', $req['is_public'] ?? true) + ->where('apps_id', app(Apps::class)->id); + + return $search; + } +} diff --git a/app/GraphQL/Social/Mutations/Messages/MessageManagementMutation.php b/app/GraphQL/Social/Mutations/Messages/MessageManagementMutation.php new file mode 100644 index 000000000..f74f287a1 --- /dev/null +++ b/app/GraphQL/Social/Mutations/Messages/MessageManagementMutation.php @@ -0,0 +1,56 @@ +id : 0; + $request['input']['parent_unique_id'] = $parent?->uuid; + $request['input']['apps_id'] = app(Apps::class)->id; + $request['input']['companies_id'] = auth()->user()->getCurrentCompany()->getId(); + $request['input']['users_id'] = auth()->user()->id; + $data = MessageInput::from($request['input']); + $action = new CreateMessageAction($data, $systemModule, $request['input']['entity_id']); + $message = $action->execute(); + $activity = []; + + $activityType = UserMessageActivityType::where('name', 'follow')->firstOrFail(); + $activity = [ + 'username' => '', + 'entity_namespace' => '', + 'text' => ' ', + 'type' => $activityType->id, + ]; + + FillUserMessage::dispatch($message, $message->user, $activity)->onQueue('message'); + + return $message; + } +} diff --git a/app/GraphQL/Social/Mutations/Messages/MessagesTypesMutation.php b/app/GraphQL/Social/Mutations/Messages/MessagesTypesMutation.php new file mode 100644 index 000000000..55dfabe51 --- /dev/null +++ b/app/GraphQL/Social/Mutations/Messages/MessagesTypesMutation.php @@ -0,0 +1,46 @@ +id; + $messageTypeInput = MessageTypeInput::from($request['input']); + $createMessageTypesAction = new CreateMessageTypeAction( + $messageTypeInput + ); + + return $createMessageTypesAction->execute(); + } + + /** + * update + * + * @param mixed $request + */ + public function update(mixed $root, array $request): MessageType + { + Languages::getById($request['input']['languages_id']); + $messageType = MessagesTypesRepository::getById($request['id']); + $messageType->update($request['input']); + + return $messageType; + } +} diff --git a/app/GraphQL/Social/Mutations/UsersLists/UsersListsManagement.php b/app/GraphQL/Social/Mutations/UsersLists/UsersListsManagement.php new file mode 100644 index 000000000..846cf4dfa --- /dev/null +++ b/app/GraphQL/Social/Mutations/UsersLists/UsersListsManagement.php @@ -0,0 +1,70 @@ +id, + auth()->user()->getCurrentCompany()->id, + auth()->user()->id, + $req['input']['name'], + $req['input']['description'], + $req['input']['is_public'], + $req['input']['is_default'] + ); + + $createUserList = new CreateUserListAction($userList); + + return $createUserList->execute(); + } + + public function update(mixed $rootValue, array $req): ModelUserList + { + $userList = UserListRepository::getById($req['id'], auth()->user()); + + $userList->update($req['input']); + + return $userList; + } + + /** + * delete + */ + public function delete(mixed $rootValue, array $req): bool + { + $userList = UserListRepository::getById($req['id'], auth()->user()); + + return $userList->delete(); + } + + public function addToList(mixed $rootValue, array $req): bool + { + $userList = UserListRepository::getById($req['users_lists_id'], auth()->user()); + $message = Message::getById($req['messages_id']); + $userList->items()->attach($message); + + return true; + } + + public function removeFromList(mixed $rootValue, array $req): bool + { + $userList = UserListRepository::getById($req['users_lists_id'], auth()->user()); + $message = Message::getById($req['messages_id']); + + $userList->items()->detach($message); + + return true; + } +} diff --git a/app/Http/Middleware/RolesMiddleware.php b/app/Http/Middleware/RolesMiddleware.php index e24cbfdc4..6930e77e6 100644 --- a/app/Http/Middleware/RolesMiddleware.php +++ b/app/Http/Middleware/RolesMiddleware.php @@ -5,7 +5,7 @@ use Bouncer; use Closure; use Illuminate\Http\Request; -use Kanvas\AccessControlList\Repositories\RolesRepository; +use Kanvas\AccessControlList\Enums\RolesEnums; use Kanvas\Apps\Models\Apps; class RolesMiddleware @@ -13,7 +13,6 @@ class RolesMiddleware /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request * @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next * * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse @@ -24,7 +23,7 @@ public function handle(Request $request, Closure $next) $user = auth()->user(); if ($user) { - Bouncer::scope()->to(RolesRepository::getScope()); + Bouncer::scope()->to(RolesEnums::getScope($app)); } return $next($request); diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 09cb1a3ab..b89f2a58b 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,7 +2,10 @@ namespace App\Providers; +use Bouncer; use Illuminate\Support\ServiceProvider; +use Kanvas\AccessControlList\Enums\RolesEnums; +use Kanvas\Apps\Models\Apps; use Kanvas\Sessions\Models\Sessions; use Laravel\Sanctum\Sanctum; diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 1e4184d31..da49791a6 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -9,6 +9,10 @@ use Kanvas\Companies\Models\Companies; use Kanvas\Companies\Models\CompaniesGroups; use Kanvas\Companies\Observers\CompaniesObserver; +use Kanvas\Social\Messages\Models\UserMessageActivity; +use Kanvas\Social\Messages\Observers\UserMessageActivityObserver; +use Kanvas\Social\UsersLists\Models\UserList; +use Kanvas\Social\UsersLists\Observers\UsersListsObserver; use Kanvas\Users\Models\Users; use Kanvas\Users\Observers\UsersObserver; @@ -32,6 +36,8 @@ public function boot() Users::observe(UsersObserver::class); Companies::observe(CompaniesObserver::class); CompaniesGroups::observe(CompaniesGroupsObserver::class); + UserMessageActivity::observe(UserMessageActivityObserver::class); + UserList::observe(UsersListsObserver::class); } /** diff --git a/app/Providers/KanvasAppsProvider.php b/app/Providers/KanvasAppsProvider.php index 72ee082f9..41f037b89 100644 --- a/app/Providers/KanvasAppsProvider.php +++ b/app/Providers/KanvasAppsProvider.php @@ -2,8 +2,11 @@ namespace App\Providers; +use Bouncer; +use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Schema as FacadesSchema; use Illuminate\Support\ServiceProvider; +use Kanvas\AccessControlList\Enums\RolesEnums; use Kanvas\Apps\Models\Apps; use Kanvas\Apps\Repositories\AppsRepository; use Kanvas\Enums\AppEnums; @@ -12,13 +15,6 @@ class KanvasAppsProvider extends ServiceProvider { - /** - * Register any application services. - */ - public function register(): void - { - } - /** * Bootstrap any application services. */ @@ -26,18 +22,30 @@ public function boot(): void { $appIdentifier = request()->header(AppEnums::KANVAS_APP_HEADER->getValue(), config('kanvas.app.id')); - if (FacadesSchema::hasTable('apps') && Apps::count() > 0) { - try { - $app = AppsRepository::findFirstByKey($appIdentifier); + try { + if (App::runningInConsole() && ! FacadesSchema::hasTable('migrations')) { + // Skip the logic if running "php artisan package:discover --ansi" for the first time + return; + } + } catch (Throwable $th) { + //we've reach here on the first time the container is build , since no db connection exist + return ; + } - $this->app->scoped(Apps::class, function () use ($app) { - return $app; - }); - } catch (Throwable $e) { - $msg = 'No App configure with this key: ' . $appIdentifier; + try { + $app = AppsRepository::findFirstByKey($appIdentifier); - throw new InternalServerErrorException($msg, $e->getMessage()); - } + $this->app->scoped(Apps::class, function () use ($app) { + return $app; + }); + + //set app ACL scope + Bouncer::scope()->to(RolesEnums::getScope($app)); + } catch (Throwable $e) { + throw new InternalServerErrorException( + 'No App configure with this key: ' . $appIdentifier, + $e->getMessage() + ); } } } diff --git a/composer.json b/composer.json index db6480c7d..04763dfb3 100644 --- a/composer.json +++ b/composer.json @@ -13,27 +13,26 @@ "php": "^8.2", "genealabs/laravel-model-caching": "^0.13", "goldspecdigital/laravel-eloquent-uuid": "^10.0", - "guzzlehttp/guzzle": "^7.5", - "http-interop/http-factory-guzzle": "^1.2", + "guzzlehttp/guzzle": "^7.6", + "http-interop/http-factory-guzzle": "^1.0", "laravel/framework": "^10.0", "laravel/octane": "^2.0", "laravel/sanctum": "^3.2", - "laravel/scout": "^9.8", + "laravel/scout": "^10.2", "laravel/socialite": "^5.6", "laravel/tinker": "^2.7", "lcobucci/jwt": "^4.3", "league/flysystem-aws-s3-v3": "^3.12", - "meilisearch/meilisearch-php": "^0.27.0", + "meilisearch/meilisearch-php": "^1.1", "mll-lab/graphql-php-scalars": "^6.0", - "mll-lab/laravel-graphiql": "^1.2", "nuwave/lighthouse": "^6.0", "phpclassic/php-shopify": "^1.2", "sentry/sentry-laravel": "^3.2", "shopify/shopify-api": "^4.1", "silber/bouncer": "^1.0", "spatie/data-transfer-object": "^3.7", - "spatie/laravel-google-cloud-storage": "^2.2", "spatie/laravel-data": "^3.1", + "spatie/laravel-google-cloud-storage": "^2.2", "spatie/laravel-health": "^1.22", "spatie/laravel-queueable-action": "^2.14", "spatie/laravel-webhook-server": "^3.4", @@ -45,12 +44,13 @@ "require-dev": { "fakerphp/faker": "^1.9.1", "kitloong/laravel-migrations-generator": "^6.8", + "mll-lab/laravel-graphiql": "^3.1", "mockery/mockery": "^1.4.4", "nunomaduro/collision": "^7.0", - "phpunit/phpunit": "^10.0", + "phpstan/phpstan": "^1.4.7", + "phpunit/phpunit": "10.2.1", "spatie/laravel-ignition": "^2.0", - "vimeo/psalm": "^5.6", - "phpstan/phpstan": "^1.4.7" + "vimeo/psalm": "^5.6" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 9564be9ff..2c359a7ff 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9f3639d2aaa3a0ef5b4a9028da46e7bf", + "content-hash": "f7d23c8a93f8d9a8ffa3ba4caf341542", "packages": [ { "name": "aws/aws-crt-php", @@ -62,16 +62,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.269.13", + "version": "3.269.0", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "84f5f9c4f9c4cd7997ca3b7f91fabaf7cc73b0bc" + "reference": "6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/84f5f9c4f9c4cd7997ca3b7f91fabaf7cc73b0bc", - "reference": "84f5f9c4f9c4cd7997ca3b7f91fabaf7cc73b0bc", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78", + "reference": "6d759ef9f24f0c7f271baf8014f41fc0cfdfbf78", "shasum": "" }, "require": { @@ -83,8 +83,7 @@ "guzzlehttp/promises": "^1.4.0", "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", "mtdowling/jmespath.php": "^2.6", - "php": ">=5.5", - "psr/http-message": "^1.0" + "php": ">=5.5" }, "require-dev": { "andrewsville/php-token-reflection": "^1.4", @@ -101,6 +100,7 @@ "paragonie/random_compat": ">= 2", "phpunit/phpunit": "^4.8.35 || ^5.6.3 || ^9.5", "psr/cache": "^1.0", + "psr/http-message": "^1.0", "psr/simple-cache": "^1.0", "sebastian/comparator": "^1.2.3 || ^4.0", "yoast/phpunit-polyfills": "^1.0" @@ -151,9 +151,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.269.13" + "source": "https://github.com/aws/aws-sdk-php/tree/3.269.0" }, - "time": "2023-05-16T18:24:42+00:00" + "time": "2023-04-26T18:21:04+00:00" }, { "name": "brick/math", @@ -353,25 +353,29 @@ }, { "name": "doctrine/deprecations", - "version": "v1.0.0", + "version": "v1.1.1", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", "shasum": "" }, "require": { - "php": "^7.1|^8.0" + "php": "^7.1 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5|^8.5|^9.5", - "psr/log": "^1|^2|^3" + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" @@ -390,34 +394,34 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" }, - "time": "2022-05-02T15:47:09+00:00" + "time": "2023-06-03T09:27:29+00:00" }, { "name": "doctrine/inflector", - "version": "2.0.6", + "version": "2.0.8", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024" + "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/d9d313a36c872fd6ee06d9a6cbcf713eaa40f024", - "reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/f9301a5b2fb1216b2b08f02ba04dc45423db6bff", + "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^10", + "doctrine/coding-standard": "^11.0", "phpstan/phpstan": "^1.8", "phpstan/phpstan-phpunit": "^1.1", "phpstan/phpstan-strict-rules": "^1.3", "phpunit/phpunit": "^8.5 || ^9.5", - "vimeo/psalm": "^4.25" + "vimeo/psalm": "^4.25 || ^5.4" }, "type": "library", "autoload": { @@ -467,7 +471,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.6" + "source": "https://github.com/doctrine/inflector/tree/2.0.8" }, "funding": [ { @@ -483,7 +487,7 @@ "type": "tidelift" } ], - "time": "2022-10-20T09:10:12+00:00" + "time": "2023-06-16T13:40:37+00:00" }, { "name": "doctrine/lexer", @@ -692,16 +696,16 @@ }, { "name": "firebase/php-jwt", - "version": "v6.5.0", + "version": "v6.8.0", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "e94e7353302b0c11ec3cfff7180cd0b1743975d2" + "reference": "48b0210c51718d682e53210c24d25c5a10a2299b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/e94e7353302b0c11ec3cfff7180cd0b1743975d2", - "reference": "e94e7353302b0c11ec3cfff7180cd0b1743975d2", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/48b0210c51718d682e53210c24d25c5a10a2299b", + "reference": "48b0210c51718d682e53210c24d25c5a10a2299b", "shasum": "" }, "require": { @@ -749,9 +753,9 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.5.0" + "source": "https://github.com/firebase/php-jwt/tree/v6.8.0" }, - "time": "2023-05-12T15:47:07+00:00" + "time": "2023-06-20T16:45:35+00:00" }, { "name": "fruitcake/php-cors", @@ -1068,32 +1072,32 @@ }, { "name": "google/cloud-core", - "version": "v1.51.2", + "version": "v1.52.1", "source": { "type": "git", "url": "https://github.com/googleapis/google-cloud-php-core.git", - "reference": "85dc48d62143f4bbfaa34c24da95003371de7b79" + "reference": "8214910f79b5508d4cd1cd48f39d7970443071d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-cloud-php-core/zipball/85dc48d62143f4bbfaa34c24da95003371de7b79", - "reference": "85dc48d62143f4bbfaa34c24da95003371de7b79", + "url": "https://api.github.com/repos/googleapis/google-cloud-php-core/zipball/8214910f79b5508d4cd1cd48f39d7970443071d5", + "reference": "8214910f79b5508d4cd1cd48f39d7970443071d5", "shasum": "" }, "require": { "google/auth": "^1.18", "guzzlehttp/guzzle": "^5.3|^6.5.7|^7.4.4", - "guzzlehttp/promises": "^1.3", + "guzzlehttp/promises": "^1.4||^2.0", "guzzlehttp/psr7": "^1.7|^2.0", "monolog/monolog": "^1.1|^2.0|^3.0", "php": ">=7.4", - "psr/http-message": "^1.0", + "psr/http-message": "^1.0|^2.0", "rize/uri-template": "~0.3" }, "require-dev": { "erusev/parsedown": "^1.6", "google/cloud-common-protos": "^0.4", - "google/gax": "^1.9", + "google/gax": "^1.19.1", "opis/closure": "^3", "phpdocumentor/reflection": "^5.0", "phpspec/prophecy-phpunit": "^2.0", @@ -1127,26 +1131,26 @@ ], "description": "Google Cloud PHP shared dependency, providing functionality useful to all components.", "support": { - "source": "https://github.com/googleapis/google-cloud-php-core/tree/v1.51.2" + "source": "https://github.com/googleapis/google-cloud-php-core/tree/v1.52.1" }, - "time": "2023-05-05T23:01:42+00:00" + "time": "2023-07-07T20:46:38+00:00" }, { "name": "google/cloud-storage", - "version": "v1.31.2", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-cloud-php-storage.git", - "reference": "7fe96d56856cda550b21779bb95a066b264852da" + "reference": "05ae33620feebe1107756b59fe0329cace3b5e13" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-cloud-php-storage/zipball/7fe96d56856cda550b21779bb95a066b264852da", - "reference": "7fe96d56856cda550b21779bb95a066b264852da", + "url": "https://api.github.com/repos/googleapis/google-cloud-php-storage/zipball/05ae33620feebe1107756b59fe0329cace3b5e13", + "reference": "05ae33620feebe1107756b59fe0329cace3b5e13", "shasum": "" }, "require": { - "google/cloud-core": "^1.51.1", + "google/cloud-core": "^1.51.3", "google/crc32": "^0.2.0", "php": ">=7.4", "ramsey/uuid": "^4.2.3" @@ -1184,9 +1188,9 @@ ], "description": "Cloud Storage Client for PHP", "support": { - "source": "https://github.com/googleapis/google-cloud-php-storage/tree/v1.31.2" + "source": "https://github.com/googleapis/google-cloud-php-storage/tree/v1.33.0" }, - "time": "2023-05-05T23:01:42+00:00" + "time": "2023-07-07T20:46:38+00:00" }, { "name": "google/crc32", @@ -1297,21 +1301,21 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.6.1", + "version": "7.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "8444a2bacf1960bc6a2b62ed86b8e72e11eebe51" + "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8444a2bacf1960bc6a2b62ed86b8e72e11eebe51", - "reference": "8444a2bacf1960bc6a2b62ed86b8e72e11eebe51", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5", + "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5", + "guzzlehttp/promises": "^1.5.3 || ^2.0", "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", @@ -1323,7 +1327,8 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.1", "ext-curl": "*", - "php-http/client-integration-tests": "^3.0", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", "phpunit/phpunit": "^8.5.29 || ^9.5.23", "psr/log": "^1.1 || ^2.0 || ^3.0" }, @@ -1402,7 +1407,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.6.1" + "source": "https://github.com/guzzle/guzzle/tree/7.7.0" }, "funding": [ { @@ -1418,20 +1423,20 @@ "type": "tidelift" } ], - "time": "2023-05-15T20:43:01+00:00" + "time": "2023-05-21T14:04:53+00:00" }, { "name": "guzzlehttp/promises", - "version": "1.5.2", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "b94b2807d85443f9719887892882d0329d1e2598" + "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598", - "reference": "b94b2807d85443f9719887892882d0329d1e2598", + "url": "https://api.github.com/repos/guzzle/promises/zipball/67ab6e18aaa14d753cc148911d273f6e6cb6721e", + "reference": "67ab6e18aaa14d753cc148911d273f6e6cb6721e", "shasum": "" }, "require": { @@ -1441,11 +1446,6 @@ "symfony/phpunit-bridge": "^4.4 || ^5.1" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5-dev" - } - }, "autoload": { "files": [ "src/functions_include.php" @@ -1486,7 +1486,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.2" + "source": "https://github.com/guzzle/promises/tree/1.5.3" }, "funding": [ { @@ -1502,7 +1502,7 @@ "type": "tidelift" } ], - "time": "2022-08-28T14:55:35+00:00" + "time": "2023-05-21T12:31:43+00:00" }, { "name": "guzzlehttp/psr7", @@ -1706,16 +1706,16 @@ }, { "name": "haydenpierce/class-finder", - "version": "0.5.2", + "version": "0.5.3", "source": { "type": "git", "url": "git@gitlab.com:hpierce1102/ClassFinder.git", - "reference": "04496c25657923afe928483d3a18c1b80ea6438b" + "reference": "40703445c18784edcc6411703e7c3869af11ec8c" }, "dist": { "type": "zip", - "url": "https://gitlab.com/api/v4/projects/hpierce1102%2FClassFinder/repository/archive.zip?sha=04496c25657923afe928483d3a18c1b80ea6438b", - "reference": "04496c25657923afe928483d3a18c1b80ea6438b", + "url": "https://gitlab.com/api/v4/projects/hpierce1102%2FClassFinder/repository/archive.zip?sha=40703445c18784edcc6411703e7c3869af11ec8c", + "reference": "40703445c18784edcc6411703e7c3869af11ec8c", "shasum": "" }, "require": { @@ -1744,7 +1744,7 @@ } ], "description": "A library that can provide of a list of classes in a given namespace", - "time": "2023-05-01T21:31:20+00:00" + "time": "2023-06-18T17:43:01+00:00" }, { "name": "http-interop/http-factory-guzzle", @@ -2008,16 +2008,16 @@ }, { "name": "laravel/framework", - "version": "v10.11.0", + "version": "v10.15.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "21a5b6d9b669f32c10cc8ba776511b5f62599fea" + "reference": "c7599dc92e04532824bafbd226c2936ce6a905b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/21a5b6d9b669f32c10cc8ba776511b5f62599fea", - "reference": "21a5b6d9b669f32c10cc8ba776511b5f62599fea", + "url": "https://api.github.com/repos/laravel/framework/zipball/c7599dc92e04532824bafbd226c2936ce6a905b8", + "reference": "c7599dc92e04532824bafbd226c2936ce6a905b8", "shasum": "" }, "require": { @@ -2204,20 +2204,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-05-16T13:59:23+00:00" + "time": "2023-07-11T13:43:52+00:00" }, { "name": "laravel/octane", - "version": "v2.0.0", + "version": "v2.0.2", "source": { "type": "git", "url": "https://github.com/laravel/octane.git", - "reference": "d962806a79c5ac97ddd1e371bd232d00c855c0d9" + "reference": "2ca23e0802b405a6fa2a1cf59fe733c4ae1e3cd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/octane/zipball/d962806a79c5ac97ddd1e371bd232d00c855c0d9", - "reference": "d962806a79c5ac97ddd1e371bd232d00c855c0d9", + "url": "https://api.github.com/repos/laravel/octane/zipball/2ca23e0802b405a6fa2a1cf59fe733c4ae1e3cd7", + "reference": "2ca23e0802b405a6fa2a1cf59fe733c4ae1e3cd7", "shasum": "" }, "require": { @@ -2291,7 +2291,7 @@ "issues": "https://github.com/laravel/octane/issues", "source": "https://github.com/laravel/octane" }, - "time": "2023-05-16T14:12:14+00:00" + "time": "2023-06-21T22:54:15+00:00" }, { "name": "laravel/sanctum", @@ -2361,43 +2361,45 @@ }, { "name": "laravel/scout", - "version": "v9.8.1", + "version": "v10.2.3", "source": { "type": "git", "url": "https://github.com/laravel/scout.git", - "reference": "38595717b396ce733d432b82e3225fa4e0d6c8ef" + "reference": "51d662fb00728dcf726a9e53a234a05896da888a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/scout/zipball/38595717b396ce733d432b82e3225fa4e0d6c8ef", - "reference": "38595717b396ce733d432b82e3225fa4e0d6c8ef", + "url": "https://api.github.com/repos/laravel/scout/zipball/51d662fb00728dcf726a9e53a234a05896da888a", + "reference": "51d662fb00728dcf726a9e53a234a05896da888a", "shasum": "" }, "require": { - "illuminate/bus": "^8.0|^9.0|^10.0", - "illuminate/contracts": "^8.0|^9.0|^10.0", - "illuminate/database": "^8.0|^9.0|^10.0", - "illuminate/http": "^8.0|^9.0|^10.0", - "illuminate/pagination": "^8.0|^9.0|^10.0", - "illuminate/queue": "^8.0|^9.0|^10.0", - "illuminate/support": "^8.0|^9.0|^10.0", - "php": "^7.3|^8.0" + "illuminate/bus": "^9.0|^10.0", + "illuminate/contracts": "^9.0|^10.0", + "illuminate/database": "^9.0|^10.0", + "illuminate/http": "^9.0|^10.0", + "illuminate/pagination": "^9.0|^10.0", + "illuminate/queue": "^9.0|^10.0", + "illuminate/support": "^9.0|^10.0", + "php": "^8.0" }, "require-dev": { - "meilisearch/meilisearch-php": "^0.19", + "algolia/algoliasearch-client-php": "^3.2", + "meilisearch/meilisearch-php": "^1.0", "mockery/mockery": "^1.0", - "orchestra/testbench": "^6.17|^7.0|^8.0", + "orchestra/testbench": "^7.0|^8.0", "php-http/guzzle7-adapter": "^1.0", + "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^9.3" }, "suggest": { "algolia/algoliasearch-client-php": "Required to use the Algolia engine (^3.2).", - "meilisearch/meilisearch-php": "Required to use the MeiliSearch engine (^0.23)." + "meilisearch/meilisearch-php": "Required to use the Meilisearch engine (^1.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "9.x-dev" + "dev-master": "10.x-dev" }, "laravel": { "providers": [ @@ -2430,7 +2432,7 @@ "issues": "https://github.com/laravel/scout/issues", "source": "https://github.com/laravel/scout" }, - "time": "2023-02-14T16:53:14+00:00" + "time": "2023-07-11T15:04:19+00:00" }, { "name": "laravel/serializable-closure", @@ -2494,16 +2496,16 @@ }, { "name": "laravel/socialite", - "version": "v5.6.1", + "version": "v5.7.0", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "a14a177f2cc71d8add71e2b19e00800e83bdda09" + "reference": "f5996f499e14db15407201a6bfbaba3ce6ce736c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/a14a177f2cc71d8add71e2b19e00800e83bdda09", - "reference": "a14a177f2cc71d8add71e2b19e00800e83bdda09", + "url": "https://api.github.com/repos/laravel/socialite/zipball/f5996f499e14db15407201a6bfbaba3ce6ce736c", + "reference": "f5996f499e14db15407201a6bfbaba3ce6ce736c", "shasum": "" }, "require": { @@ -2518,6 +2520,7 @@ "require-dev": { "mockery/mockery": "^1.0", "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0", + "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^8.0|^9.3" }, "type": "library", @@ -2559,7 +2562,7 @@ "issues": "https://github.com/laravel/socialite/issues", "source": "https://github.com/laravel/socialite" }, - "time": "2023-01-20T15:42:35+00:00" + "time": "2023-07-08T20:51:43+00:00" }, { "name": "laravel/tinker", @@ -3362,16 +3365,16 @@ }, { "name": "meilisearch/meilisearch-php", - "version": "v0.27.0", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/meilisearch/meilisearch-php.git", - "reference": "e95db9ed85a45dcd831573979bf1d42cb99b9b3b" + "reference": "c153714aaa947fb36779384999b65f6164247ed6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/meilisearch/meilisearch-php/zipball/e95db9ed85a45dcd831573979bf1d42cb99b9b3b", - "reference": "e95db9ed85a45dcd831573979bf1d42cb99b9b3b", + "url": "https://api.github.com/repos/meilisearch/meilisearch-php/zipball/c153714aaa947fb36779384999b65f6164247ed6", + "reference": "c153714aaa947fb36779384999b65f6164247ed6", "shasum": "" }, "require": { @@ -3386,7 +3389,7 @@ "guzzlehttp/guzzle": "^7.1", "http-interop/http-factory-guzzle": "^1.0", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "1.9.3", + "phpstan/phpstan": "1.10.16", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", "phpstan/phpstan-strict-rules": "^1.1", @@ -3424,9 +3427,9 @@ ], "support": { "issues": "https://github.com/meilisearch/meilisearch-php/issues", - "source": "https://github.com/meilisearch/meilisearch-php/tree/v0.27.0" + "source": "https://github.com/meilisearch/meilisearch-php/tree/v1.2.1" }, - "time": "2023-01-10T19:29:02+00:00" + "time": "2023-06-06T20:48:12+00:00" }, { "name": "mll-lab/graphql-php-scalars", @@ -3489,84 +3492,18 @@ }, "time": "2023-05-09T13:20:50+00:00" }, - { - "name": "mll-lab/laravel-graphiql", - "version": "v1.2.2", - "source": { - "type": "git", - "url": "https://github.com/mll-lab/laravel-graphiql.git", - "reference": "0c20cd7e7321f59fc63b51ea3f31c21c1b4ea74c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/mll-lab/laravel-graphiql/zipball/0c20cd7e7321f59fc63b51ea3f31c21c1b4ea74c", - "reference": "0c20cd7e7321f59fc63b51ea3f31c21c1b4ea74c", - "shasum": "" - }, - "require": { - "illuminate/console": "5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9 || ^10", - "illuminate/contracts": "5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9 || ^10", - "illuminate/support": "5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9 || ^10", - "php": "^7.1 || ^8" - }, - "require-dev": { - "ergebnis/composer-normalize": "^2.29", - "laravel/lumen-framework": "5.5.* || 5.6.* || 5.7.* || 5.8.* || ^6 || ^7 || ^8 || ^9 || ^10", - "mll-lab/php-cs-fixer-config": "^4.4", - "nunomaduro/larastan": "^2.4.1", - "orchestra/testbench": "^4 || ^5 || ^6 || ^7.7 || ^8.8", - "phpstan/extension-installer": "^1", - "phpstan/phpstan": "^1.10.3", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.1.1" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "MLL\\GraphiQL\\GraphiQLServiceProvider" - ] - } - }, - "autoload": { - "psr-4": { - "MLL\\GraphiQL\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Benedikt Franke", - "email": "benedikt@franke.tech" - } - ], - "description": "Easily integrate GraphiQL into your Laravel project", - "keywords": [ - "graphiql", - "graphql", - "laravel" - ], - "support": { - "issues": "https://github.com/mll-lab/laravel-graphiql/issues", - "source": "https://github.com/mll-lab/laravel-graphiql/tree/v1.2.2" - }, - "time": "2023-04-04T15:41:13+00:00" - }, { "name": "monolog/monolog", - "version": "3.3.1", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "9b5daeaffce5b926cac47923798bba91059e60e2" + "reference": "e2392369686d420ca32df3803de28b5d6f76867d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/9b5daeaffce5b926cac47923798bba91059e60e2", - "reference": "9b5daeaffce5b926cac47923798bba91059e60e2", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/e2392369686d420ca32df3803de28b5d6f76867d", + "reference": "e2392369686d420ca32df3803de28b5d6f76867d", "shasum": "" }, "require": { @@ -3581,7 +3518,7 @@ "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "graylog2/gelf-php": "^1.4.2 || ^2.0", "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", @@ -3589,7 +3526,7 @@ "phpstan/phpstan": "^1.9", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-strict-rules": "^1.4", - "phpunit/phpunit": "^9.5.26", + "phpunit/phpunit": "^10.1", "predis/predis": "^1.1 || ^2", "ruflin/elastica": "^7", "symfony/mailer": "^5.4 || ^6", @@ -3642,7 +3579,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.3.1" + "source": "https://github.com/Seldaek/monolog/tree/3.4.0" }, "funding": [ { @@ -3654,7 +3591,7 @@ "type": "tidelift" } ], - "time": "2023-02-06T13:46:10+00:00" + "time": "2023-06-21T08:46:11+00:00" }, { "name": "mtdowling/jmespath.php", @@ -3719,16 +3656,16 @@ }, { "name": "nesbot/carbon", - "version": "2.66.0", + "version": "2.68.1", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "496712849902241f04902033b0441b269effe001" + "reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/496712849902241f04902033b0441b269effe001", - "reference": "496712849902241f04902033b0441b269effe001", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4f991ed2a403c85efbc4f23eb4030063fdbe01da", + "reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da", "shasum": "" }, "require": { @@ -3817,7 +3754,7 @@ "type": "tidelift" } ], - "time": "2023-01-29T18:53:47+00:00" + "time": "2023-06-20T18:29:04+00:00" }, { "name": "nette/schema", @@ -3970,16 +3907,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.15.4", + "version": "v4.16.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290" + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290", - "reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", "shasum": "" }, "require": { @@ -4020,9 +3957,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" }, - "time": "2023-03-05T19:49:14+00:00" + "time": "2023-06-25T14:52:30+00:00" }, { "name": "nunomaduro/termwind", @@ -4112,16 +4049,16 @@ }, { "name": "nuwave/lighthouse", - "version": "v6.9.0", + "version": "v6.14.0", "source": { "type": "git", "url": "https://github.com/nuwave/lighthouse.git", - "reference": "0dc47d5dfd65d2087fff8a518aa42bb7e1567fe2" + "reference": "e09071f7b85af2a6f5ed5d846a8ed88735efa0bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nuwave/lighthouse/zipball/0dc47d5dfd65d2087fff8a518aa42bb7e1567fe2", - "reference": "0dc47d5dfd65d2087fff8a518aa42bb7e1567fe2", + "url": "https://api.github.com/repos/nuwave/lighthouse/zipball/e09071f7b85af2a6f5ed5d846a8ed88735efa0bd", + "reference": "e09071f7b85af2a6f5ed5d846a8ed88735efa0bd", "shasum": "" }, "require": { @@ -4144,7 +4081,7 @@ "require-dev": { "algolia/algoliasearch-client-php": "^3 || ^4", "bensampo/laravel-enum": "^5 || ^6", - "dms/phpunit-arraysubset-asserts": "^0.4", + "dms/phpunit-arraysubset-asserts": "^0.4 || ^0.5", "ergebnis/composer-normalize": "^2.2.2", "fakerphp/faker": "^1.21", "laravel/framework": "^9 || ^10", @@ -4163,7 +4100,7 @@ "phpstan/phpstan": "^1.10.3", "phpstan/phpstan-mockery": "^1.1", "phpstan/phpstan-phpunit": "^1.1.1", - "phpunit/phpunit": "^9.6.4", + "phpunit/phpunit": "^9.6.4 || ^10", "predis/predis": "^1.1 || ^2.1", "pusher/pusher-php-server": "^5 || ^6 || ^7.0.2", "rector/rector": "^0.15.18", @@ -4238,7 +4175,7 @@ "type": "patreon" } ], - "time": "2023-05-11T09:09:36+00:00" + "time": "2023-07-10T09:05:23+00:00" }, { "name": "nyholm/psr7", @@ -4437,16 +4374,16 @@ }, { "name": "php-amqplib/php-amqplib", - "version": "v3.5.3", + "version": "v3.5.4", "source": { "type": "git", "url": "https://github.com/php-amqplib/php-amqplib.git", - "reference": "bccaaf8ef8bcf18b4ab41e645e92537752b887bd" + "reference": "1aecbd182b35eb039667c50d7d92d71f105be779" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/bccaaf8ef8bcf18b4ab41e645e92537752b887bd", - "reference": "bccaaf8ef8bcf18b4ab41e645e92537752b887bd", + "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/1aecbd182b35eb039667c50d7d92d71f105be779", + "reference": "1aecbd182b35eb039667c50d7d92d71f105be779", "shasum": "" }, "require": { @@ -4512,29 +4449,28 @@ ], "support": { "issues": "https://github.com/php-amqplib/php-amqplib/issues", - "source": "https://github.com/php-amqplib/php-amqplib/tree/v3.5.3" + "source": "https://github.com/php-amqplib/php-amqplib/tree/v3.5.4" }, - "time": "2023-04-03T18:25:49+00:00" + "time": "2023-07-01T11:25:08+00:00" }, { "name": "php-http/client-common", - "version": "2.6.1", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/php-http/client-common.git", - "reference": "665bfc381bb910385f70391ed3eeefd0b7bbdd0d" + "reference": "880509727a447474d2a71b7d7fa5d268ddd3db4b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/client-common/zipball/665bfc381bb910385f70391ed3eeefd0b7bbdd0d", - "reference": "665bfc381bb910385f70391ed3eeefd0b7bbdd0d", + "url": "https://api.github.com/repos/php-http/client-common/zipball/880509727a447474d2a71b7d7fa5d268ddd3db4b", + "reference": "880509727a447474d2a71b7d7fa5d268ddd3db4b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0", "php-http/httplug": "^2.0", "php-http/message": "^1.6", - "php-http/message-factory": "^1.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0", "psr/http-message": "^1.0 || ^2.0", @@ -4582,22 +4518,22 @@ ], "support": { "issues": "https://github.com/php-http/client-common/issues", - "source": "https://github.com/php-http/client-common/tree/2.6.1" + "source": "https://github.com/php-http/client-common/tree/2.7.0" }, - "time": "2023-04-14T13:30:08+00:00" + "time": "2023-05-17T06:46:59+00:00" }, { "name": "php-http/discovery", - "version": "1.18.0", + "version": "1.19.1", "source": { "type": "git", "url": "https://github.com/php-http/discovery.git", - "reference": "29ae6fae35f4116bbfe4c8b96ccc3f687eb07cd9" + "reference": "57f3de01d32085fea20865f9b16fb0e69347c39e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/discovery/zipball/29ae6fae35f4116bbfe4c8b96ccc3f687eb07cd9", - "reference": "29ae6fae35f4116bbfe4c8b96ccc3f687eb07cd9", + "url": "https://api.github.com/repos/php-http/discovery/zipball/57f3de01d32085fea20865f9b16fb0e69347c39e", + "reference": "57f3de01d32085fea20865f9b16fb0e69347c39e", "shasum": "" }, "require": { @@ -4660,9 +4596,9 @@ ], "support": { "issues": "https://github.com/php-http/discovery/issues", - "source": "https://github.com/php-http/discovery/tree/1.18.0" + "source": "https://github.com/php-http/discovery/tree/1.19.1" }, - "time": "2023-05-03T14:49:12+00:00" + "time": "2023-07-11T07:02:26+00:00" }, { "name": "php-http/httplug", @@ -4723,22 +4659,21 @@ }, { "name": "php-http/message", - "version": "1.15.0", + "version": "1.16.0", "source": { "type": "git", "url": "https://github.com/php-http/message.git", - "reference": "2a1fbaa00cf5ffc82f379adf47388663bce8190d" + "reference": "47a14338bf4ebd67d317bf1144253d7db4ab55fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/message/zipball/2a1fbaa00cf5ffc82f379adf47388663bce8190d", - "reference": "2a1fbaa00cf5ffc82f379adf47388663bce8190d", + "url": "https://api.github.com/repos/php-http/message/zipball/47a14338bf4ebd67d317bf1144253d7db4ab55fd", + "reference": "47a14338bf4ebd67d317bf1144253d7db4ab55fd", "shasum": "" }, "require": { "clue/stream-filter": "^1.5", "php": "^7.2 || ^8.0", - "php-http/message-factory": "^1.0.2", "psr/http-message": "^1.1 || ^2.0" }, "provide": { @@ -4749,6 +4684,7 @@ "ext-zlib": "*", "guzzlehttp/psr7": "^1.0 || ^2.0", "laminas/laminas-diactoros": "^2.0 || ^3.0", + "php-http/message-factory": "^1.0.2", "phpspec/phpspec": "^5.1 || ^6.3 || ^7.1", "slim/slim": "^3.0" }, @@ -4786,9 +4722,9 @@ ], "support": { "issues": "https://github.com/php-http/message/issues", - "source": "https://github.com/php-http/message/tree/1.15.0" + "source": "https://github.com/php-http/message/tree/1.16.0" }, - "time": "2023-05-10T08:19:58+00:00" + "time": "2023-05-17T06:43:38+00:00" }, { "name": "php-http/message-factory", @@ -4904,16 +4840,16 @@ }, { "name": "phpclassic/php-shopify", - "version": "v1.2.5", + "version": "v1.2.7", "source": { "type": "git", "url": "https://github.com/phpclassic/php-shopify.git", - "reference": "1d05bc9c662b01e804b12ab6049cf707a43d4285" + "reference": "ac59e488690beebf948223756486cffa67972ace" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpclassic/php-shopify/zipball/1d05bc9c662b01e804b12ab6049cf707a43d4285", - "reference": "1d05bc9c662b01e804b12ab6049cf707a43d4285", + "url": "https://api.github.com/repos/phpclassic/php-shopify/zipball/ac59e488690beebf948223756486cffa67972ace", + "reference": "ac59e488690beebf948223756486cffa67972ace", "shasum": "" }, "require": { @@ -4949,9 +4885,9 @@ ], "support": { "issues": "https://github.com/phpclassic/php-shopify/issues", - "source": "https://github.com/phpclassic/php-shopify/tree/v1.2.5" + "source": "https://github.com/phpclassic/php-shopify/tree/v1.2.7" }, - "time": "2023-02-13T03:51:33+00:00" + "time": "2023-06-28T07:22:42+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -5008,16 +4944,16 @@ }, { "name": "phpdocumentor/type-resolver", - "version": "1.7.1", + "version": "1.7.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "dfc078e8af9c99210337325ff5aa152872c98714" + "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/dfc078e8af9c99210337325ff5aa152872c98714", - "reference": "dfc078e8af9c99210337325ff5aa152872c98714", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/b2fe4d22a5426f38e014855322200b97b5362c0d", + "reference": "b2fe4d22a5426f38e014855322200b97b5362c0d", "shasum": "" }, "require": { @@ -5060,9 +4996,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.1" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.2" }, - "time": "2023-03-27T19:02:04+00:00" + "time": "2023-05-30T18:13:47+00:00" }, { "name": "phpoption/phpoption", @@ -5141,16 +5077,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.19", + "version": "3.0.21", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "cc181005cf548bfd8a4896383bb825d859259f95" + "reference": "4580645d3fc05c189024eb3b834c6c1e4f0f30a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cc181005cf548bfd8a4896383bb825d859259f95", - "reference": "cc181005cf548bfd8a4896383bb825d859259f95", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/4580645d3fc05c189024eb3b834c6c1e4f0f30a1", + "reference": "4580645d3fc05c189024eb3b834c6c1e4f0f30a1", "shasum": "" }, "require": { @@ -5231,7 +5167,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.19" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.21" }, "funding": [ { @@ -5247,26 +5183,28 @@ "type": "tidelift" } ], - "time": "2023-03-05T17:13:09+00:00" + "time": "2023-07-09T15:24:48+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "1.20.4", + "version": "1.22.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "7d568c87a9df9c5f7e8b5f075fc469aa8cb0a4cd" + "reference": "65c39594fbd8c67abfc68bb323f86447bab79cc0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/7d568c87a9df9c5f7e8b5f075fc469aa8cb0a4cd", - "reference": "7d568c87a9df9c5f7e8b5f075fc469aa8cb0a4cd", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/65c39594fbd8c67abfc68bb323f86447bab79cc0", + "reference": "65c39594fbd8c67abfc68bb323f86447bab79cc0", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", "php-parallel-lint/php-parallel-lint": "^1.2", "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^1.5", @@ -5290,9 +5228,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.20.4" + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.22.1" }, - "time": "2023-05-02T09:19:37+00:00" + "time": "2023-06-29T20:46:06+00:00" }, { "name": "psr/cache", @@ -5603,16 +5541,16 @@ }, { "name": "psr/http-message", - "version": "1.1", + "version": "2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { @@ -5621,7 +5559,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -5636,7 +5574,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", @@ -5650,9 +5588,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/1.1" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2023-04-04T09:50:52+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { "name": "psr/log", @@ -5757,16 +5695,16 @@ }, { "name": "psy/psysh", - "version": "v0.11.17", + "version": "v0.11.18", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "3dc5d4018dabd80bceb8fe1e3191ba8460569f0a" + "reference": "4f00ee9e236fa6a48f4560d1300b9c961a70a7ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/3dc5d4018dabd80bceb8fe1e3191ba8460569f0a", - "reference": "3dc5d4018dabd80bceb8fe1e3191ba8460569f0a", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/4f00ee9e236fa6a48f4560d1300b9c961a70a7ec", + "reference": "4f00ee9e236fa6a48f4560d1300b9c961a70a7ec", "shasum": "" }, "require": { @@ -5827,9 +5765,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.11.17" + "source": "https://github.com/bobthecow/psysh/tree/v0.11.18" }, - "time": "2023-05-05T20:02:42+00:00" + "time": "2023-05-23T02:31:11+00:00" }, { "name": "ralouphie/getallheaders", @@ -6120,21 +6058,21 @@ }, { "name": "sentry/sdk", - "version": "3.3.0", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php-sdk.git", - "reference": "d0678fc7274dbb03046ed05cb24eb92945bedf8e" + "reference": "cd91b752f07c4bab9fb3b173f81af68a78a78d6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php-sdk/zipball/d0678fc7274dbb03046ed05cb24eb92945bedf8e", - "reference": "d0678fc7274dbb03046ed05cb24eb92945bedf8e", + "url": "https://api.github.com/repos/getsentry/sentry-php-sdk/zipball/cd91b752f07c4bab9fb3b173f81af68a78a78d6d", + "reference": "cd91b752f07c4bab9fb3b173f81af68a78a78d6d", "shasum": "" }, "require": { "http-interop/http-factory-guzzle": "^1.0", - "sentry/sentry": "^3.9", + "sentry/sentry": "^3.19", "symfony/http-client": "^4.3|^5.0|^6.0" }, "type": "metapackage", @@ -6161,7 +6099,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-php-sdk/issues", - "source": "https://github.com/getsentry/sentry-php-sdk/tree/3.3.0" + "source": "https://github.com/getsentry/sentry-php-sdk/tree/3.5.0" }, "funding": [ { @@ -6173,26 +6111,26 @@ "type": "custom" } ], - "time": "2022-10-11T09:05:00+00:00" + "time": "2023-06-12T17:50:36+00:00" }, { "name": "sentry/sentry", - "version": "3.18.1", + "version": "3.20.1", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php.git", - "reference": "b10161a08f51df0d12adda0b95cf8412fff3ce47" + "reference": "644ad9768c18139a80ac510090fad000d9ffd8a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/b10161a08f51df0d12adda0b95cf8412fff3ce47", - "reference": "b10161a08f51df0d12adda0b95cf8412fff3ce47", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/644ad9768c18139a80ac510090fad000d9ffd8a4", + "reference": "644ad9768c18139a80ac510090fad000d9ffd8a4", "shasum": "" }, "require": { "ext-json": "*", "ext-mbstring": "*", - "guzzlehttp/promises": "^1.4", + "guzzlehttp/promises": "^1.5.3|^2.0", "jean85/pretty-package-versions": "^1.5|^2.0.4", "php": "^7.2|^8.0", "php-http/async-client-implementation": "^1.0", @@ -6200,6 +6138,7 @@ "php-http/discovery": "^1.15", "php-http/httplug": "^1.1|^2.0", "php-http/message": "^1.5", + "php-http/message-factory": "^1.1", "psr/http-factory": "^1.0", "psr/http-factory-implementation": "^1.0", "psr/log": "^1.0|^2.0|^3.0", @@ -6265,7 +6204,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-php/issues", - "source": "https://github.com/getsentry/sentry-php/tree/3.18.1" + "source": "https://github.com/getsentry/sentry-php/tree/3.20.1" }, "funding": [ { @@ -6277,28 +6216,28 @@ "type": "custom" } ], - "time": "2023-05-16T09:34:42+00:00" + "time": "2023-06-26T11:01:40+00:00" }, { "name": "sentry/sentry-laravel", - "version": "3.4.0", + "version": "3.6.1", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-laravel.git", - "reference": "50ec5eae5d09d182d2d048981d0b45c24579a7f7" + "reference": "eb94a52b88794d0c108dc46ca1a680531c3a8bad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/50ec5eae5d09d182d2d048981d0b45c24579a7f7", - "reference": "50ec5eae5d09d182d2d048981d0b45c24579a7f7", + "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/eb94a52b88794d0c108dc46ca1a680531c3a8bad", + "reference": "eb94a52b88794d0c108dc46ca1a680531c3a8bad", "shasum": "" }, "require": { "illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0", "nyholm/psr7": "^1.0", "php": "^7.2 | ^8.0", - "sentry/sdk": "^3.3", - "sentry/sentry": "^3.16", + "sentry/sdk": "^3.4", + "sentry/sentry": "^3.20", "symfony/psr-http-message-bridge": "^1.0 | ^2.0" }, "require-dev": { @@ -6355,7 +6294,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-laravel/issues", - "source": "https://github.com/getsentry/sentry-laravel/tree/3.4.0" + "source": "https://github.com/getsentry/sentry-laravel/tree/3.6.1" }, "funding": [ { @@ -6367,7 +6306,7 @@ "type": "custom" } ], - "time": "2023-05-08T14:15:56+00:00" + "time": "2023-07-04T10:30:42+00:00" }, { "name": "shopify/shopify-api", @@ -6649,16 +6588,16 @@ }, { "name": "spatie/laravel-data", - "version": "3.5.1", + "version": "3.7.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-data.git", - "reference": "2ca317a41b52df78c48602f227da383ff8683b21" + "reference": "a975123d86e0133a361ac225d17acb3d11aa351f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-data/zipball/2ca317a41b52df78c48602f227da383ff8683b21", - "reference": "2ca317a41b52df78c48602f227da383ff8683b21", + "url": "https://api.github.com/repos/spatie/laravel-data/zipball/a975123d86e0133a361ac225d17acb3d11aa351f", + "reference": "a975123d86e0133a361ac225d17acb3d11aa351f", "shasum": "" }, "require": { @@ -6720,7 +6659,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-data/issues", - "source": "https://github.com/spatie/laravel-data/tree/3.5.1" + "source": "https://github.com/spatie/laravel-data/tree/3.7.0" }, "funding": [ { @@ -6728,7 +6667,7 @@ "type": "github" } ], - "time": "2023-05-12T12:12:37+00:00" + "time": "2023-07-05T11:45:14+00:00" }, { "name": "spatie/laravel-google-cloud-storage", @@ -6807,16 +6746,16 @@ }, { "name": "spatie/laravel-health", - "version": "1.22.5", + "version": "1.22.7", "source": { "type": "git", "url": "https://github.com/spatie/laravel-health.git", - "reference": "eb61cc060f9e24c95801e76815367f4fe3555807" + "reference": "1268c60470e22a6aa33fca8c478aab44c89ebbdc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-health/zipball/eb61cc060f9e24c95801e76815367f4fe3555807", - "reference": "eb61cc060f9e24c95801e76815367f4fe3555807", + "url": "https://api.github.com/repos/spatie/laravel-health/zipball/1268c60470e22a6aa33fca8c478aab44c89ebbdc", + "reference": "1268c60470e22a6aa33fca8c478aab44c89ebbdc", "shasum": "" }, "require": { @@ -6887,7 +6826,7 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/laravel-health/tree/1.22.5" + "source": "https://github.com/spatie/laravel-health/tree/1.22.7" }, "funding": [ { @@ -6895,7 +6834,7 @@ "type": "github" } ], - "time": "2023-03-29T07:39:16+00:00" + "time": "2023-06-28T07:11:37+00:00" }, { "name": "spatie/laravel-package-tools", @@ -7181,23 +7120,23 @@ }, { "name": "symfony/console", - "version": "v6.2.10", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "12288d9f4500f84a4d02254d4aa968b15488476f" + "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/12288d9f4500f84a4d02254d4aa968b15488476f", - "reference": "12288d9f4500f84a4d02254d4aa968b15488476f", + "url": "https://api.github.com/repos/symfony/console/zipball/8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7", + "reference": "8788808b07cf0bdd6e4b7fdd23d8ddb1470c83b7", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", + "symfony/service-contracts": "^2.5|^3", "symfony/string": "^5.4|^6.0" }, "conflict": { @@ -7219,12 +7158,6 @@ "symfony/process": "^5.4|^6.0", "symfony/var-dumper": "^5.4|^6.0" }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" - }, "type": "library", "autoload": { "psr-4": { @@ -7257,7 +7190,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.2.10" + "source": "https://github.com/symfony/console/tree/v6.3.0" }, "funding": [ { @@ -7273,20 +7206,20 @@ "type": "tidelift" } ], - "time": "2023-04-28T13:37:43+00:00" + "time": "2023-05-29T12:49:39+00:00" }, { "name": "symfony/css-selector", - "version": "v6.2.7", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "aedf3cb0f5b929ec255d96bbb4909e9932c769e0" + "reference": "88453e64cd86c5b60e8d2fb2c6f953bbc353ffbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/aedf3cb0f5b929ec255d96bbb4909e9932c769e0", - "reference": "aedf3cb0f5b929ec255d96bbb4909e9932c769e0", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/88453e64cd86c5b60e8d2fb2c6f953bbc353ffbf", + "reference": "88453e64cd86c5b60e8d2fb2c6f953bbc353ffbf", "shasum": "" }, "require": { @@ -7322,7 +7255,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.2.7" + "source": "https://github.com/symfony/css-selector/tree/v6.3.0" }, "funding": [ { @@ -7338,20 +7271,20 @@ "type": "tidelift" } ], - "time": "2023-02-14T08:44:56+00:00" + "time": "2023-03-20T16:43:42+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e" + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", - "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", "shasum": "" }, "require": { @@ -7360,7 +7293,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -7389,7 +7322,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" }, "funding": [ { @@ -7405,20 +7338,20 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:25:55+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/error-handler", - "version": "v6.2.10", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "8b7e9f124640cb0611624a9383176c3e5f7d8cfb" + "reference": "99d2d814a6351461af350ead4d963bd67451236f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/8b7e9f124640cb0611624a9383176c3e5f7d8cfb", - "reference": "8b7e9f124640cb0611624a9383176c3e5f7d8cfb", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/99d2d814a6351461af350ead4d963bd67451236f", + "reference": "99d2d814a6351461af350ead4d963bd67451236f", "shasum": "" }, "require": { @@ -7426,8 +7359,11 @@ "psr/log": "^1|^2|^3", "symfony/var-dumper": "^5.4|^6.0" }, + "conflict": { + "symfony/deprecation-contracts": "<2.5" + }, "require-dev": { - "symfony/deprecation-contracts": "^2.1|^3", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-kernel": "^5.4|^6.0", "symfony/serializer": "^5.4|^6.0" }, @@ -7460,7 +7396,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.2.10" + "source": "https://github.com/symfony/error-handler/tree/v6.3.0" }, "funding": [ { @@ -7476,28 +7412,29 @@ "type": "tidelift" } ], - "time": "2023-04-18T13:46:08+00:00" + "time": "2023-05-10T12:03:13+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.2.8", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "04046f35fd7d72f9646e721fc2ecb8f9c67d3339" + "reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/04046f35fd7d72f9646e721fc2ecb8f9c67d3339", - "reference": "04046f35fd7d72f9646e721fc2ecb8f9c67d3339", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa", + "reference": "3af8ac1a3f98f6dbc55e10ae59c9e44bfc38dfaa", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/event-dispatcher-contracts": "^2|^3" + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4" + "symfony/dependency-injection": "<5.4", + "symfony/service-contracts": "<2.5" }, "provide": { "psr/event-dispatcher-implementation": "1.0", @@ -7510,13 +7447,9 @@ "symfony/error-handler": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", + "symfony/service-contracts": "^2.5|^3", "symfony/stopwatch": "^5.4|^6.0" }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" - }, "type": "library", "autoload": { "psr-4": { @@ -7543,7 +7476,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.2.8" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.0" }, "funding": [ { @@ -7559,33 +7492,30 @@ "type": "tidelift" } ], - "time": "2023-03-20T16:06:02+00:00" + "time": "2023-04-21T14:41:17+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "0ad3b6f1e4e2da5690fefe075cd53a238646d8dd" + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/0ad3b6f1e4e2da5690fefe075cd53a238646d8dd", - "reference": "0ad3b6f1e4e2da5690fefe075cd53a238646d8dd", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", + "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", "shasum": "" }, "require": { "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -7622,7 +7552,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.3.0" }, "funding": [ { @@ -7638,20 +7568,20 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:32:47+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/finder", - "version": "v6.2.7", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "20808dc6631aecafbe67c186af5dcb370be3a0eb" + "reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/20808dc6631aecafbe67c186af5dcb370be3a0eb", - "reference": "20808dc6631aecafbe67c186af5dcb370be3a0eb", + "url": "https://api.github.com/repos/symfony/finder/zipball/d9b01ba073c44cef617c7907ce2419f8d00d75e2", + "reference": "d9b01ba073c44cef617c7907ce2419f8d00d75e2", "shasum": "" }, "require": { @@ -7686,7 +7616,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.2.7" + "source": "https://github.com/symfony/finder/tree/v6.3.0" }, "funding": [ { @@ -7702,28 +7632,32 @@ "type": "tidelift" } ], - "time": "2023-02-16T09:57:23+00:00" + "time": "2023-04-02T01:25:41+00:00" }, { "name": "symfony/http-client", - "version": "v6.2.10", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "3f5545a91c8e79dedd1a06c4b04e1682c80c42f9" + "reference": "1c828a06aef2f5eeba42026dfc532d4fc5406123" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/3f5545a91c8e79dedd1a06c4b04e1682c80c42f9", - "reference": "3f5545a91c8e79dedd1a06c4b04e1682c80c42f9", + "url": "https://api.github.com/repos/symfony/http-client/zipball/1c828a06aef2f5eeba42026dfc532d4fc5406123", + "reference": "1c828a06aef2f5eeba42026dfc532d4fc5406123", "shasum": "" }, "require": { "php": ">=8.1", "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.1|^3", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-client-contracts": "^3", - "symfony/service-contracts": "^1.0|^2|^3" + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.3" }, "provide": { "php-http/async-client-implementation": "*", @@ -7774,7 +7708,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.2.10" + "source": "https://github.com/symfony/http-client/tree/v6.3.1" }, "funding": [ { @@ -7790,32 +7724,29 @@ "type": "tidelift" } ], - "time": "2023-04-20T13:12:48+00:00" + "time": "2023-06-24T11:51:27+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "df2ecd6cb70e73c1080e6478aea85f5f4da2c48b" + "reference": "3b66325d0176b4ec826bffab57c9037d759c31fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/df2ecd6cb70e73c1080e6478aea85f5f4da2c48b", - "reference": "df2ecd6cb70e73c1080e6478aea85f5f4da2c48b", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/3b66325d0176b4ec826bffab57c9037d759c31fb", + "reference": "3b66325d0176b4ec826bffab57c9037d759c31fb", "shasum": "" }, "require": { "php": ">=8.1" }, - "suggest": { - "symfony/http-client-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -7855,7 +7786,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.3.0" }, "funding": [ { @@ -7871,32 +7802,34 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:32:47+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.2.10", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "49adbb92bcb4e3c2943719d2756271e8b9602acc" + "reference": "e0ad0d153e1c20069250986cd9e9dd1ccebb0d66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/49adbb92bcb4e3c2943719d2756271e8b9602acc", - "reference": "49adbb92bcb4e3c2943719d2756271e8b9602acc", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e0ad0d153e1c20069250986cd9e9dd1ccebb0d66", + "reference": "e0ad0d153e1c20069250986cd9e9dd1ccebb0d66", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.1" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" }, "conflict": { "symfony/cache": "<6.2" }, "require-dev": { - "predis/predis": "~1.0", + "doctrine/dbal": "^2.13.1|^3.0", + "predis/predis": "^1.1|^2.0", "symfony/cache": "^5.4|^6.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", @@ -7904,9 +7837,6 @@ "symfony/mime": "^5.4|^6.0", "symfony/rate-limiter": "^5.2|^6.0" }, - "suggest": { - "symfony/mime": "To use the file extension guesser" - }, "type": "library", "autoload": { "psr-4": { @@ -7933,7 +7863,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.2.10" + "source": "https://github.com/symfony/http-foundation/tree/v6.3.1" }, "funding": [ { @@ -7949,29 +7879,29 @@ "type": "tidelift" } ], - "time": "2023-04-18T13:46:08+00:00" + "time": "2023-06-24T11:51:27+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.2.10", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "81064a65a5496f17d2b6984f6519406f98864215" + "reference": "161e16fd2e35fb4881a43bc8b383dfd5be4ac374" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/81064a65a5496f17d2b6984f6519406f98864215", - "reference": "81064a65a5496f17d2b6984f6519406f98864215", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/161e16fd2e35fb4881a43bc8b383dfd5be4ac374", + "reference": "161e16fd2e35fb4881a43bc8b383dfd5be4ac374", "shasum": "" }, "require": { "php": ">=8.1", "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/error-handler": "^6.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.3", "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-foundation": "^5.4.21|^6.2.7", + "symfony/http-foundation": "^6.2.7", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -7979,15 +7909,18 @@ "symfony/cache": "<5.4", "symfony/config": "<6.1", "symfony/console": "<5.4", - "symfony/dependency-injection": "<6.2", + "symfony/dependency-injection": "<6.3", "symfony/doctrine-bridge": "<5.4", "symfony/form": "<5.4", "symfony/http-client": "<5.4", + "symfony/http-client-contracts": "<2.5", "symfony/mailer": "<5.4", "symfony/messenger": "<5.4", "symfony/translation": "<5.4", + "symfony/translation-contracts": "<2.5", "symfony/twig-bridge": "<5.4", "symfony/validator": "<5.4", + "symfony/var-dumper": "<6.3", "twig/twig": "<2.13" }, "provide": { @@ -7996,28 +7929,27 @@ "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", "symfony/browser-kit": "^5.4|^6.0", + "symfony/clock": "^6.2", "symfony/config": "^6.1", "symfony/console": "^5.4|^6.0", "symfony/css-selector": "^5.4|^6.0", - "symfony/dependency-injection": "^6.2", + "symfony/dependency-injection": "^6.3", "symfony/dom-crawler": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2|^3", + "symfony/http-client-contracts": "^2.5|^3", "symfony/process": "^5.4|^6.0", + "symfony/property-access": "^5.4.5|^6.0.5", "symfony/routing": "^5.4|^6.0", + "symfony/serializer": "^6.3", "symfony/stopwatch": "^5.4|^6.0", "symfony/translation": "^5.4|^6.0", - "symfony/translation-contracts": "^1.1|^2|^3", + "symfony/translation-contracts": "^2.5|^3", "symfony/uid": "^5.4|^6.0", + "symfony/validator": "^6.3", + "symfony/var-exporter": "^6.2", "twig/twig": "^2.13|^3.0.4" }, - "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "" - }, "type": "library", "autoload": { "psr-4": { @@ -8044,7 +7976,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.2.10" + "source": "https://github.com/symfony/http-kernel/tree/v6.3.1" }, "funding": [ { @@ -8060,20 +7992,20 @@ "type": "tidelift" } ], - "time": "2023-04-28T13:50:28+00:00" + "time": "2023-06-26T06:07:32+00:00" }, { "name": "symfony/mailer", - "version": "v6.2.8", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "bfcfa015c67e19c6fdb7ca6fe70700af1e740a17" + "reference": "7b03d9be1dea29bfec0a6c7b603f5072a4c97435" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/bfcfa015c67e19c6fdb7ca6fe70700af1e740a17", - "reference": "bfcfa015c67e19c6fdb7ca6fe70700af1e740a17", + "url": "https://api.github.com/repos/symfony/mailer/zipball/7b03d9be1dea29bfec0a6c7b603f5072a4c97435", + "reference": "7b03d9be1dea29bfec0a6c7b603f5072a4c97435", "shasum": "" }, "require": { @@ -8083,9 +8015,10 @@ "psr/log": "^1|^2|^3", "symfony/event-dispatcher": "^5.4|^6.0", "symfony/mime": "^6.2", - "symfony/service-contracts": "^1.1|^2|^3" + "symfony/service-contracts": "^2.5|^3" }, "conflict": { + "symfony/http-client-contracts": "<2.5", "symfony/http-kernel": "<5.4", "symfony/messenger": "<6.2", "symfony/mime": "<6.2", @@ -8123,7 +8056,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.2.8" + "source": "https://github.com/symfony/mailer/tree/v6.3.0" }, "funding": [ { @@ -8139,28 +8072,32 @@ "type": "tidelift" } ], - "time": "2023-03-14T15:00:05+00:00" + "time": "2023-05-29T12:49:39+00:00" }, { "name": "symfony/mailgun-mailer", - "version": "v6.2.10", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/mailgun-mailer.git", - "reference": "2c9d47b11cc154d2db3f571030cd965d128de1a8" + "reference": "2fafefe8683a93155aceb6cca622c7cee2e27174" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/2c9d47b11cc154d2db3f571030cd965d128de1a8", - "reference": "2c9d47b11cc154d2db3f571030cd965d128de1a8", + "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/2fafefe8683a93155aceb6cca622c7cee2e27174", + "reference": "2fafefe8683a93155aceb6cca622c7cee2e27174", "shasum": "" }, "require": { "php": ">=8.1", "symfony/mailer": "^5.4.21|^6.2.7" }, + "conflict": { + "symfony/http-foundation": "<6.2" + }, "require-dev": { - "symfony/http-client": "^5.4|^6.0" + "symfony/http-client": "^5.4|^6.0", + "symfony/webhook": "^6.3" }, "type": "symfony-mailer-bridge", "autoload": { @@ -8188,7 +8125,7 @@ "description": "Symfony Mailgun Mailer Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailgun-mailer/tree/v6.2.10" + "source": "https://github.com/symfony/mailgun-mailer/tree/v6.3.0" }, "funding": [ { @@ -8204,20 +8141,20 @@ "type": "tidelift" } ], - "time": "2023-04-14T16:23:31+00:00" + "time": "2023-05-02T16:15:19+00:00" }, { "name": "symfony/mime", - "version": "v6.2.10", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "b6c137fc53a9f7c4c951cd3f362b3734c7a97723" + "reference": "7b5d2121858cd6efbed778abce9cfdd7ab1f62ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/b6c137fc53a9f7c4c951cd3f362b3734c7a97723", - "reference": "b6c137fc53a9f7c4c951cd3f362b3734c7a97723", + "url": "https://api.github.com/repos/symfony/mime/zipball/7b5d2121858cd6efbed778abce9cfdd7ab1f62ad", + "reference": "7b5d2121858cd6efbed778abce9cfdd7ab1f62ad", "shasum": "" }, "require": { @@ -8271,7 +8208,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.2.10" + "source": "https://github.com/symfony/mime/tree/v6.3.0" }, "funding": [ { @@ -8287,25 +8224,25 @@ "type": "tidelift" } ], - "time": "2023-04-19T09:54:16+00:00" + "time": "2023-04-28T15:57:00+00:00" }, { "name": "symfony/options-resolver", - "version": "v6.2.7", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "aa0e85b53bbb2b4951960efd61d295907eacd629" + "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/aa0e85b53bbb2b4951960efd61d295907eacd629", - "reference": "aa0e85b53bbb2b4951960efd61d295907eacd629", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a10f19f5198d589d5c33333cffe98dc9820332dd", + "reference": "a10f19f5198d589d5c33333cffe98dc9820332dd", "shasum": "" }, "require": { "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3" + "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", "autoload": { @@ -8338,7 +8275,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.2.7" + "source": "https://github.com/symfony/options-resolver/tree/v6.3.0" }, "funding": [ { @@ -8354,7 +8291,7 @@ "type": "tidelift" } ], - "time": "2023-02-14T08:44:56+00:00" + "time": "2023-05-12T14:21:09+00:00" }, { "name": "symfony/polyfill-ctype", @@ -8932,6 +8869,83 @@ ], "time": "2022-11-03T14:55:06+00:00" }, + { + "name": "symfony/polyfill-php83", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "508c652ba3ccf69f8c97f251534f229791b52a57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/508c652ba3ccf69f8c97f251534f229791b52a57", + "reference": "508c652ba3ccf69f8c97f251534f229791b52a57", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "symfony/polyfill-php80": "^1.14" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php83/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, { "name": "symfony/polyfill-uuid", "version": "v1.27.0", @@ -9016,16 +9030,16 @@ }, { "name": "symfony/process", - "version": "v6.2.10", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e" + "reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e", - "reference": "b34cdbc9c5e75d45a3703e63a48ad07aafa8bf2e", + "url": "https://api.github.com/repos/symfony/process/zipball/8741e3ed7fe2e91ec099e02446fb86667a0f1628", + "reference": "8741e3ed7fe2e91ec099e02446fb86667a0f1628", "shasum": "" }, "require": { @@ -9057,7 +9071,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.2.10" + "source": "https://github.com/symfony/process/tree/v6.3.0" }, "funding": [ { @@ -9073,7 +9087,7 @@ "type": "tidelift" } ], - "time": "2023-04-18T13:56:57+00:00" + "time": "2023-05-19T08:06:44+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -9165,16 +9179,16 @@ }, { "name": "symfony/routing", - "version": "v6.2.8", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "69062e2823f03b82265d73a966999660f0e1e404" + "reference": "d37ad1779c38b8eb71996d17dc13030dcb7f9cf5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/69062e2823f03b82265d73a966999660f0e1e404", - "reference": "69062e2823f03b82265d73a966999660f0e1e404", + "url": "https://api.github.com/repos/symfony/routing/zipball/d37ad1779c38b8eb71996d17dc13030dcb7f9cf5", + "reference": "d37ad1779c38b8eb71996d17dc13030dcb7f9cf5", "shasum": "" }, "require": { @@ -9195,12 +9209,6 @@ "symfony/http-foundation": "^5.4|^6.0", "symfony/yaml": "^5.4|^6.0" }, - "suggest": { - "symfony/config": "For using the all-in-one router or any loader", - "symfony/expression-language": "For using expression matching", - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/yaml": "For using the YAML loader" - }, "type": "library", "autoload": { "psr-4": { @@ -9233,7 +9241,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.2.8" + "source": "https://github.com/symfony/routing/tree/v6.3.1" }, "funding": [ { @@ -9249,20 +9257,20 @@ "type": "tidelift" } ], - "time": "2023-03-14T15:00:05+00:00" + "time": "2023-06-05T15:30:22+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "a8c9cedf55f314f3a186041d19537303766df09a" + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a8c9cedf55f314f3a186041d19537303766df09a", - "reference": "a8c9cedf55f314f3a186041d19537303766df09a", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", "shasum": "" }, "require": { @@ -9272,13 +9280,10 @@ "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -9318,7 +9323,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" }, "funding": [ { @@ -9334,20 +9339,20 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:32:47+00:00" + "time": "2023-05-23T14:45:45+00:00" }, { "name": "symfony/string", - "version": "v6.2.8", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef" + "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/193e83bbd6617d6b2151c37fff10fa7168ebddef", - "reference": "193e83bbd6617d6b2151c37fff10fa7168ebddef", + "url": "https://api.github.com/repos/symfony/string/zipball/f2e190ee75ff0f5eced645ec0be5c66fac81f51f", + "reference": "f2e190ee75ff0f5eced645ec0be5c66fac81f51f", "shasum": "" }, "require": { @@ -9358,13 +9363,13 @@ "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { "symfony/error-handler": "^5.4|^6.0", "symfony/http-client": "^5.4|^6.0", "symfony/intl": "^6.2", - "symfony/translation-contracts": "^2.0|^3.0", + "symfony/translation-contracts": "^2.5|^3.0", "symfony/var-exporter": "^5.4|^6.0" }, "type": "library", @@ -9404,7 +9409,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.2.8" + "source": "https://github.com/symfony/string/tree/v6.3.0" }, "funding": [ { @@ -9420,32 +9425,34 @@ "type": "tidelift" } ], - "time": "2023-03-20T16:06:02+00:00" + "time": "2023-03-21T21:06:29+00:00" }, { "name": "symfony/translation", - "version": "v6.2.8", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "817535dbb1721df8b3a8f2489dc7e50bcd6209b5" + "reference": "f72b2cba8f79dd9d536f534f76874b58ad37876f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/817535dbb1721df8b3a8f2489dc7e50bcd6209b5", - "reference": "817535dbb1721df8b3a8f2489dc7e50bcd6209b5", + "url": "https://api.github.com/repos/symfony/translation/zipball/f72b2cba8f79dd9d536f534f76874b58ad37876f", + "reference": "f72b2cba8f79dd9d536f534f76874b58ad37876f", "shasum": "" }, "require": { "php": ">=8.1", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.3|^3.0" + "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { "symfony/config": "<5.4", "symfony/console": "<5.4", "symfony/dependency-injection": "<5.4", + "symfony/http-client-contracts": "<2.5", "symfony/http-kernel": "<5.4", + "symfony/service-contracts": "<2.5", "symfony/twig-bundle": "<5.4", "symfony/yaml": "<5.4" }, @@ -9459,20 +9466,14 @@ "symfony/console": "^5.4|^6.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2.0|^3.0", + "symfony/http-client-contracts": "^2.5|^3.0", "symfony/http-kernel": "^5.4|^6.0", "symfony/intl": "^5.4|^6.0", "symfony/polyfill-intl-icu": "^1.21", "symfony/routing": "^5.4|^6.0", - "symfony/service-contracts": "^1.1.2|^2|^3", + "symfony/service-contracts": "^2.5|^3", "symfony/yaml": "^5.4|^6.0" }, - "suggest": { - "nikic/php-parser": "To use PhpAstExtractor", - "psr/log-implementation": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" - }, "type": "library", "autoload": { "files": [ @@ -9502,7 +9503,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.2.8" + "source": "https://github.com/symfony/translation/tree/v6.3.0" }, "funding": [ { @@ -9518,32 +9519,29 @@ "type": "tidelift" } ], - "time": "2023-03-31T09:14:44+00:00" + "time": "2023-05-19T12:46:45+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.2.1", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "dfec258b9dd17a6b24420d464c43bffe347441c8" + "reference": "02c24deb352fb0d79db5486c0c79905a85e37e86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dfec258b9dd17a6b24420d464c43bffe347441c8", - "reference": "dfec258b9dd17a6b24420d464c43bffe347441c8", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/02c24deb352fb0d79db5486c0c79905a85e37e86", + "reference": "02c24deb352fb0d79db5486c0c79905a85e37e86", "shasum": "" }, "require": { "php": ">=8.1" }, - "suggest": { - "symfony/translation-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -9583,7 +9581,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.2.1" + "source": "https://github.com/symfony/translation-contracts/tree/v3.3.0" }, "funding": [ { @@ -9599,20 +9597,20 @@ "type": "tidelift" } ], - "time": "2023-03-01T10:32:47+00:00" + "time": "2023-05-30T17:17:10+00:00" }, { "name": "symfony/uid", - "version": "v6.2.7", + "version": "v6.3.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "d30c72a63897cfa043e1de4d4dd2ffa9ecefcdc0" + "reference": "01b0f20b1351d997711c56f1638f7a8c3061e384" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/d30c72a63897cfa043e1de4d4dd2ffa9ecefcdc0", - "reference": "d30c72a63897cfa043e1de4d4dd2ffa9ecefcdc0", + "url": "https://api.github.com/repos/symfony/uid/zipball/01b0f20b1351d997711c56f1638f7a8c3061e384", + "reference": "01b0f20b1351d997711c56f1638f7a8c3061e384", "shasum": "" }, "require": { @@ -9657,7 +9655,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.2.7" + "source": "https://github.com/symfony/uid/tree/v6.3.0" }, "funding": [ { @@ -9673,20 +9671,20 @@ "type": "tidelift" } ], - "time": "2023-02-14T08:44:56+00:00" + "time": "2023-04-08T07:25:02+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.2.10", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "41a750a23412ca76fdbbf5096943b4134272c1ab" + "reference": "c81268d6960ddb47af17391a27d222bd58cf0515" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/41a750a23412ca76fdbbf5096943b4134272c1ab", - "reference": "41a750a23412ca76fdbbf5096943b4134272c1ab", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c81268d6960ddb47af17391a27d222bd58cf0515", + "reference": "c81268d6960ddb47af17391a27d222bd58cf0515", "shasum": "" }, "require": { @@ -9694,7 +9692,6 @@ "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "phpunit/phpunit": "<5.4.3", "symfony/console": "<5.4" }, "require-dev": { @@ -9704,11 +9701,6 @@ "symfony/uid": "^5.4|^6.0", "twig/twig": "^2.13|^3.0.4" }, - "suggest": { - "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", - "ext-intl": "To show region name in time zone dump", - "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" - }, "bin": [ "Resources/bin/var-dump-server" ], @@ -9745,7 +9737,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.2.10" + "source": "https://github.com/symfony/var-dumper/tree/v6.3.1" }, "funding": [ { @@ -9761,7 +9753,7 @@ "type": "tidelift" } ], - "time": "2023-04-18T13:46:08+00:00" + "time": "2023-06-21T12:08:28+00:00" }, { "name": "thecodingmachine/safe", @@ -9957,23 +9949,23 @@ }, { "name": "vladimir-yuldashev/laravel-queue-rabbitmq", - "version": "v13.2.0", + "version": "v13.3.3", "source": { "type": "git", "url": "https://github.com/vyuldashev/laravel-queue-rabbitmq.git", - "reference": "53d48953792f6e6f4472c0474b185b3059d29fdd" + "reference": "86315a4613a487f10ea5aae4c6ccbb06ef6f0694" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vyuldashev/laravel-queue-rabbitmq/zipball/53d48953792f6e6f4472c0474b185b3059d29fdd", - "reference": "53d48953792f6e6f4472c0474b185b3059d29fdd", + "url": "https://api.github.com/repos/vyuldashev/laravel-queue-rabbitmq/zipball/86315a4613a487f10ea5aae4c6ccbb06ef6f0694", + "reference": "86315a4613a487f10ea5aae4c6ccbb06ef6f0694", "shasum": "" }, "require": { "ext-json": "*", "illuminate/queue": "^9.0|^10.0", "php": "^8.0", - "php-amqplib/php-amqplib": "^3.0" + "php-amqplib/php-amqplib": "^v3.2" }, "require-dev": { "laravel/framework": "^9.0|^10.0", @@ -10015,9 +10007,9 @@ "description": "RabbitMQ driver for Laravel Queue. Supports Laravel Horizon.", "support": { "issues": "https://github.com/vyuldashev/laravel-queue-rabbitmq/issues", - "source": "https://github.com/vyuldashev/laravel-queue-rabbitmq/tree/v13.2.0" + "source": "https://github.com/vyuldashev/laravel-queue-rabbitmq/tree/v13.3.3" }, - "time": "2023-02-22T18:49:48+00:00" + "time": "2023-07-12T07:34:33+00:00" }, { "name": "vlucas/phpdotenv", @@ -10237,16 +10229,16 @@ }, { "name": "webonyx/graphql-php", - "version": "v15.4.0", + "version": "v15.5.1", "source": { "type": "git", "url": "https://github.com/webonyx/graphql-php.git", - "reference": "99290f7945a5b39ad823f7600fa196de62597e9d" + "reference": "b305633164a48947e22d53b6b15fcb98613c6592" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/99290f7945a5b39ad823f7600fa196de62597e9d", - "reference": "99290f7945a5b39ad823f7600fa196de62597e9d", + "url": "https://api.github.com/repos/webonyx/graphql-php/zipball/b305633164a48947e22d53b6b15fcb98613c6592", + "reference": "b305633164a48947e22d53b6b15fcb98613c6592", "shasum": "" }, "require": { @@ -10257,20 +10249,20 @@ "require-dev": { "amphp/amp": "^2.6", "amphp/http-server": "^2.1", - "dms/phpunit-arraysubset-asserts": "^0.4", + "dms/phpunit-arraysubset-asserts": "dev-master", "ergebnis/composer-normalize": "^2.28", - "mll-lab/php-cs-fixer-config": "^5.0", + "mll-lab/php-cs-fixer-config": "^5", "nyholm/psr7": "^1.5", "phpbench/phpbench": "^1.2", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "1.10.15", - "phpstan/phpstan-phpunit": "1.3.11", + "phpstan/phpstan": "1.10.19", + "phpstan/phpstan-phpunit": "1.3.13", "phpstan/phpstan-strict-rules": "1.5.1", - "phpunit/phpunit": "^9.5", + "phpunit/phpunit": "^9.5 || ^10", "psr/http-message": "^1 || ^2", "react/http": "^1.6", "react/promise": "^2.9", - "rector/rector": "^0.16.0", + "rector/rector": "^0.17.0", "symfony/polyfill-php81": "^1.23", "symfony/var-exporter": "^5 || ^6", "thecodingmachine/safe": "^1.3 || ^2" @@ -10298,7 +10290,7 @@ ], "support": { "issues": "https://github.com/webonyx/graphql-php/issues", - "source": "https://github.com/webonyx/graphql-php/tree/v15.4.0" + "source": "https://github.com/webonyx/graphql-php/tree/v15.5.1" }, "funding": [ { @@ -10306,7 +10298,7 @@ "type": "open_collective" } ], - "time": "2023-05-11T10:26:08+00:00" + "time": "2023-06-16T12:19:23+00:00" } ], "packages-dev": [ @@ -10826,16 +10818,16 @@ }, { "name": "doctrine/dbal", - "version": "3.6.2", + "version": "3.6.4", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "b4bd1cfbd2b916951696d82e57d054394d84864c" + "reference": "19f0dec95edd6a3c3c5ff1d188ea94c6b7fc903f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/b4bd1cfbd2b916951696d82e57d054394d84864c", - "reference": "b4bd1cfbd2b916951696d82e57d054394d84864c", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/19f0dec95edd6a3c3c5ff1d188ea94c6b7fc903f", + "reference": "19f0dec95edd6a3c3c5ff1d188ea94c6b7fc903f", "shasum": "" }, "require": { @@ -10848,12 +10840,12 @@ "psr/log": "^1|^2|^3" }, "require-dev": { - "doctrine/coding-standard": "11.1.0", + "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2022.3", - "phpstan/phpstan": "1.10.9", + "phpstan/phpstan": "1.10.14", "phpstan/phpstan-strict-rules": "^1.5", - "phpunit/phpunit": "9.6.6", + "phpunit/phpunit": "9.6.7", "psalm/plugin-phpunit": "0.18.4", "squizlabs/php_codesniffer": "3.7.2", "symfony/cache": "^5.4|^6.0", @@ -10918,7 +10910,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.6.2" + "source": "https://github.com/doctrine/dbal/tree/3.6.4" }, "funding": [ { @@ -10934,7 +10926,7 @@ "type": "tidelift" } ], - "time": "2023-04-14T07:25:38+00:00" + "time": "2023-06-15T07:40:12+00:00" }, { "name": "doctrine/event-manager", @@ -11029,16 +11021,16 @@ }, { "name": "fakerphp/faker", - "version": "v1.22.0", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "f85772abd508bd04e20bb4b1bbe260a68d0066d2" + "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/f85772abd508bd04e20bb4b1bbe260a68d0066d2", - "reference": "f85772abd508bd04e20bb4b1bbe260a68d0066d2", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", + "reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01", "shasum": "" }, "require": { @@ -11091,9 +11083,9 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.22.0" + "source": "https://github.com/FakerPHP/Faker/tree/v1.23.0" }, - "time": "2023-05-14T12:31:37+00:00" + "time": "2023-06-12T08:44:38+00:00" }, { "name": "felixfbecker/advanced-json-rpc", @@ -11454,40 +11446,112 @@ ], "time": "2023-03-26T07:37:00+00:00" }, + { + "name": "mll-lab/laravel-graphiql", + "version": "v3.1.0", + "source": { + "type": "git", + "url": "https://github.com/mll-lab/laravel-graphiql.git", + "reference": "54d7dbe5376ab87a6ea83be11b1431d0af9e2f6c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mll-lab/laravel-graphiql/zipball/54d7dbe5376ab87a6ea83be11b1431d0af9e2f6c", + "reference": "54d7dbe5376ab87a6ea83be11b1431d0af9e2f6c", + "shasum": "" + }, + "require": { + "illuminate/console": "^9 || ^10", + "illuminate/contracts": "^9 || ^10", + "illuminate/support": "^9 || ^10", + "php": "^8" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.29", + "laravel/lumen-framework": "^9 || ^10", + "mll-lab/php-cs-fixer-config": "^5", + "nunomaduro/larastan": "^2.5.2", + "orchestra/testbench": "^7.7 || ^8.8", + "phpstan/extension-installer": "^1", + "phpstan/phpstan": "^1.10.15", + "phpstan/phpstan-mockery": "^1.1.1", + "phpstan/phpstan-phpunit": "^1.3.11" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "MLL\\GraphiQL\\GraphiQLServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "MLL\\GraphiQL\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Benedikt Franke", + "email": "benedikt@franke.tech" + } + ], + "description": "Easily integrate GraphiQL into your Laravel project", + "keywords": [ + "graphiql", + "graphql", + "laravel" + ], + "support": { + "issues": "https://github.com/mll-lab/laravel-graphiql/issues", + "source": "https://github.com/mll-lab/laravel-graphiql/tree/v3.1.0" + }, + "time": "2023-07-04T13:58:40+00:00" + }, { "name": "mockery/mockery", - "version": "1.5.1", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e" + "reference": "13a7fa2642c76c58fa2806ef7f565344c817a191" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/e92dcc83d5a51851baf5f5591d32cb2b16e3684e", - "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e", + "url": "https://api.github.com/repos/mockery/mockery/zipball/13a7fa2642c76c58fa2806ef7f565344c817a191", + "reference": "13a7fa2642c76c58fa2806ef7f565344c817a191", "shasum": "" }, "require": { "hamcrest/hamcrest-php": "^2.0.1", "lib-pcre": ">=7.0", - "php": "^7.3 || ^8.0" + "php": "^7.4 || ^8.0" }, "conflict": { "phpunit/phpunit": "<8.0" }, "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.3" + "phpunit/phpunit": "^8.5 || ^9.3", + "psalm/plugin-phpunit": "^0.18", + "vimeo/psalm": "^5.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-main": "1.6.x-dev" } }, "autoload": { - "psr-0": { - "Mockery": "library/" + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" } }, "notification-url": "https://packagist.org/downloads/", @@ -11522,9 +11586,9 @@ ], "support": { "issues": "https://github.com/mockery/mockery/issues", - "source": "https://github.com/mockery/mockery/tree/1.5.1" + "source": "https://github.com/mockery/mockery/tree/1.6.2" }, - "time": "2022-09-07T15:32:08+00:00" + "time": "2023-06-07T09:07:52+00:00" }, { "name": "myclabs/deep-copy", @@ -11701,40 +11765,40 @@ }, { "name": "nunomaduro/collision", - "version": "v7.5.2", + "version": "v7.7.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "76b3cabda0aabda455fc3b9db6c3615f5a87c7ff" + "reference": "69a07197d055456d29911116fca3bc2c985f524b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/76b3cabda0aabda455fc3b9db6c3615f5a87c7ff", - "reference": "76b3cabda0aabda455fc3b9db6c3615f5a87c7ff", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/69a07197d055456d29911116fca3bc2c985f524b", + "reference": "69a07197d055456d29911116fca3bc2c985f524b", "shasum": "" }, "require": { "filp/whoops": "^2.15.2", "nunomaduro/termwind": "^1.15.1", "php": "^8.1.0", - "symfony/console": "^6.2.8" + "symfony/console": "^6.3.0" }, "conflict": { "phpunit/phpunit": "<10.1.2" }, "require-dev": { - "brianium/paratest": "^7.1.3", - "laravel/framework": "^10.8.0", - "laravel/pint": "^1.9.0", - "laravel/sail": "^1.21.4", - "laravel/sanctum": "^3.2.1", + "brianium/paratest": "^7.2.2", + "laravel/framework": "^10.14.1", + "laravel/pint": "^1.10.3", + "laravel/sail": "^1.23.0", + "laravel/sanctum": "^3.2.5", "laravel/tinker": "^2.8.1", - "nunomaduro/larastan": "^2.6.0", - "orchestra/testbench-core": "^8.5.0", - "pestphp/pest": "^2.5.2", - "phpunit/phpunit": "^10.1.1", + "nunomaduro/larastan": "^2.6.3", + "orchestra/testbench-core": "^8.5.8", + "pestphp/pest": "^2.8.1", + "phpunit/phpunit": "^10.2.2", "sebastian/environment": "^6.0.1", - "spatie/laravel-ignition": "^2.1.0" + "spatie/laravel-ignition": "^2.2.0" }, "type": "library", "extra": { @@ -11793,7 +11857,7 @@ "type": "patreon" } ], - "time": "2023-04-22T22:12:40+00:00" + "time": "2023-06-29T09:10:16+00:00" }, { "name": "phar-io/manifest", @@ -11965,16 +12029,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.15", + "version": "1.10.25", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd" + "reference": "578f4e70d117f9a90699324c555922800ac38d8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/762c4dac4da6f8756eebb80e528c3a47855da9bd", - "reference": "762c4dac4da6f8756eebb80e528c3a47855da9bd", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/578f4e70d117f9a90699324c555922800ac38d8c", + "reference": "578f4e70d117f9a90699324c555922800ac38d8c", "shasum": "" }, "require": { @@ -12023,20 +12087,20 @@ "type": "tidelift" } ], - "time": "2023-05-09T15:28:01+00:00" + "time": "2023-07-06T12:11:37+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "10.1.1", + "version": "10.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "884a0da7f9f46f28b2cb69134217fd810b793974" + "reference": "db1497ec8dd382e82c962f7abbe0320e4882ee4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/884a0da7f9f46f28b2cb69134217fd810b793974", - "reference": "884a0da7f9f46f28b2cb69134217fd810b793974", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/db1497ec8dd382e82c962f7abbe0320e4882ee4e", + "reference": "db1497ec8dd382e82c962f7abbe0320e4882ee4e", "shasum": "" }, "require": { @@ -12093,7 +12157,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.1" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.2" }, "funding": [ { @@ -12101,7 +12165,7 @@ "type": "github" } ], - "time": "2023-04-17T12:15:40+00:00" + "time": "2023-05-22T09:04:27+00:00" }, { "name": "phpunit/php-file-iterator", @@ -12347,16 +12411,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.1.3", + "version": "10.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2379ebafc1737e71cdc84f402acb6b7f04198b9d" + "reference": "599b33294350e8f51163119d5670512f98b0490d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2379ebafc1737e71cdc84f402acb6b7f04198b9d", - "reference": "2379ebafc1737e71cdc84f402acb6b7f04198b9d", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/599b33294350e8f51163119d5670512f98b0490d", + "reference": "599b33294350e8f51163119d5670512f98b0490d", "shasum": "" }, "require": { @@ -12396,7 +12460,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "10.1-dev" + "dev-main": "10.2-dev" } }, "autoload": { @@ -12428,7 +12492,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.1.3" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.2.1" }, "funding": [ { @@ -12444,7 +12508,7 @@ "type": "tidelift" } ], - "time": "2023-05-11T05:16:22+00:00" + "time": "2023-06-05T05:15:51+00:00" }, { "name": "sebastian/cli-parser", @@ -13421,16 +13485,16 @@ }, { "name": "spatie/backtrace", - "version": "1.4.0", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "ec4dd16476b802dbdc6b4467f84032837e316b8c" + "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/ec4dd16476b802dbdc6b4467f84032837e316b8c", - "reference": "ec4dd16476b802dbdc6b4467f84032837e316b8c", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/483f76a82964a0431aa836b6ed0edde0c248e3ab", + "reference": "483f76a82964a0431aa836b6ed0edde0c248e3ab", "shasum": "" }, "require": { @@ -13467,7 +13531,7 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.4.0" + "source": "https://github.com/spatie/backtrace/tree/1.5.3" }, "funding": [ { @@ -13479,26 +13543,27 @@ "type": "other" } ], - "time": "2023-03-04T08:57:24+00:00" + "time": "2023-06-28T12:59:17+00:00" }, { "name": "spatie/flare-client-php", - "version": "1.3.6", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/spatie/flare-client-php.git", - "reference": "530ac81255af79f114344286e4275f8869c671e2" + "reference": "943894c6a6b00501365ac0b91ae0dce56f2226fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/530ac81255af79f114344286e4275f8869c671e2", - "reference": "530ac81255af79f114344286e4275f8869c671e2", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/943894c6a6b00501365ac0b91ae0dce56f2226fa", + "reference": "943894c6a6b00501365ac0b91ae0dce56f2226fa", "shasum": "" }, "require": { "illuminate/pipeline": "^8.0|^9.0|^10.0", + "nesbot/carbon": "^2.62.1", "php": "^8.0", - "spatie/backtrace": "^1.2", + "spatie/backtrace": "^1.5.2", "symfony/http-foundation": "^5.0|^6.0", "symfony/mime": "^5.2|^6.0", "symfony/process": "^5.2|^6.0", @@ -13515,7 +13580,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.1.x-dev" + "dev-main": "1.3.x-dev" } }, "autoload": { @@ -13540,7 +13605,7 @@ ], "support": { "issues": "https://github.com/spatie/flare-client-php/issues", - "source": "https://github.com/spatie/flare-client-php/tree/1.3.6" + "source": "https://github.com/spatie/flare-client-php/tree/1.4.1" }, "funding": [ { @@ -13548,28 +13613,28 @@ "type": "github" } ], - "time": "2023-04-12T07:57:12+00:00" + "time": "2023-07-06T09:29:49+00:00" }, { "name": "spatie/ignition", - "version": "1.7.0", + "version": "1.9.0", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "f747d83c6d7cb6229b462f3ddbb3a82dc0db0f78" + "reference": "de24ff1e01814d5043bd6eb4ab36a5a852a04973" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/f747d83c6d7cb6229b462f3ddbb3a82dc0db0f78", - "reference": "f747d83c6d7cb6229b462f3ddbb3a82dc0db0f78", + "url": "https://api.github.com/repos/spatie/ignition/zipball/de24ff1e01814d5043bd6eb4ab36a5a852a04973", + "reference": "de24ff1e01814d5043bd6eb4ab36a5a852a04973", "shasum": "" }, "require": { "ext-json": "*", "ext-mbstring": "*", "php": "^8.0", - "spatie/backtrace": "^1.4", - "spatie/flare-client-php": "^1.1", + "spatie/backtrace": "^1.5.3", + "spatie/flare-client-php": "^1.4.0", "symfony/console": "^5.4|^6.0", "symfony/var-dumper": "^5.4|^6.0" }, @@ -13581,7 +13646,7 @@ "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", "psr/simple-cache-implementation": "*", - "symfony/cache": "^6.2", + "symfony/cache": "^6.0", "symfony/process": "^5.4|^6.0", "vlucas/phpdotenv": "^5.5" }, @@ -13631,20 +13696,20 @@ "type": "github" } ], - "time": "2023-05-04T13:20:26+00:00" + "time": "2023-06-28T13:24:59+00:00" }, { "name": "spatie/laravel-ignition", - "version": "2.1.2", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "2f99fa6b732a6049e78ed34e4608ce589605ae54" + "reference": "dd15fbe82ef5392798941efae93c49395a87d943" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/2f99fa6b732a6049e78ed34e4608ce589605ae54", - "reference": "2f99fa6b732a6049e78ed34e4608ce589605ae54", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/dd15fbe82ef5392798941efae93c49395a87d943", + "reference": "dd15fbe82ef5392798941efae93c49395a87d943", "shasum": "" }, "require": { @@ -13654,7 +13719,7 @@ "illuminate/support": "^10.0", "php": "^8.1", "spatie/flare-client-php": "^1.3.5", - "spatie/ignition": "^1.5.0", + "spatie/ignition": "^1.9", "symfony/console": "^6.2.3", "symfony/var-dumper": "^6.2.3" }, @@ -13723,20 +13788,20 @@ "type": "github" } ], - "time": "2023-05-09T07:19:31+00:00" + "time": "2023-06-28T13:51:52+00:00" }, { "name": "symfony/filesystem", - "version": "v6.2.10", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894" + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/fd588debf7d1bc16a2c84b4b3b71145d9946b894", - "reference": "fd588debf7d1bc16a2c84b4b3b71145d9946b894", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", "shasum": "" }, "require": { @@ -13770,7 +13835,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.2.10" + "source": "https://github.com/symfony/filesystem/tree/v6.3.1" }, "funding": [ { @@ -13786,7 +13851,7 @@ "type": "tidelift" } ], - "time": "2023-04-18T13:46:08+00:00" + "time": "2023-06-01T08:30:39+00:00" }, { "name": "theseer/tokenizer", @@ -13840,16 +13905,16 @@ }, { "name": "vimeo/psalm", - "version": "5.11.0", + "version": "5.13.1", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "c9b192ab8400fdaf04b2b13d110575adc879aa90" + "reference": "086b94371304750d1c673315321a55d15fc59015" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/c9b192ab8400fdaf04b2b13d110575adc879aa90", - "reference": "c9b192ab8400fdaf04b2b13d110575adc879aa90", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/086b94371304750d1c673315321a55d15fc59015", + "reference": "086b94371304750d1c673315321a55d15fc59015", "shasum": "" }, "require": { @@ -13940,9 +14005,9 @@ ], "support": { "issues": "https://github.com/vimeo/psalm/issues", - "source": "https://github.com/vimeo/psalm/tree/5.11.0" + "source": "https://github.com/vimeo/psalm/tree/5.13.1" }, - "time": "2023-05-04T21:35:44+00:00" + "time": "2023-06-27T16:39:49+00:00" } ], "aliases": [], diff --git a/config/data.php b/config/data.php new file mode 100644 index 000000000..848d2dc55 --- /dev/null +++ b/config/data.php @@ -0,0 +1,71 @@ + [DATE_ATOM, 'Y-m-d'], + + /* + * Global transformers will take complex types and transform them into simple + * types. + */ + 'transformers' => [ + DateTimeInterface::class => \Spatie\LaravelData\Transformers\DateTimeInterfaceTransformer::class, + \Illuminate\Contracts\Support\Arrayable::class => \Spatie\LaravelData\Transformers\ArrayableTransformer::class, + BackedEnum::class => Spatie\LaravelData\Transformers\EnumTransformer::class, + ], + + /* + * Global casts will cast values into complex types when creating a data + * object from simple types. + */ + 'casts' => [ + DateTimeInterface::class => Spatie\LaravelData\Casts\DateTimeInterfaceCast::class, + BackedEnum::class => Spatie\LaravelData\Casts\EnumCast::class, + ], + + /* + * Rule inferrers can be configured here. They will automatically add + * validation rules to properties of a data object based upon + * the type of the property. + */ + 'rule_inferrers' => [ + Spatie\LaravelData\RuleInferrers\SometimesRuleInferrer::class, + Spatie\LaravelData\RuleInferrers\NullableRuleInferrer::class, + Spatie\LaravelData\RuleInferrers\RequiredRuleInferrer::class, + Spatie\LaravelData\RuleInferrers\BuiltInTypesRuleInferrer::class, + Spatie\LaravelData\RuleInferrers\AttributesRuleInferrer::class, + ], + + /** + * Normalizers return an array representation of the payload, or null if + * it cannot normalize the payload. The normalizers below are used for + * every data object, unless overridden in a specific data object class. + */ + 'normalizers' => [ + Spatie\LaravelData\Normalizers\ModelNormalizer::class, + // Spatie\LaravelData\Normalizers\FormRequestNormalizer::class, + Spatie\LaravelData\Normalizers\ArrayableNormalizer::class, + Spatie\LaravelData\Normalizers\ObjectNormalizer::class, + Spatie\LaravelData\Normalizers\ArrayNormalizer::class, + Spatie\LaravelData\Normalizers\JsonNormalizer::class, + ], + + /* + * Data objects can be wrapped into a key like 'data' when used as a resource, + * this key can be set globally here for all data objects. You can pass in + * `null` if you want to disable wrapping. + */ + 'wrap' => null, + + /** + * Adds a specific caster to the Symphony VarDumper component which hides + * some properties from data objects and collections when being dumped + * by `dump` or `dd`. Can be 'enabled', 'disabled' or 'development' + * which will only enable the caster locally. + */ + 'var_dumper_caster_mode' => 'development', +]; diff --git a/config/database.php b/config/database.php index 02d3c80b7..b6f716b98 100644 --- a/config/database.php +++ b/config/database.php @@ -160,7 +160,7 @@ ], 'sticky' => true, 'port' => env('DB_CRM_PORT', '3306'), - 'database' => env('DB_CRM_DATABASE', 'social'), + 'database' => env('DB_CRM_DATABASE', 'crm'), 'username' => env('DB_CRM_USERNAME', 'kanvas'), 'password' => env('DB_CRM_PASSWORD', ''), 'unix_socket' => env('DB_CRM_SOCKET', ''), diff --git a/config/lighthouse.php b/config/lighthouse.php index 753828c59..744bf8885 100755 --- a/config/lighthouse.php +++ b/config/lighthouse.php @@ -554,4 +554,7 @@ */ 'entities_resolver_namespace' => 'App\\GraphQL\\Entities', ], + 'schema_cache' => [ + 'enable' => env('LIGHTHOUSE_SCHEMA_CACHE_ENABLE', true), + ], ]; diff --git a/config/scout.php b/config/scout.php index 33035e1ba..d88ba6fc7 100644 --- a/config/scout.php +++ b/config/scout.php @@ -1,5 +1,9 @@ env('MEILISEARCH_HOST', 'http://localhost:7700'), 'key' => env('MEILISEARCH_KEY', null), 'index-settings' => [ - // 'users' => [ - // 'filterableAttributes'=> ['id', 'name', 'email'], - // ], + Message::class => [ + 'filterableAttributes' => ['apps_id'], + 'sortableAttributes' => ['created_at','updated_at'], + ], + ModelUserList::class => [ + 'filterableAttributes' => [ + 'apps_id', + 'companies_id', + 'users_id', + 'is_public', + 'is_default', + 'name', + 'description', + 'items' + ], + 'sortableAttributes' => ['created_at','updated_at'], + ], ], ], diff --git a/database/migrations/2023_07_13_040152_update_user_link_source_type.php b/database/migrations/2023_07_13_040152_update_user_link_source_type.php new file mode 100644 index 000000000..3a17e8af6 --- /dev/null +++ b/database/migrations/2023_07_13_040152_update_user_link_source_type.php @@ -0,0 +1,35 @@ +char('source_users_id', 128)->change(); + $table->char('source_users_id_text', 255)->nullable()->change(); + $table->char('source_username', 128)->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('user_linked_sources', function (Blueprint $table) { + $table->string('source_users_id', 64)->change(); + $table->string('source_users_id_text', 255)->nullable()->change(); + $table->string('source_username', 45)->change(); + }); + } +}; diff --git a/database/migrations/Guild/2023_02_07_031052_create_organizations_table.php b/database/migrations/Guild/2023_02_07_031052_create_organizations_guild_table.php similarity index 95% rename from database/migrations/Guild/2023_02_07_031052_create_organizations_table.php rename to database/migrations/Guild/2023_02_07_031052_create_organizations_guild_table.php index 5b38d1bcc..ef88ddd38 100755 --- a/database/migrations/Guild/2023_02_07_031052_create_organizations_table.php +++ b/database/migrations/Guild/2023_02_07_031052_create_organizations_guild_table.php @@ -4,7 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class CreateOrganizationsTable extends Migration +class CreateOrganizationsGuildTable extends Migration { /** * Run the migrations. diff --git a/database/migrations/Inventory/2023_06_15_234654_create_attributes_values_table.php b/database/migrations/Inventory/2023_06_15_234654_create_attributes_values_table.php new file mode 100644 index 000000000..6fe543952 --- /dev/null +++ b/database/migrations/Inventory/2023_06_15_234654_create_attributes_values_table.php @@ -0,0 +1,34 @@ +charset = 'utf8mb4'; + $table->collation = 'utf8mb4_unicode_520_ci'; + $table->id(); + $table->index('attributes_id'); + $table->bigInteger('attributes_id')->unsigned(); + $table->text('value'); + $table->boolean('is_deleted')->default(0); + $table->timestamp('created_at')->useCurrent(); + $table->timestamp('updated_at')->useCurrent()->useCurrentOnUpdate(); + $table->foreign('attributes_id')->references('id')->on('attributes'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('attributes_values'); + } +}; diff --git a/database/migrations/Social/2023_02_04_234119_create_app_module_message_table.php b/database/migrations/Social/2023_02_04_234119_create_app_module_message_table.php index edc7cc188..f9fbbcb6a 100755 --- a/database/migrations/Social/2023_02_04_234119_create_app_module_message_table.php +++ b/database/migrations/Social/2023_02_04_234119_create_app_module_message_table.php @@ -20,7 +20,7 @@ public function up() $table->integer('apps_id')->index('apps_id'); $table->bigInteger('companies_id')->index('companies_id'); $table->string('system_modules', 100)->nullable()->index('system_modules'); - $table->bigInteger('entity_id')->nullable()->index('entity_id'); + $table->string('entity_id')->nullable()->index('entity_id'); $table->dateTime('created_at')->index('created_at'); $table->dateTime('updated_at')->nullable()->index('updated_at'); $table->boolean('is_deleted')->default(false)->index('is_deleted'); diff --git a/database/migrations/Social/2023_02_04_234119_create_user_messages_table.php b/database/migrations/Social/2023_02_04_234119_create_user_messages_table.php index eb72e7bbc..42f2168a4 100755 --- a/database/migrations/Social/2023_02_04_234119_create_user_messages_table.php +++ b/database/migrations/Social/2023_02_04_234119_create_user_messages_table.php @@ -14,7 +14,8 @@ class CreateUserMessagesTable extends Migration public function up() { Schema::connection('social')->create('user_messages', function (Blueprint $table) { - $table->char('messages_id', 36); + $table->increments('id'); + $table->bigInteger('messages_id'); $table->bigInteger('users_id'); $table->longText('notes')->nullable(); $table->text('activities')->nullable(); @@ -26,8 +27,6 @@ public function up() $table->longText('saved_lists')->nullable(); $table->dateTime('created_at')->index('created_at'); $table->tinyInteger('is_deleted')->default(0)->index('is_deleted'); - - $table->primary(['messages_id', 'users_id']); $table->index(['users_id', 'is_deleted'], 'users_id'); }); } diff --git a/database/migrations/Social/2023_02_04_234119_create_users_lists_table.php b/database/migrations/Social/2023_02_04_234119_create_users_lists_table.php index 42656be85..506c84782 100755 --- a/database/migrations/Social/2023_02_04_234119_create_users_lists_table.php +++ b/database/migrations/Social/2023_02_04_234119_create_users_lists_table.php @@ -14,16 +14,17 @@ class CreateUsersListsTable extends Migration public function up() { Schema::connection('social')->create('users_lists', function (Blueprint $table) { - $table->integer('id', true); + $table->id(); $table->integer('apps_id')->index('apps_id'); $table->bigInteger('companies_id')->index('companies_id'); $table->bigInteger('users_id')->index('users_id'); - $table->string('name', 50); + $table->string('name', 255); $table->char('slug', 100)->nullable()->default('')->index('slug'); $table->text('description')->nullable(); $table->boolean('is_public')->nullable()->index('is_public'); $table->boolean('is_default')->default(false)->index('is_default'); $table->dateTime('created_at')->index('created_at'); + $table->dateTime('deleted_at')->nullable(); $table->dateTime('updated_at')->nullable()->index('updated_at'); $table->boolean('is_deleted')->index('is_deleted'); diff --git a/database/migrations/Social/2023_05_25_201643_activity_types.php b/database/migrations/Social/2023_05_25_201643_activity_types.php new file mode 100644 index 000000000..ea5513162 --- /dev/null +++ b/database/migrations/Social/2023_05_25_201643_activity_types.php @@ -0,0 +1,30 @@ +create('users_messages_activities_types', function (Blueprint $table) { + $table->id(); + $table->bigInteger('apps_id')->unsigned(); + $table->string('name'); + $table->dateTime('created_at')->index('created_at'); + $table->dateTime('updated_at')->nullable()->index('updated_at'); + $table->boolean('is_deleted')->default(false)->index('is_deleted'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users_messages_activities_types'); + } +}; diff --git a/database/migrations/Social/2023_06_15_170518_users_lists_messages.php b/database/migrations/Social/2023_06_15_170518_users_lists_messages.php new file mode 100644 index 000000000..f41f76eef --- /dev/null +++ b/database/migrations/Social/2023_06_15_170518_users_lists_messages.php @@ -0,0 +1,33 @@ +create('users_lists_messages', function (Blueprint $table) { + $table->id(); + $table->bigInteger('users_lists_id')->unsigned(); + $table->bigInteger('messages_id'); + $table->integer('weight')->default(0); + $table->boolean('is_deleted')->default(false)->index('is_deleted'); + $table->foreign('users_lists_id')->references('id')->on('users_lists'); + $table->foreign('messages_id')->references('id')->on('messages'); + $table->softDeletes(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users_lists_messages'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 2dda89713..1d85362e9 100755 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -28,6 +28,7 @@ public function run() NotificationTypesSeeder::class, TemplateSeeder::class, CustomFieldsTypesSeeder::class, + MessageActivityTypeSeeder::class, ]); } } diff --git a/database/seeders/Guild/ContactTypeSeeder.php b/database/seeders/Guild/ContactTypeSeeder.php new file mode 100755 index 000000000..8caa2e586 --- /dev/null +++ b/database/seeders/Guild/ContactTypeSeeder.php @@ -0,0 +1,30 @@ +insert([ + [ + 'companies_id' => 0, + 'users_id' => 0, + 'name' => 'Email', + ],[ + 'companies_id' => 0, + 'users_id' => 0, + 'name' => 'Phone', + ], + ]); + } +} diff --git a/database/seeders/GuildSeeder.php b/database/seeders/GuildSeeder.php new file mode 100644 index 000000000..45bf6869d --- /dev/null +++ b/database/seeders/GuildSeeder.php @@ -0,0 +1,21 @@ +call([ + ContactTypeSeeder::class, + ]); + } +} diff --git a/database/seeders/MessageActivityTypeSeeder.php b/database/seeders/MessageActivityTypeSeeder.php new file mode 100644 index 000000000..a108f3f94 --- /dev/null +++ b/database/seeders/MessageActivityTypeSeeder.php @@ -0,0 +1,21 @@ + 1, + 'name' => 'follow', + ]); + } +} diff --git a/database/seeders/SourceSeeder.php b/database/seeders/SourceSeeder.php index dae911457..3eca0b658 100755 --- a/database/seeders/SourceSeeder.php +++ b/database/seeders/SourceSeeder.php @@ -4,6 +4,7 @@ use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; +use Kanvas\Enums\SourceEnum; class SourceSeeder extends Seeder { @@ -16,19 +17,19 @@ public function run() { DB::table('sources')->insert( [ - 'title' => 'baka', + 'title' => SourceEnum::BAKA, 'url' => 'baka.io', 'created_at' => date('Y-m-d H:i:s'), 'is_deleted' => 0 ], [ - 'title' => 'androipapp', + 'title' => SourceEnum::ANDROID, 'url' => 'bakaapp.io', 'created_at' => date('Y-m-d H:i:s'), 'is_deleted' => 0 ], [ - 'title' => 'iosapp', + 'title' => SourceEnum::IOS, 'url' => 'bakaios.io', 'created_at' => date('Y-m-d H:i:s'), 'is_deleted' => 0 @@ -58,7 +59,7 @@ public function run() 'is_deleted' => 0 ], [ - 'title' => 'webapp', + 'title' => SourceEnum::WEBAPP, 'url' => 'webapp.io', 'created_at' => date('Y-m-d H:i:s'), 'is_deleted' => 0 diff --git a/Dockerfile b/development.Dockerfile similarity index 91% rename from Dockerfile rename to development.Dockerfile index 926f0dcd1..ea1a2bfa6 100644 --- a/Dockerfile +++ b/development.Dockerfile @@ -10,6 +10,8 @@ RUN adduser -u 1000 -s /bin/sh --disabled-password -G www www # Copy code to /var/www COPY --chown=www:www-data . /app +RUN composer install --optimize-autoloader + # add root to www group RUN chmod -R ug+w /app/storage diff --git a/docker-compose.yml b/docker-compose.yml index 57709c32b..9e766835c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -132,6 +132,24 @@ services: - s3data:/data networks: - sail + meilisearch: + container_name: meilisearch + image: getmeili/meilisearch:v1.1 + environment: + - http_proxy + - https_proxy + - MEILI_MASTER_KEY=${MEILI_MASTER_KEY:-masterKey} + - MEILI_NO_ANALYTICS=${MEILI_NO_ANALYTICS:-true} + - MEILI_ENV=${MEILI_ENV:-development} + - MEILI_LOG_LEVEL + - MEILI_DB_PATH=${MEILI_DB_PATH:-/data.ms} + ports: + - ${MEILI_PORT:-7700}:7700 + networks: + - sail + volumes: + - meilisearch:/data.ms + restart: unless-stopped networks: sail: driver: bridge @@ -144,3 +162,4 @@ volumes: sail-rabbitmq: driver: local s3data: + meilisearch: diff --git a/graphql/schemas/Ecosystem/accessControlList.graphql b/graphql/schemas/Ecosystem/accessControlList.graphql deleted file mode 100644 index 5d01f660e..000000000 --- a/graphql/schemas/Ecosystem/accessControlList.graphql +++ /dev/null @@ -1,53 +0,0 @@ -type Role { - id: Int! - name: String! - title: String - scope: String -} - -extend type Query @guard { - roles: [Role] - @field( - resolver: "App\\GraphQL\\Ecosystem\\Resolvers\\AccessControlList\\RolesResolver@getAllRoles" - ) - hasRole(userId: Int!, role: String!): Boolean - @field( - resolver: "App\\GraphQL\\Ecosystem\\Resolvers\\AccessControlList\\RolesResolver@hasRole" - ) - can(userId: Int!, permission: String): Boolean - @field( - resolver: "App\\GraphQL\\Ecosystem\\Resolvers\\AccessControlList\\PermissionsResolver@can" - ) - getAllAbilities(userId: Int!): [String] - @field( - resolver: "App\\GraphQL\\Ecosystem\\Queries\\AccessControlList\\AccessControlList@getAllAbilities" - ) -} - -extend type Mutation @guard { - createRole(name: String!, title: String): Role - @field( - resolver: "App\\GraphQL\\Ecosystem\\Mutations\\AccessControlList\\AccessControlListManagementMutation@createRole" - ) - updateRole(id: Int!, name: String, title: String): Role - @field( - resolver: "App\\GraphQL\\Ecosystem\\Mutations\\AccessControlList\\AccessControlListManagementMutation@updateRole" - ) - - assignRoleToUser(userId: Int!, role: String!): Boolean - @field( - resolver: "App\\GraphQL\\Ecosystem\\Mutations\\AccessControlList\\AccessControlListManagementMutation@assignRoleToUser" - ) - removeRole(userId: Int!, role: String!): Boolean - @field( - resolver: "App\\GraphQL\\Ecosystem\\Mutations\\AccessControlList\\AccessControlListManagementMutation@removeRoleFromUser" - ) - givePermissionToUser(userId: Int!, permission: String!): Boolean - @field( - resolver: "App\\GraphQL\\Ecosystem\\Mutations\\AccessControlList\\AccessControlListManagementMutation@givePermissionToUser" - ) - removePermissionToUser(userId: Int!, permission: String!): Boolean - @field( - resolver: "App\\GraphQL\\Ecosystem\\Mutations\\AccessControlList\\AccessControlListManagementMutation@removePermissionToUser" - ) -} diff --git a/graphql/schemas/Ecosystem/apps.graphql b/graphql/schemas/Ecosystem/app.graphql similarity index 98% rename from graphql/schemas/Ecosystem/apps.graphql rename to graphql/schemas/Ecosystem/app.graphql index 4c6aeb31f..d0e80e1fa 100644 --- a/graphql/schemas/Ecosystem/apps.graphql +++ b/graphql/schemas/Ecosystem/app.graphql @@ -1,5 +1,5 @@ type App { - id: Int! + id: ID! name: String! description: String url: String @@ -16,7 +16,7 @@ type App { } type Template { - id: Int! + id: ID! name: String! template: String! } @@ -125,7 +125,7 @@ extend type Query @guardByAppKey { orderBy: _ @orderBy(columns: ["id"]) ): [User!]! @paginate( - builder: "App\\GraphQL\\Ecosystem\\Queries\\Apps\\AppUserManagement@getAllAppUsers" + builder: "App\\GraphQL\\Ecosystem\\Queries\\Apps\\AppUserManagementQuery@getAllAppUsers" defaultCount: 10 ) } @@ -133,7 +133,7 @@ extend type Query @guardByAppKey { extend type Query { getAppSettings(key: String! @eq): AppSettings @field( - resolver: "App\\GraphQL\\Ecosystem\\Queries\\Apps\\AppsList@getAppSettings" + resolver: "App\\GraphQL\\Ecosystem\\Queries\\Apps\\AppsListQuery@getAppSettings" ) } diff --git a/graphql/schemas/Ecosystem/cities.graphql b/graphql/schemas/Ecosystem/city.graphql similarity index 100% rename from graphql/schemas/Ecosystem/cities.graphql rename to graphql/schemas/Ecosystem/city.graphql diff --git a/graphql/schemas/Ecosystem/companies.graphql b/graphql/schemas/Ecosystem/company.graphql similarity index 88% rename from graphql/schemas/Ecosystem/companies.graphql rename to graphql/schemas/Ecosystem/company.graphql index 1e034b683..e0b379565 100644 --- a/graphql/schemas/Ecosystem/companies.graphql +++ b/graphql/schemas/Ecosystem/company.graphql @@ -1,5 +1,5 @@ type Company { - id: Int! + id: ID! uuid: String! name: String! website: String @@ -16,7 +16,7 @@ type Company { } type CompanyGroup { - id: Int! + id: ID! uuid: String! name: String! app: App! @@ -36,8 +36,8 @@ type CompanyAssociation { } type CompanyBranch { - id: Int! - companies_id: Int! + id: ID! + companies_id: ID! name: String! email: String phone: String @@ -70,7 +70,7 @@ input CompanyInput { input CompanyBranchInput { name: String! - companies_id: Int! + companies_id: ID! is_default: Boolean website: String address: String @@ -150,7 +150,7 @@ extend type Query @guard { ) ): [User!]! @paginate( - builder: "App\\GraphQL\\Ecosystem\\Queries\\Companies\\UserManagement@getAllCompanyUsers" + builder: "App\\GraphQL\\Ecosystem\\Queries\\Companies\\UserManagementQuery@getAllCompanyUsers" defaultCount: 10 ) @@ -172,26 +172,26 @@ extend type Query @guard { ) ): [User!]! @paginate( - builder: "App\\GraphQL\\Ecosystem\\Queries\\Companies\\UserManagement@getAllCompanyBranchUsers" + builder: "App\\GraphQL\\Ecosystem\\Queries\\Companies\\UserManagementQuery@getAllCompanyBranchUsers" defaultCount: 10 ) companySettings: CompanySettings @field( - resolver: "App\\GraphQL\\Ecosystem\\Queries\\Companies\\CompanySettings@getAllSettings" + resolver: "App\\GraphQL\\Ecosystem\\Queries\\Companies\\CompanySettingQuery@getAllSettings" ) } -extend type Mutation @guard { +extend type Mutation @guardByAdmin { createCompany(input: CompanyInput): Company! @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Companies\\CompaniesManagementMutation@createCompany" ) - updateCompany(id: Int!, input: CompanyInput): Company! + updateCompany(id: ID!, input: CompanyInput): Company! @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Companies\\CompaniesManagementMutation@updateCompany" ) - deleteCompany(id: Int!): Boolean! + deleteCompany(id: ID!): Boolean! @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Companies\\CompaniesManagementMutation@deleteCompany" ) @@ -199,27 +199,27 @@ extend type Mutation @guard { @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Companies\\CompaniesManagementMutation@createCompaniesBranch" ) - updateCompanyBranch(id: Int!, input: CompanyBranchInput): CompanyBranch! + updateCompanyBranch(id: ID!, input: CompanyBranchInput): CompanyBranch! @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Companies\\CompaniesManagementMutation@updateCompanyBranch" ) - deleteCompanyBranch(id: Int!): String! + deleteCompanyBranch(id: ID!): String! @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Companies\\CompaniesManagementMutation@deleteCompanyBranch" ) - addUserToBranch(id: Int!, users_id: Int!): Boolean! + addUserToBranch(id: ID!, users_id: ID!): Boolean! @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Companies\\CompaniesManagementMutation@addUserToBranch" ) - removeUserFromBranch(id: Int!, users_id: Int!): Boolean! + removeUserFromBranch(id: ID!, users_id: ID!): Boolean! @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Companies\\CompaniesManagementMutation@removeUserFromBranch" ) - addUserToCompany(id: Int!, users_id: Int!): Boolean! + addUserToCompany(id: ID!, users_id: ID!): Boolean! @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Companies\\CompaniesManagementMutation@addUserToCompany" ) - removeUserFromCompany(id: Int!, users_id: Int!): Boolean! + removeUserFromCompany(id: ID!, users_id: ID!): Boolean! @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Companies\\CompaniesManagementMutation@removeUserFromCompany" ) diff --git a/graphql/schemas/Ecosystem/countries.graphql b/graphql/schemas/Ecosystem/country.graphql similarity index 100% rename from graphql/schemas/Ecosystem/countries.graphql rename to graphql/schemas/Ecosystem/country.graphql diff --git a/graphql/schemas/Ecosystem/customFields.graphql b/graphql/schemas/Ecosystem/customField.graphql similarity index 62% rename from graphql/schemas/Ecosystem/customFields.graphql rename to graphql/schemas/Ecosystem/customField.graphql index a6110b297..8fbd176ad 100644 --- a/graphql/schemas/Ecosystem/customFields.graphql +++ b/graphql/schemas/Ecosystem/customField.graphql @@ -1,6 +1,6 @@ type CustomField { name: String! - data: Mixed + value: Mixed systemModule: SystemModule! entity_id: String! } @@ -12,6 +12,11 @@ input CustomFieldInput { entity_id: String! } +input CustomFieldEntityInput { + name: String! + data: Mixed +} + extend type Mutation @guard { setCustomField(input: CustomFieldInput!): Boolean! @field( @@ -30,3 +35,23 @@ extend type Mutation @guard { resolver: "App\\GraphQL\\Ecosystem\\Mutations\\CustomFields\\CustomFieldMutation@delete" ) } + +extend type Query @guard { + customField( + name: String! + system_module_uuid: String! + entity_id: String! + ): Mixed + @field( + resolver: "App\\GraphQL\\Ecosystem\\Queries\\CustomFields\\CustomFieldQuery@get" + ) + customFields( + name: String! + system_module_uuid: String! + entity_id: String! + ): Mixed + @field( + resolver: + "App\\GraphQL\\Ecosystem\\Queries\\CustomFields\\CustomFieldQuery@getAll" + ) +} diff --git a/graphql/schemas/Ecosystem/fileSystem.graphql b/graphql/schemas/Ecosystem/fileSystem.graphql index 9efc03c08..25287af1e 100644 --- a/graphql/schemas/Ecosystem/fileSystem.graphql +++ b/graphql/schemas/Ecosystem/fileSystem.graphql @@ -33,7 +33,7 @@ extend type Query @guard { ) ): [Filesystem!]! @paginate( - builder: "App\\GraphQL\\Ecosystem\\Queries\\Filesystem\\FilesystemQueries@getFilesFromSystemModuleEntity" + builder: "App\\GraphQL\\Ecosystem\\Queries\\Filesystem\\FilesystemQuery@getFilesFromSystemModuleEntity" defaultCount: 10 ) } diff --git a/graphql/schemas/Ecosystem/invites.graphql b/graphql/schemas/Ecosystem/invite.graphql similarity index 100% rename from graphql/schemas/Ecosystem/invites.graphql rename to graphql/schemas/Ecosystem/invite.graphql diff --git a/graphql/schemas/Ecosystem/language.graphql b/graphql/schemas/Ecosystem/language.graphql new file mode 100644 index 000000000..933d8d742 --- /dev/null +++ b/graphql/schemas/Ecosystem/language.graphql @@ -0,0 +1,5 @@ +type Language { + id: Int! + name: String! + order: Int +} diff --git a/graphql/schemas/Ecosystem/notifications.graphql b/graphql/schemas/Ecosystem/notification.graphql similarity index 100% rename from graphql/schemas/Ecosystem/notifications.graphql rename to graphql/schemas/Ecosystem/notification.graphql diff --git a/graphql/schemas/Ecosystem/notificationSettings.graphql b/graphql/schemas/Ecosystem/notificationSetting.graphql similarity index 100% rename from graphql/schemas/Ecosystem/notificationSettings.graphql rename to graphql/schemas/Ecosystem/notificationSetting.graphql diff --git a/graphql/schemas/Ecosystem/rolePermission.graphql b/graphql/schemas/Ecosystem/rolePermission.graphql new file mode 100644 index 000000000..f301f5efe --- /dev/null +++ b/graphql/schemas/Ecosystem/rolePermission.graphql @@ -0,0 +1,54 @@ +type Role { + id: Int! + name: String! + title: String + scope: String +} + +extend type Query @guard { + roles: [Role] + @field( + resolver: "App\\GraphQL\\Ecosystem\\Queries\\Roles\\RoleQuery@getAllRoles" + ) + hasRole(userId: Int!, role: Mixed!): Boolean + @field( + resolver: "App\\GraphQL\\Ecosystem\\Queries\\Roles\\RoleQuery@hasRole" + ) + can(userId: Int!, permission: String): Boolean + @field( + resolver: "App\\GraphQL\\Ecosystem\\Queries\\Roles\\RolePermissionQuery@can" + ) + getAllAbilities(userId: Int!): [String] + @field( + resolver: "App\\GraphQL\\Ecosystem\\Queries\\Roles\\RoleAbilitiesQuery@getAllAbilities" + ) +} + +extend type Mutation @guardByAdmin { + createRole(name: String!, title: String): Role + @field( + resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Roles\\RolesManagementMutation@createRole" + ) + updateRole(id: Int!, name: String, title: String): Role + @field( + resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Roles\\RolesManagementMutation@updateRole" + ) + + #assign role to the company and to the app + assignRoleToUser(userId: Int!, role: Mixed!): Boolean + @field( + resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Roles\\RolesManagementMutation@assignRoleToUser" + ) + removeRole(userId: Int!, role: Mixed!): Boolean + @field( + resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Roles\\RolesManagementMutation@removeRoleFromUser" + ) + givePermissionToUser(userId: Int!, permission: String!): Boolean + @field( + resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Roles\\RolesManagementMutation@givePermissionToUser" + ) + removePermissionToUser(userId: Int!, permission: String!): Boolean + @field( + resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Roles\\RolesManagementMutation@removePermissionToUser" + ) +} diff --git a/graphql/schemas/Ecosystem/source.graphql b/graphql/schemas/Ecosystem/source.graphql new file mode 100644 index 000000000..7c33d26ae --- /dev/null +++ b/graphql/schemas/Ecosystem/source.graphql @@ -0,0 +1,6 @@ +type Source { + id: Int! + title: String! + url: String! + language: Language! @belongsTo +} diff --git a/graphql/schemas/Ecosystem/systemModules.graphql b/graphql/schemas/Ecosystem/systemModule.graphql similarity index 100% rename from graphql/schemas/Ecosystem/systemModules.graphql rename to graphql/schemas/Ecosystem/systemModule.graphql diff --git a/graphql/schemas/Ecosystem/types.graphql b/graphql/schemas/Ecosystem/type.graphql similarity index 100% rename from graphql/schemas/Ecosystem/types.graphql rename to graphql/schemas/Ecosystem/type.graphql diff --git a/graphql/schemas/Ecosystem/users.graphql b/graphql/schemas/Ecosystem/user.graphql similarity index 70% rename from graphql/schemas/Ecosystem/users.graphql rename to graphql/schemas/Ecosystem/user.graphql index 537d49ae5..b4f885ebe 100644 --- a/graphql/schemas/Ecosystem/users.graphql +++ b/graphql/schemas/Ecosystem/user.graphql @@ -12,10 +12,18 @@ type User { @field(resolver: "App\\GraphQL\\Ecosystem\\Types\\UserType@address") sex: String user_active: Boolean! + abilities: Mixed! @method(name: "getAbilitiesList") + roles: Mixed! @method(name: "getRoles") created_at: DateTime updated_at: DateTime - branches: [CompanyBranch!] @HasManyThrough - companies: [Company!] @HasManyThrough + branches: [CompanyBranch!]! @HasManyThrough + companies: [Company!]! @HasManyThrough + apps: [App!]! @HasManyThrough + custom_fields: [CustomField!]! + @paginate( + defaultCount: 10 + builder: "App\\GraphQL\\Ecosystem\\Queries\\CustomFields\\HashFieldsQuery@getAllByGraphType" + ) } type AddressType { @@ -44,6 +52,13 @@ type TokenResponse { sessionId: String! } +type UserLinkSource { + users_id: Int! + source: Source! @belongsTo + source_user_id: String! + source_user_name: String +} + type RegisterResponse { user: User! token: TokenResponse! @@ -80,6 +95,12 @@ input RegisterInput { roles_id: Int } +input DeviceInput { + device_id: String! + source_site: String! + source_username: String +} + input UpdateUserInput { firstname: String lastname: String @@ -92,14 +113,11 @@ input UpdateUserInput { address_1: String address_2: String zip_code: Int - city_id: Int - @rules(apply: ["exists:Kanvas\\Locations\\Models\\Cities,id"]) - state_id: Int - @rules(apply: ["exists:Kanvas\\Locations\\Models\\States,id"]) + city_id: Int @rules(apply: ["exists:Kanvas\\Locations\\Models\\Cities,id"]) + state_id: Int @rules(apply: ["exists:Kanvas\\Locations\\Models\\States,id"]) country_id: Int - @rules( - apply: ["exists:Kanvas\\Locations\\Models\\Countries,id"] - ) + @rules(apply: ["exists:Kanvas\\Locations\\Models\\Countries,id"]) + custom_fields: [CustomFieldEntityInput!]! } extend type Mutation { @@ -107,12 +125,12 @@ extend type Mutation { @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Auth\\AuthManagementMutation@loginMutation" ) - logout: Boolean + logout: Boolean! @guard @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Auth\\AuthManagementMutation@logout" ) - logoutFromAllDevices: Boolean + logoutFromAllDevices: Boolean! @guard @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Auth\\AuthManagementMutation@logoutFromAllDevices" @@ -121,7 +139,7 @@ extend type Mutation { @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Auth\\AuthManagementMutation@register" ) - refreshToken(refresh_token: String!): TokenResponse + refreshToken(refresh_token: String!): TokenResponse! @guard @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Auth\\AuthManagementMutation@refreshToken" @@ -134,34 +152,44 @@ extend type Mutation { @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Users\\UserManagementMutation@changePassword" ) - forgotPassword(data: ForgotPasswordInput!): Boolean + forgotPassword(data: ForgotPasswordInput!): Boolean! @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Auth\\AuthManagementMutation@forgot" ) - resetPassword(data: ResetPasswordInput!): Boolean + resetPassword(data: ResetPasswordInput!): Boolean! @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Auth\\AuthManagementMutation@reset" ) - updateUser(data: UpdateUserInput!): User + updateUser(id: ID!, data: UpdateUserInput!): User! @guard @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Users\\UserManagementMutation@updateUser" ) - switchCompanyBranch(company_branch_id: Int!): Boolean + switchCompanyBranch(company_branch_id: Int!): Boolean! @guard @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Auth\\AuthManagementMutation@switchCompanyBranch" ) - socialLogin(data: SocialLoginInput!): TokenResponse + socialLogin(data: SocialLoginInput!): TokenResponse! @field( resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Auth\\AuthManagementMutation@socialLogin" ) + linkDevice(data: DeviceInput!): Boolean! + @guard + @field( + resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Users\\UserDeviceMutation@register" + ) + unLinkDevice(data: DeviceInput!): Boolean! + @guard + @field( + resolver: "App\\GraphQL\\Ecosystem\\Mutations\\Users\\UserDeviceMutation@remove" + ) } type Query @guard { me: User! @auth user(id: ID! @eq): User @field( - resolver: "App\\GraphQL\\Ecosystem\\Queries\\Users\\UsersList@getFromCurrentCompany" + resolver: "App\\GraphQL\\Ecosystem\\Queries\\Users\\UsersListQuery@getFromCurrentCompany" ) } diff --git a/graphql/schemas/Ecosystem/visitors.graphql b/graphql/schemas/Ecosystem/visitor.graphql similarity index 100% rename from graphql/schemas/Ecosystem/visitors.graphql rename to graphql/schemas/Ecosystem/visitor.graphql diff --git a/graphql/schemas/Guild/contact.graphql b/graphql/schemas/Guild/contact.graphql index 850bb6adb..4166d0039 100644 --- a/graphql/schemas/Guild/contact.graphql +++ b/graphql/schemas/Guild/contact.graphql @@ -1,5 +1,5 @@ type Contact { - id: Int! + id: ID! type: ContactType! @belongsTo people: People! @belongsTo value: String @@ -7,14 +7,14 @@ type Contact { } type ContactType { - id: Int! + id: ID! company: Company! @belongsTo name: String! user: User! @belongsTo } type Address { - id: Int! + id: ID! people: People! @belongsTo address: String address_2: String @@ -24,3 +24,22 @@ type Address { country: Country is_default: Boolean! } + +input ContactInput { + value: String! + contacts_types_id: ID! + weight: Int +} + +input AddressInput { + address: String! + address_2: String + city: String + city_id: ID + state: String + state_id: ID + zip: String + country: String + country_id: ID + is_default: Boolean +} \ No newline at end of file diff --git a/graphql/schemas/Guild/customer.graphql b/graphql/schemas/Guild/customer.graphql deleted file mode 100644 index ac55d14de..000000000 --- a/graphql/schemas/Guild/customer.graphql +++ /dev/null @@ -1,28 +0,0 @@ -type People { - id: Int! - uuid: String! - company: Company! - user: User! - name: String! - dob: String! - contacts: [Contact!] @hasMany - address: [Address!] @hasMany -} - -type PeopleRelationship { - id: Int! - name: String! - description: String - company: Company! @belongsTo -} - -extend type Query @guard { - peopleRelationships( - where: _ @whereConditions(columns: ["name", "description", "id"]) - ): [PeopleRelationship!]! - @paginate( - model: "Kanvas\\Guild\\Customers\\Models\\PeopleRelationship" - defaultCount: 10 - scopes: ["fromApp", "fromCompany"] - ) -} diff --git a/graphql/schemas/Guild/lead.graphql b/graphql/schemas/Guild/lead.graphql index 3c1553508..f8c3a0eb6 100644 --- a/graphql/schemas/Guild/lead.graphql +++ b/graphql/schemas/Guild/lead.graphql @@ -1,10 +1,11 @@ type Lead { - id: Int! + id: ID! uuid: String! company: Company! @belongsTo branch: CompanyBranch! @belongsTo title: String! people: People + owner: User @belongsTo organization: Organization @belongsTo receiver: LeadReceiver @belongsTo status: LeadStatus @belongsTo @@ -16,12 +17,13 @@ type Lead { phone: String description: String reason_lost: String - pipeline: LeadPipeline! @belongsTo - stage: LeadPipelineStage! @belongsTo(relation: "stage") - custom_fields: [CustomField] + pipeline: LeadPipeline @belongsTo + stage: LeadPipelineStage @belongsTo(relation: "stage") + participants: [LeadsParticipants!]! @hasMany + custom_fields: [CustomField!]! @paginate( defaultCount: 10 - builder: "App\\GraphQL\\Ecosystem\\Queries\\CustomFields\\CustomFieldQueries@getAllByGraphType" + builder: "App\\GraphQL\\Ecosystem\\Queries\\CustomFields\\CustomFieldQuery@getAllByGraphType" ) created_at: DateTime! updated_at: DateTime! @@ -31,9 +33,13 @@ type LeadsParticipants { people: People! @belongsTo relationship: PeopleRelationship @belongsTo } - +type Rotation{ + id: ID! + users_id: ID! + companies_id: ID! +} type LeadReceiver { - id: Int! + id: ID! uuid: String! company: Company! @belongsTo branch: CompanyBranch! @belongsTo @@ -51,20 +57,20 @@ type LeadReceiver { } type LeadStatus { - id: Int! + id: ID! name: String! is_default: Boolean! } type LeadType { - id: Int! + id: ID! company: Company! @belongsTo name: String! description: String } type LeadSource { - id: Int! + id: ID! company: Company! @belongsTo name: String! description: String @@ -72,7 +78,7 @@ type LeadSource { } type LeadPipeline { - id: Int! + id: ID! company: Company! @belongsTo module: SystemModule! @belongsTo stages: [LeadPipelineStage!]! @hasMany @@ -83,7 +89,7 @@ type LeadPipeline { } type LeadPipelineStage { - id: Int! + id: ID! pipeline: LeadPipeline! @belongsTo name: String! rotting_days: Int! @@ -96,14 +102,54 @@ input LeadsParticipantsInput { relationship_id: Int! } +input LeadInput { + branch_id: ID + title: String! + people: PeopleInput! + organization: OrganizationInput + leads_owner_id: ID + receiver_id: ID + status_id: ID + type_id: ID + source_id: ID + description: String + reason_lost: String + pipeline_stage_id: ID! + custom_fields: [CustomFieldEntityInput!]! +} + +input LeadUpdateInput { + branch_id: ID! + title: String + people_id: ID! + leads_owner_id: ID + organization_id: ID + receiver_id: ID + status_id: ID + type_id: ID + source_id: ID + description: String + reason_lost: String + pipeline_stage_id: ID + custom_fields: [CustomFieldEntityInput!]! +} + extend type Mutation @guard { + createLead(input: LeadInput!): Lead + @field(resolver: "App\\GraphQL\\Guild\\Mutations\\Leads\\LeadManagementMutation@create") + updateLead(id: ID!, input: LeadUpdateInput!): Lead + @field(resolver: "App\\GraphQL\\Guild\\Mutations\\Leads\\LeadManagementMutation@update") + deleteLead(id: ID!): Boolean + @field(resolver: "App\\GraphQL\\Guild\\Mutations\\Leads\\LeadManagementMutation@delete") + restoreLead(id: ID!): Boolean + @field(resolver: "App\\GraphQL\\Guild\\Mutations\\Leads\\LeadManagementMutation@restore") addLeadParticipant(input: LeadsParticipantsInput!): Boolean! @field( - resolver: "App\\GraphQL\\Guild\\Mutations\\Leads\\Participants@add" + resolver: "App\\GraphQL\\Guild\\Mutations\\Leads\\ParticipantMutation@add" ) removeLeadParticipant(input: LeadsParticipantsInput!): Boolean! @field( - resolver: "App\\GraphQL\\Guild\\Mutations\\Leads\\Participants@remove" + resolver: "App\\GraphQL\\Guild\\Mutations\\Leads\\ParticipantMutation@remove" ) } @@ -125,7 +171,7 @@ extend type Query @guard { "status" ] ) - ): [Lead] + ): [Lead!]! @paginate( model: "Kanvas\\Guild\\Leads\\Models\\Lead" scopes: ["fromCompany"] diff --git a/graphql/schemas/Guild/organization.graphql b/graphql/schemas/Guild/organization.graphql index 0a05a1833..998c47c6f 100644 --- a/graphql/schemas/Guild/organization.graphql +++ b/graphql/schemas/Guild/organization.graphql @@ -1,8 +1,55 @@ type Organization { - id: Int! + id: ID! uuid: String! company: Company! @belongsTo user: User! @belongsTo name: String! - address: String! -} \ No newline at end of file + address: String +} + +input OrganizationInput { + name: String! + address: String +} + +input OrganizationPeopleInput { + organization_id: ID! + peoples_id: [ID!]! +} + +extend type Mutation @guard { + createOrganization(input: OrganizationInput!): Organization + @field(resolver: "App\\GraphQL\\Guild\\Mutations\\Organizations\\OrganizationManagementMutation@create") + updateOrganization(id: ID!, input: OrganizationInput!): Organization + @field(resolver: "App\\GraphQL\\Guild\\Mutations\\Organizations\\OrganizationManagementMutation@update") + deleteOrganization(id: ID!): Boolean + @field(resolver: "App\\GraphQL\\Guild\\Mutations\\Organizations\\OrganizationManagementMutation@delete") + restoreOrganization(id: ID!): Boolean + @field(resolver: "App\\GraphQL\\Guild\\Mutations\\Organizations\\OrganizationManagementMutation@restore") + addPeopleToOrganization(input: OrganizationPeopleInput!): Boolean! + @field( + resolver: "App\\GraphQL\\Guild\\Mutations\\Organizations\\PeopleOrganizationMutation@add" + ) + removePeopleFromOrganization(input: OrganizationPeopleInput!): Boolean! + @field( + resolver: "App\\GraphQL\\Guild\\Mutations\\Organizations\\PeopleOrganizationMutation@remove" + ) +} + +extend type Query @guard { + organizations( + where: _ + @whereConditions( + columns: [ + "id" + "name" + "uuid" + ] + ) + ): [Organization!]! + @paginate( + model: "Kanvas\\Guild\\Organizations\\Models\\Organization" + scopes: ["fromCompany"] + defaultCount: 10 + ) +} diff --git a/graphql/schemas/Guild/people.graphql b/graphql/schemas/Guild/people.graphql new file mode 100644 index 000000000..5e889dff6 --- /dev/null +++ b/graphql/schemas/Guild/people.graphql @@ -0,0 +1,96 @@ +type People { + id: ID! + uuid: String! + company: Company! @belongsTo + user: User! @belongsTo + name: String! + dob: Date + contacts: [Contact!]! @hasMany + address: [Address!]! @hasMany + custom_fields: [CustomField!]! + @paginate( + defaultCount: 10 + builder: "App\\GraphQL\\Ecosystem\\Queries\\CustomFields\\CustomFieldQuery@getAllByGraphType" + ) +} + +type PeopleRelationship { + id: ID! + name: String! + description: String + company: Company! @belongsTo +} + +input PeopleInput { + id: ID + firstname: String! + lastname: String! + facebook_contact_id: String + twitter_contact_id: String + linkedin_contact_id: String + google_contact_id: String + dob: String + contacts: [ContactInput!]! + address: [AddressInput!]! + custom_fields: [CustomFieldEntityInput!]! +} + +input PeopleParticipantInput { + id: ID + firstname: String! + lastname: String! + participants_types_id: ID! + facebook_contact_id: String + twitter_contact_id: String + linkedin_contact_id: String + google_contact_id: String + dob: Date + contacts: [ContactInput!]! + address: [AddressInput!]! +} + +extend type Query @guard { + peoples( + where: _ + @whereConditions( + columns: [ + "id" + "uuid" + "companies_id" + "dob" + ] + ) + ): [People!]! + @paginate( + model: "Kanvas\\Guild\\Customers\\Models\\People" + scopes: ["fromCompany"] + defaultCount: 10 + ) + peopleRelationships( + where: _ @whereConditions(columns: ["name", "description", "id"]) + ): [PeopleRelationship!]! + @paginate( + model: "Kanvas\\Guild\\Customers\\Models\\PeopleRelationship" + defaultCount: 10 + scopes: ["fromApp", "fromCompany"] + ) +} + +extend type Mutation @guard { + createPeople(input: PeopleInput!): People + @field( + resolver: "App\\GraphQL\\Guild\\Mutations\\Peoples\\PeopleManagementMutation@create" + ) + updatePeople(id: ID!, input: PeopleInput!): People + @field( + resolver: "App\\GraphQL\\Guild\\Mutations\\Peoples\\PeopleManagementMutation@update" + ) + deletePeople(id: ID!): Boolean + @field( + resolver: "App\\GraphQL\\Guild\\Mutations\\Peoples\\PeopleManagementMutation@delete" + ) + restorePeople(id: ID!): Boolean + @field( + resolver: "App\\GraphQL\\Guild\\Mutations\\Peoples\\PeopleManagementMutation@restore" + ) +} diff --git a/graphql/schemas/Inventory/attributes.graphql b/graphql/schemas/Inventory/attributes.graphql index 38c4b76df..24463bee0 100644 --- a/graphql/schemas/Inventory/attributes.graphql +++ b/graphql/schemas/Inventory/attributes.graphql @@ -1,11 +1,13 @@ input AttributeInput { name: String! source_id: Mixed - value: Mixed + value: Mixed! } + input AttributeUpdateInput { name: String } + type Attributes { id: Int! uuid: String @@ -13,20 +15,26 @@ type Attributes { created_at: String updated_at: String companies: [Company] + values: [AttributesValue] @hasMany(relation: "defaultValues") +} + +type AttributesValue { + id: Int! value: Mixed } + extend type Mutation @guard { createAttribute(input: AttributeInput!): Attributes! @field( - resolver: "App\\GraphQL\\Inventory\\Mutations\\Attributes\\Attributes@create" + resolver: "App\\GraphQL\\Inventory\\Mutations\\Attributes\\AttributeMutation@create" ) updateAttribute(id: Int!, input: AttributeUpdateInput!): Attributes! @field( - resolver: "App\\GraphQL\\Inventory\\Mutations\\Attributes\\Attributes@update" + resolver: "App\\GraphQL\\Inventory\\Mutations\\Attributes\\AttributeMutation@update" ) deleteAttribute(id: Int!): Attributes! @field( - resolver: "App\\GraphQL\\Inventory\\Mutations\\Attributes\\Attributes@delete" + resolver: "App\\GraphQL\\Inventory\\Mutations\\Attributes\\AttributeMutation@delete" ) } extend type Query @guard { diff --git a/graphql/schemas/Inventory/channels.graphql b/graphql/schemas/Inventory/channel.graphql similarity index 100% rename from graphql/schemas/Inventory/channels.graphql rename to graphql/schemas/Inventory/channel.graphql diff --git a/graphql/schemas/Inventory/products.graphql b/graphql/schemas/Inventory/product.graphql similarity index 96% rename from graphql/schemas/Inventory/products.graphql rename to graphql/schemas/Inventory/product.graphql index 43f9c8f37..fc28da6c2 100644 --- a/graphql/schemas/Inventory/products.graphql +++ b/graphql/schemas/Inventory/product.graphql @@ -11,6 +11,9 @@ input ProductInput { categories: [Int] warehouses: [Int] source_id: Mixed + variants: [VariantsInput] + attributes: [AttributeInput] + price: Float } type Product { @@ -33,6 +36,7 @@ type Product { attributes: [Attributes] variants: [Variant] productsTypes: ProductType + companies: Company } input ProductInputUpdate { diff --git a/graphql/schemas/Inventory/variants.graphql b/graphql/schemas/Inventory/variant.graphql similarity index 98% rename from graphql/schemas/Inventory/variants.graphql rename to graphql/schemas/Inventory/variant.graphql index 09a21e474..61506a830 100644 --- a/graphql/schemas/Inventory/variants.graphql +++ b/graphql/schemas/Inventory/variant.graphql @@ -12,7 +12,7 @@ type Variant { files: [Filesystem] @paginate( defaultCount: 10 - builder: "App\\GraphQL\\Ecosystem\\Queries\\Filesystem\\FilesystemQueries@getFileByGraphType" + builder: "App\\GraphQL\\Ecosystem\\Queries\\Filesystem\\FilesystemQuery@getFileByGraphType" ) interactions(visitor: VisitorEntityInput!): Interactions @method(name: "getEntitySocialInteractions") @@ -20,6 +20,7 @@ type Variant { warehouses: [WarehouseVariantRelationship] attributes: [VariantsAttributes] channels: [VariantChannelRelationship] + companies: Company } type WarehouseVariantRelationship { diff --git a/graphql/schemas/Social/message.graphql b/graphql/schemas/Social/message.graphql new file mode 100644 index 000000000..d392cd778 --- /dev/null +++ b/graphql/schemas/Social/message.graphql @@ -0,0 +1,58 @@ +type Message { + id: Int! + parent_id: Int + parent_unique_id: Mixed + uuid: String! + companies_id: Int! + users_id: Int! + message_types_id: Int! + message: Mixed + reactions_count: Int + comment_count: Int + total_liked: Int + total_saved: Int + parent: Message + user: User! + messageType: MessageType! +} + +input MessageInput { + message_types_id: Int! + message: Mixed! + system_modules_id: Int! + entity_id: Mixed! +} +extend type Mutation @guard { + createMessage(input: MessageInput!): Message + @field( + resolver: "App\\GraphQL\\Social\\Mutations\\Messages\\MessageManagementMutation@create" + ) +} + +extend type Query @guard { + messages( + where: _ + @whereConditions( + columns: [ + "id" + "parent_id" + "parent_unique_id" + "companies_id" + "uuid" + "message_types_id" + "message" + "reactions_count" + "comments_count" + "total_liked" + "total_saved" + "total_shared" + ] + ) + orderBy: _ @orderBy(columns: ["created_at", "updated_at", "id"]) + search: String @search + ): [Message] + @paginate( + defaultCount: 25 + builder: "App\\GraphQL\\Social\\Builders\\Messages\\MessageBuilder@getAll" + ) +} diff --git a/graphql/schemas/Social/messagesTypes.graphql b/graphql/schemas/Social/messagesTypes.graphql new file mode 100644 index 000000000..89d886356 --- /dev/null +++ b/graphql/schemas/Social/messagesTypes.graphql @@ -0,0 +1,40 @@ + +input CreateMessageTypeInput { + languages_id: Int! + name: String! + verb: String! + template: String! + templates_plura: String! +} + +type MessageType { + id: Int! + languages_id: Int! + apps_id: Int! + uuid: String! + name: String! + verb: String! + template: String! + templates_plura: String! +} + +extend type Query { + messageTypes( + where: _@whereConditions( + columns: ["id", "languages_id", "apps_id", "uuid", "name", "verb", "template", "templates_plura"] + ) + ): [MessageType] @paginate( + model: "Kanvas\\Social\\MessagesTypes\\Models\\MessageType" + defaultCount: 25, + scopes: ["fromApp"] + ) +} + + +extend type Mutation @guard { + createMessageType(input: CreateMessageTypeInput!): MessageType! + @field(resolver: "App\\GraphQL\\Social\\Mutations\\Messages\\MessagesTypesMutation@create") + + updateMessageType(id: Int! input: CreateMessageTypeInput): MessageType! + @field(resolver: "App\\GraphQL\\Social\\Mutations\\Messages\\MessagesTypesMutation@update") +} \ No newline at end of file diff --git a/graphql/schemas/Social/userList.graphql b/graphql/schemas/Social/userList.graphql new file mode 100644 index 000000000..47f5db3c2 --- /dev/null +++ b/graphql/schemas/Social/userList.graphql @@ -0,0 +1,78 @@ +input UserListInput { + name: String! + description: String + is_public: Boolean + is_default: Boolean +} + +type UserList @model(class: "\\Kanvas\\Social\\UsersLists\\Models\\UserList"){ + id: Int! + slug: String! + name: String! + description: String + is_public: Boolean + is_default: Boolean! + user: User! + apps: [App] + company: Company! + items: [Message] +} + +extend type Mutation @guard { + createUserList(input: UserListInput!): UserList + @field ( + resolver: "App\\GraphQL\\Social\\Mutations\\UsersLists\\UsersListsManagement@create" + ) + updateUserList(id: Int!, input: UserListInput!): UserList + @field ( + resolver: "App\\GraphQL\\Social\\Mutations\\UsersLists\\UsersListsManagement@update" + ) + deleteUserList(id: Int!): Boolean + @field ( + resolver: "App\\GraphQL\\Social\\Mutations\\UsersLists\\UsersListsManagement@delete" + ) + addToUserList( + users_lists_id: Int!, + messages_id: Int! + ): Boolean + @field ( + resolver: "App\\GraphQL\\Social\\Mutations\\UsersLists\\UsersListsManagement@addToList" + ) + removeFromUserList( + users_lists_id: Int!, + messages_id: Int! + ): Boolean + @field ( + resolver: "App\\GraphQL\\Social\\Mutations\\UsersLists\\UsersListsManagement@removeFromList" + ) +} + +extend type Query @guard { + getUsersLists( + where: _@whereConditions( + columns: [ + "id" + "company_id", + "name", + "description" + ] + ) + orderBy: _ @orderBy(columns: ["created_at", "updated_at", "id"]) + ): [UserList!]! @paginate( + model: "Kanvas\\Social\\UsersLists\\Models\\UserList" + scopes: ["fromApp", "fromUser"] + defaultCount: 25 + ) +} + +extend type Query { + searchUsersLists( + search: String + orderBy: _ @orderBy(columns: ["created_at", "updated_at", "id"]) + ): [UserList!]! @paginate( + # model: "Kanvas\\Social\\UsersLists\\Models\\UserList" + scopes: ["fromApp", "isPublic"] + defaultCount: 25 + builder: "App\\GraphQL\\Social\\Builders\\UsersLists\\SearchBuilder@search" + ) +} \ No newline at end of file diff --git a/helm/.helmignore b/helm/.helmignore index fd1cc75dd..1f5ef540c 100644 --- a/helm/.helmignore +++ b/helm/.helmignore @@ -22,4 +22,8 @@ *.tmproj .vscode/ -pod-cron-scheduler.yaml +# pod-cron-scheduler.yaml + +# vpa-api.yaml +# vpa-queue.yaml +cronjob-health-checker.yaml diff --git a/helm/templates/pod-cron-scheduler.yaml b/helm/templates/cronjob-health-checker.yaml similarity index 97% rename from helm/templates/pod-cron-scheduler.yaml rename to helm/templates/cronjob-health-checker.yaml index 1c7e876f3..2e9514b8d 100644 --- a/helm/templates/pod-cron-scheduler.yaml +++ b/helm/templates/cronjob-health-checker.yaml @@ -3,7 +3,8 @@ kind: CronJob metadata: name: laravel-schedule spec: - successfulJobsHistoryLimit: 1 + successfulJobsHistoryLimit: 0 + failedJobsHistoryLimit: 0 schedule: "* * * * *" jobTemplate: spec: diff --git a/helm/templates/pod-api.yaml b/helm/templates/pod-api.yaml index 89116c5c9..c6efd67db 100644 --- a/helm/templates/pod-api.yaml +++ b/helm/templates/pod-api.yaml @@ -110,7 +110,6 @@ spec: chmod -R 777 /var/www/html/storage/logs && \ chmod -R 777 /var/www/html/bootstrap/cache && \ cd /var/www/html \ - && composer install --no-dev --optimize-autoloader \ && php artisan lighthouse:cache \ && php artisan config:cache" ] diff --git a/helm/templates/pod-queue.yaml b/helm/templates/pod-queue.yaml index 240d018ab..8c985d74f 100644 --- a/helm/templates/pod-queue.yaml +++ b/helm/templates/pod-queue.yaml @@ -54,7 +54,6 @@ spec: chmod -R 777 /var/www/html/storage/logs && \ chmod -R 777 /var/www/html/bootstrap/cache && \ cd /var/www/html \ - && composer install --no-dev --optimize-autoloader \ && php artisan config:cache \ && php artisan queue:work --timeout=400" ] diff --git a/helm/templates/vpa-api.yaml b/helm/templates/vpa-api.yaml new file mode 100644 index 000000000..43c432ecd --- /dev/null +++ b/helm/templates/vpa-api.yaml @@ -0,0 +1,11 @@ +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{.Values.deployments.api.name}} +spec: + targetRef: + apiVersion: "apps/v1" + kind: Deployment + name: {{.Values.deployments.api.name}} + updatePolicy: + updateMode: "Auto" \ No newline at end of file diff --git a/helm/templates/vpa-queue.yaml b/helm/templates/vpa-queue.yaml new file mode 100644 index 000000000..c4a7a5b62 --- /dev/null +++ b/helm/templates/vpa-queue.yaml @@ -0,0 +1,11 @@ +apiVersion: autoscaling.k8s.io/v1 +kind: VerticalPodAutoscaler +metadata: + name: {{.Values.deployments.queue.name}} +spec: + targetRef: + apiVersion: "apps/v1" + kind: Deployment + name: {{.Values.deployments.queue.name}} + updatePolicy: + updateMode: "Auto" \ No newline at end of file diff --git a/src/Baka/Casts/Json.php b/src/Baka/Casts/Json.php new file mode 100644 index 000000000..eef43b698 --- /dev/null +++ b/src/Baka/Casts/Json.php @@ -0,0 +1,33 @@ + $attributes + * @return array + */ + public function get(Model $model, string $key, mixed $value, array $attributes): string|array + { + return Str::isJson($value) ? json_decode($value, true) : $value; + } + + /** + * Prepare the given value for storage. + * + * @param array $attributes + */ + public function set(Model $model, string $key, mixed $value, array $attributes): string|array + { + return Str::isJson($value) || is_array($value) ? json_encode($value) : $value; + } +} diff --git a/src/Baka/Contracts/CompanyInterface.php b/src/Baka/Contracts/CompanyInterface.php index 46d87de41..fe5b1dc78 100644 --- a/src/Baka/Contracts/CompanyInterface.php +++ b/src/Baka/Contracts/CompanyInterface.php @@ -4,9 +4,24 @@ namespace Baka\Contracts; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\Eloquent\Relations\HasOne; + interface CompanyInterface { public function getId(): mixed; public function getUuid(): string; + + public function branches(): HasMany; + + public function defaultBranch(): HasOne; + + public function branch(): HasOne; + + public function groups(): BelongsToMany; + + public function user(): BelongsTo; } diff --git a/src/Baka/Traits/HasCompositePrimaryKeyTrait.php b/src/Baka/Traits/HasCompositePrimaryKeyTrait.php index 6b7b9707a..752fee22e 100644 --- a/src/Baka/Traits/HasCompositePrimaryKeyTrait.php +++ b/src/Baka/Traits/HasCompositePrimaryKeyTrait.php @@ -40,6 +40,7 @@ protected function setKeysForSaveQuery($query) throw new Exception(__METHOD__ . 'Missing part of the primary key: ' . $key); } } + return $query; } diff --git a/src/Baka/Traits/HashTableTrait.php b/src/Baka/Traits/HashTableTrait.php index 86ca0f7ba..75b519ca8 100644 --- a/src/Baka/Traits/HashTableTrait.php +++ b/src/Baka/Traits/HashTableTrait.php @@ -4,7 +4,6 @@ namespace Baka\Traits; -use Baka\Support\Str; use Illuminate\Database\Eloquent\Model; use Kanvas\Exceptions\ConfigurationException; @@ -54,12 +53,21 @@ public function set(string $key, mixed $value): bool $this->settingsModel->{$this->getSettingsPrimaryKey()} = $this->getKey(); } $this->settingsModel->name = $key; - $this->settingsModel->value = ! is_array($value) ? (string) $value : json_encode($value); + $this->settingsModel->value = $value; $this->settingsModel->save(); return true; } + public function setAll(array $settings): bool + { + foreach ($settings as $value) { + $this->set($value['name'], $value['data']); + } + + return true; + } + /** * Get the settings by its key. */ @@ -89,9 +97,7 @@ public function getAllSettings(bool $onlyPublicSettings = false): array } foreach ($settings as $setting) { - $allSettings[$setting->name] = ! Str::isJson($setting->value) - ? $setting->value - : json_decode($setting->value, true); + $allSettings[$setting->name] = $setting->value; } return $allSettings; @@ -111,9 +117,7 @@ public function get(string $key): mixed $value = $this->getSettingsByKey($key); if (is_object($value)) { - return ! Str::isJson($value->value) - ? $value->value - : json_decode($value->value, true); + return $value->value; } return null; diff --git a/src/Baka/Traits/KanvasModelTrait.php b/src/Baka/Traits/KanvasModelTrait.php index e7e43ee31..059fe5c95 100644 --- a/src/Baka/Traits/KanvasModelTrait.php +++ b/src/Baka/Traits/KanvasModelTrait.php @@ -4,11 +4,13 @@ namespace Baka\Traits; +use Baka\Contracts\CompanyInterface; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Facades\Schema; use Kanvas\Apps\Models\Apps; use Kanvas\Companies\Models\Companies; +use Kanvas\Companies\Models\CompaniesBranches; use Kanvas\Enums\StateEnums; use Kanvas\Exceptions\ModelNotFoundException as ExceptionsModelNotFoundException; use Kanvas\Users\Models\Users; @@ -27,6 +29,18 @@ public function getUuid(): string return $this->uuid; } + public static function getByName(string $name): self + { + try { + return self::where('name', $name) + ->notDeleted() + ->firstOrFail(); + } catch (ModelNotFoundException $e) { + //we want to expose the not found msg + throw new ExceptionsModelNotFoundException($e->getMessage()); + } + } + public static function getByUuid(string $uuid): self { try { @@ -51,6 +65,32 @@ public static function getById(mixed $id): self } } + public static function getByIdFromCompany(mixed $id, CompanyInterface $company): self + { + try { + return self::where('id', $id) + ->notDeleted() + ->fromCompany($company) + ->firstOrFail(); + } catch (ModelNotFoundException $e) { + //we want to expose the not found msg + throw new ExceptionsModelNotFoundException($e->getMessage()); + } + } + + public static function getByIdFromBranch(mixed $id, CompaniesBranches $branch): self + { + try { + return self::where('id', $id) + ->notDeleted() + ->where('companies_branches_id', $branch->getId()) + ->firstOrFail(); + } catch (ModelNotFoundException $e) { + //we want to expose the not found msg + throw new ExceptionsModelNotFoundException($e->getMessage()); + } + } + /** * can't use the name company since the scope is also using the same name. * @@ -76,8 +116,6 @@ public function user(): BelongsTo /** * cant use app because of the scope name. - * - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function app(): BelongsTo { @@ -92,8 +130,6 @@ public function app(): BelongsTo * Current soft delete. * * @todo change to laravel default behavior - * - * @return bool */ public function softDelete(): bool { @@ -103,9 +139,19 @@ public function softDelete(): bool } /** - * Get the table name with the connection name. + * restore * - * @return string + * @todo change to laravel default behavior + */ + public function restoreRecord(): bool + { + $this->is_deleted = StateEnums::NO->getValue(); + + return $this->saveOrFail(); + } + + /** + * Get the table name with the connection name. */ public static function getFullTableName(): string { @@ -116,8 +162,6 @@ public static function getFullTableName(): string /** * Get the table name. - * - * @return string */ public static function getTableName(): string { @@ -126,9 +170,6 @@ public static function getTableName(): string /** * Those the given entity have the given column. - * - * @param string $name - * @return bool */ public function hasColumn(string $name): bool { diff --git a/src/Baka/Traits/KanvasScopesTrait.php b/src/Baka/Traits/KanvasScopesTrait.php index d588ba344..9e0364327 100644 --- a/src/Baka/Traits/KanvasScopesTrait.php +++ b/src/Baka/Traits/KanvasScopesTrait.php @@ -10,4 +10,5 @@ trait KanvasScopesTrait use KanvasCompanyScopesTrait; use NotDeletedScopesTrait; use IsPublicScopesTrait; + use KanvasUsersScopesTrait; } diff --git a/src/Baka/Traits/KanvasUsersScopesTrait.php b/src/Baka/Traits/KanvasUsersScopesTrait.php new file mode 100644 index 000000000..c916ce698 --- /dev/null +++ b/src/Baka/Traits/KanvasUsersScopesTrait.php @@ -0,0 +1,16 @@ +where('users_id', auth()->user()->id); + } +} diff --git a/src/Guild/Customers/Actions/CreatePeopleAction.php b/src/Guild/Customers/Actions/CreatePeopleAction.php new file mode 100644 index 000000000..d9a708a84 --- /dev/null +++ b/src/Guild/Customers/Actions/CreatePeopleAction.php @@ -0,0 +1,86 @@ +peopleData->branch->company()->firstOrFail(); + + $attributes = [ + 'users_id' => $this->peopleData->user->getId(), + 'name' => $this->peopleData->firstname . ' ' . $this->peopleData->lastname, + 'dob' => $this->peopleData->dob, + 'google_contact_id' => $this->peopleData->google_contact_id, + 'facebook_contact_id' => $this->peopleData->facebook_contact_id, + 'apple_contact_id' => $this->peopleData->apple_contact_id, + ]; + + //@todo how to avoid duplicated? should it be use or frontend? + if ($this->peopleData->id) { + $people = PeoplesRepository::getById($this->peopleData->id, $company); + $people->update($attributes); + } else { + $attributes['companies_id'] = $company->getId(); + $people = People::create($attributes); + } + + $people->setCustomFields($this->peopleData->custom_fields); + $people->saveCustomFields(); + + if ($this->peopleData->contacts->count()) { + $contacts = []; + foreach ($this->peopleData->contacts as $contact) { + $contacts[] = new Contact([ + 'contacts_types_id' => $contact->contacts_types_id, + 'value' => $contact->value, + 'weight' => $contact->weight, + ]); + } + + $people->contacts()->saveMany($contacts); + } + + if ($this->peopleData->address->count()) { + $addresses = []; + foreach ($this->peopleData->address as $address) { + $addresses[] = new Address([ + 'address' => $address->address, + 'address_2' => $address->address_2, + 'city' => $address->city, + 'state' => $address->state, + 'zip' => $address->zipcode, + //'country' => $address->country, + 'is_default' => $address->is_default, + 'city_id' => $address->city_id ?? 0, + 'state_id' => $address->state_id ?? 0, + 'countries_id' => $address->country_id ?? 0, + ]); + } + + $people->address()->saveMany($addresses); + } + + return $people; + } +} diff --git a/src/Guild/Customers/Actions/UpdatePeopleAction.php b/src/Guild/Customers/Actions/UpdatePeopleAction.php new file mode 100644 index 000000000..06a58640a --- /dev/null +++ b/src/Guild/Customers/Actions/UpdatePeopleAction.php @@ -0,0 +1,80 @@ + $this->peopleData->firstname . ' ' . $this->peopleData->lastname, + 'dob' => $this->peopleData->dob, + 'google_contact_id' => $this->peopleData->google_contact_id, + 'facebook_contact_id' => $this->peopleData->facebook_contact_id, + 'apple_contact_id' => $this->peopleData->apple_contact_id, + ]; + + //@todo how to avoid duplicated? should it be use or frontend? + $this->people->update($attributes); + + $this->people->setCustomFields($this->peopleData->custom_fields); + $this->people->saveCustomFields(); + + if ($this->peopleData->contacts->count()) { + $contacts = []; + $this->people->contacts()->delete(); + foreach ($this->peopleData->contacts as $contact) { + $contacts[] = new Contact([ + 'contacts_types_id' => $contact->contacts_types_id, + 'value' => $contact->value, + 'weight' => $contact->weight, + ]); + } + + $this->people->contacts()->saveMany($contacts); + } + + if ($this->peopleData->address->count()) { + $addresses = []; + $this->people->address()->delete(); + foreach ($this->peopleData->address as $address) { + $addresses[] = new Address([ + 'address' => $address->address, + 'address_2' => $address->address_2, + 'city' => $address->city, + 'state' => $address->state, + 'zip' => $address->zipcode, + //'country' => $address->country, + 'is_default' => $address->is_default, + 'city_id' => $address->city_id ?? 0, + 'state_id' => $address->state_id ?? 0, + 'countries_id' => $address->country_id ?? 0, + ]); + } + + $this->people->address()->saveMany($addresses); + } + + return $this->people; + } +} diff --git a/src/Guild/Customers/DataTransferObject/Address.php b/src/Guild/Customers/DataTransferObject/Address.php new file mode 100644 index 000000000..830f4516e --- /dev/null +++ b/src/Guild/Customers/DataTransferObject/Address.php @@ -0,0 +1,27 @@ + 'datetime:Y-m-d', + ]; + public function address(): HasMany { return $this->hasMany( @@ -53,4 +57,42 @@ public function contacts(): HasMany 'id' ); } + + /** + * @psalm-suppress MixedReturnStatement + */ + public function getEmails(): Collection + { + return $this->contacts() + ->where( + 'contacts_types_id', + ContactType::getByName('Email')->getId() + ) + ->get(); + } + + /** + * @psalm-suppress MixedReturnStatement + */ + public function getPhones(): Collection + { + return $this->contacts() + ->where( + 'contacts_types_id', + ContactType::getByName('Phone')->getId() + ) + ->get(); + } + + public function getFirstAndLastName(): array + { + $name = explode(' ', trim($this->name)); + $firstName = $name[0]; + unset($name[0]); + + return [ + 'firstName' => trim($firstName), + 'lastName' => isset($name[1]) ? implode(' ', $name) : '', + ]; + } } diff --git a/src/Guild/Leads/Actions/CreateLeadAction.php b/src/Guild/Leads/Actions/CreateLeadAction.php new file mode 100644 index 000000000..6d9364538 --- /dev/null +++ b/src/Guild/Leads/Actions/CreateLeadAction.php @@ -0,0 +1,87 @@ +company = $this->leadData->branch->company()->firstOrFail(); + } + + /** + * execute. + */ + public function execute(): Lead + { + $newLead = new Lead(); + $newLead->leads_owner_id = $this->leadData->leads_owner_id; + + if (! $this->leadData->leads_owner_id) { + try { + $newLead->leads_owner_id = LeadsRepository::getDefaultReceiver($this->leadData->branch)->agents_id; + } catch (ModelNotFoundException $e) { + } + } + + $newLead->users_id = $this->leadData->user->getId(); + $newLead->companies_id = $this->company->getId(); + $newLead->companies_branches_id = $this->leadData->branch->getId(); + $newLead->leads_receivers_id = $this->leadData->receiver_id; + $newLead->leads_types_id = $this->leadData->type_id; + $newLead->leads_sources_id = $this->leadData->source_id; + $newLead->title = $this->leadData->title ?? $this->leadData->people->firstname . ' ' . $this->leadData->people->lastname . ' Opps'; + $newLead->firstname = $this->leadData->people->firstname; + $newLead->lastname = $this->leadData->people->lastname; + $newLead->description = $this->leadData->description; + + //create people + $people = (new CreatePeopleAction($this->leadData->people))->execute(); + $newLead->people_id = $people->getId(); + $newLead->saveOrFail(); + + $newLead->setCustomFields($this->leadData->custom_fields); + $newLead->saveCustomFields(); + + //create organization + if ($this->leadData->organization instanceof Organization) { + $organization = (new CreateOrganizationAction($this->leadData->organization))->execute(); + $newLead->organization_id = $organization->getId(); + $newLead->saveOrFail(); + + $organization->addPeople($people); + } + + if ($this->leadAttempt instanceof LeadAttempt) { + $this->leadAttempt->leads_id = $newLead->getId(); + $this->leadAttempt->processed = 1; + $this->leadAttempt->saveOrFail(); + } + + //@todo add workflow + + return $newLead; + } +} diff --git a/src/Guild/Leads/Actions/CreateLeadAttemptAction.php b/src/Guild/Leads/Actions/CreateLeadAttemptAction.php new file mode 100644 index 000000000..53af9664c --- /dev/null +++ b/src/Guild/Leads/Actions/CreateLeadAttemptAction.php @@ -0,0 +1,39 @@ + $this->company->getId(), + 'header' => $this->headers, + 'request' => $this->request, + 'ip' => $this->ip, + 'source' => $this->source, + 'public_key' => $this->request['public_key'] ?? null, + 'processed' => 0, + ]); + } +} diff --git a/src/Guild/Leads/Actions/UpdateLeadAction.php b/src/Guild/Leads/Actions/UpdateLeadAction.php new file mode 100644 index 000000000..5d8358967 --- /dev/null +++ b/src/Guild/Leads/Actions/UpdateLeadAction.php @@ -0,0 +1,125 @@ +lead->company; + $branch = $this->lead->company->branches()->where('id', $this->leadData->branch_id)->firstOrFail(); + + $people = PeoplesRepository::getById($this->leadData->people_id, $company); + + if ($this->leadData->status_id) { + $leadStatus = LeadStatus::getById($this->leadData->status_id); + } + + if ($this->leadData->type_id) { + $leadType = LeadType::getByIdFromCompany( + $this->leadData->type_id, + $company + ); + } + + if ($this->leadData->source_id) { + $leadSource = LeadSource::getByIdFromCompany( + $this->leadData->source_id, + $company + ); + } + + if ($this->leadData->pipeline_stage_id) { + $pipelineStage = PipelineStage::getById($this->leadData->pipeline_stage_id); + $pipeline = Pipeline::getByIdFromCompany( + $pipelineStage->pipelines_id, + $company + ); + } + + $receiver = null; + if ($this->leadData->receiver_id) { + $receiver = LeadReceiver::getByIdFromBranch( + $this->leadData->receiver_id, + $branch + ); + } + + $owner = null; + if ($this->leadData->leads_owner_id) { + $owner = UsersRepository::getUserOfCompanyById($company, $this->leadData->leads_owner_id); + } + + $organization = null; + if ($this->leadData->organization_id) { + $organization = Organization::getByIdFromCompany( + $this->leadData->organization_id, + $company + ); + } + + //cant understand why db connection is switching to another db + $lead = Lead::getById($this->lead->getId()); + $lead->title = $this->leadData->title; + $lead->people_id = $people->getId(); + $lead->firstname = $people->firstname; + $lead->lastname = $people->lastname; + $lead->email = $people->getEmails()->count() ? $people->getEmails()->first()->value : ''; + $lead->leads_status_id = $this->leadData->status_id ? $leadStatus->getId() : 0; + $lead->leads_types_id = $this->leadData->type_id ? $leadType->getId() : null; + $lead->leads_sources_id = $this->leadData->source_id ? $leadSource->getId() : null; + $lead->pipeline_id = $this->leadData->pipeline_stage_id ? $pipeline->getId() : 0; + $lead->pipeline_stage_id = $this->leadData->pipeline_stage_id ? $pipelineStage->getId() : 0; + $lead->leads_receivers_id = $receiver ? $receiver->getId() : 0; + $lead->companies_branches_id = $branch->getId(); + $lead->description = $this->leadData->description ?? ''; + $lead->reason_lost = $this->leadData->reason_lost ?? ''; + $lead->leads_owner_id = $owner ? $owner->getId() : 0; + $lead->organization_id = $organization ? $organization->getId() : 0; + + $lead->saveOrFail(); + + $lead->setCustomFields($this->leadData->custom_fields); + $lead->saveCustomFields(); + + if ($this->leadAttempt) { + $this->leadAttempt->leads_id = $lead->getId(); + $this->leadAttempt->saveOrFail(); + } + + /** + * @psalm-suppress LessSpecificReturnStatement + */ + return $lead; + } +} diff --git a/src/Guild/Leads/DataTransferObject/Lead.php b/src/Guild/Leads/DataTransferObject/Lead.php new file mode 100644 index 000000000..814ce9907 --- /dev/null +++ b/src/Guild/Leads/DataTransferObject/Lead.php @@ -0,0 +1,92 @@ +company, + $branch, + $user + ); + + return new self( + app(Apps::class), + $branch, + $user, + (string) $request['title'], + (int) $request['pipeline_stage_id'], + People::from([ + 'app' => app(Apps::class), + 'branch' => $branch, + 'user' => $user, + 'firstname' => $request['people']['firstname'], + 'lastname' => $request['people']['lastname'], + 'contacts' => Contact::collection($request['people']['contacts']), + 'address' => Address::collection($request['people']['address']), + 'id' => $request['people']['id'] ?? 0, + 'dob' => $request['people']['dob'] ?? null, + 'facebook_contact_id' => $request['people']['facebook_contact_id'] ?? null, + 'google_contact_id' => $request['people']['google_contact_id'] ?? null, + 'apple_contact_id' => $request['people']['apple_contact_id'] ?? null, + 'linkedin_contact_id' => $request['people']['linkedin_contact_id'] ?? null, + ]), + $request['leads_owner_id'] ?? 0, + $request['type_id'] ?? 0, + $request['status_id'] ?? 0, + $request['source_id'] ?? 0, + $request['receiver_id'] ?? 0, + $request['description'] ?? null, + $request['reason_lost'] ?? null, + isset($request['organization']) ? Organization::from([ + 'company' => $branch->company, + 'user' => $user, + ...$request['organization'], + ]) : null, + $request['custom_fields'] ?? [], + ); + } +} diff --git a/src/Guild/Leads/DataTransferObject/LeadUpdateInput.php b/src/Guild/Leads/DataTransferObject/LeadUpdateInput.php new file mode 100644 index 000000000..572d4604f --- /dev/null +++ b/src/Guild/Leads/DataTransferObject/LeadUpdateInput.php @@ -0,0 +1,30 @@ + 'array', + 'header' => 'array', + ]; public function lead(): BelongsTo { diff --git a/src/Guild/Leads/Models/LeadReceiver.php b/src/Guild/Leads/Models/LeadReceiver.php index 3f4db4c7e..18986043c 100644 --- a/src/Guild/Leads/Models/LeadReceiver.php +++ b/src/Guild/Leads/Models/LeadReceiver.php @@ -4,10 +4,11 @@ namespace Kanvas\Guild\Leads\Models; -use Baka\Traits\KanvasScopesTrait; use Baka\Traits\NoAppRelationshipTrait; use Baka\Traits\UuidTrait; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Kanvas\Guild\Models\BaseModel; +use Kanvas\Guild\Rotations\Models\Rotation; /** * Class LeadReceiver. @@ -35,4 +36,12 @@ class LeadReceiver extends BaseModel protected $table = 'leads_receivers'; protected $guarded = []; + + /** + * rotation + */ + public function rotation(): BelongsTo + { + return $this->belongsTo(Rotation::class, 'rotations_id'); + } } diff --git a/src/Guild/Leads/Models/LeadStatus.php b/src/Guild/Leads/Models/LeadStatus.php index c5082cc27..0a64f1eea 100644 --- a/src/Guild/Leads/Models/LeadStatus.php +++ b/src/Guild/Leads/Models/LeadStatus.php @@ -4,7 +4,6 @@ namespace Kanvas\Guild\Leads\Models; -use Baka\Traits\KanvasScopesTrait; use Baka\Traits\NoAppRelationshipTrait; use Kanvas\Guild\Models\BaseModel; @@ -17,6 +16,8 @@ * @property string $created_at * @property string $updated_at * @property int $is_deleted + * + * @todo add company_id */ class LeadStatus extends BaseModel { diff --git a/src/Guild/Leads/Repositories/LeadsRepository.php b/src/Guild/Leads/Repositories/LeadsRepository.php index b721e957c..85734c561 100644 --- a/src/Guild/Leads/Repositories/LeadsRepository.php +++ b/src/Guild/Leads/Repositories/LeadsRepository.php @@ -4,9 +4,14 @@ namespace Kanvas\Guild\Leads\Repositories; +use Baka\Enums\StateEnums; use Baka\Traits\SearchableTrait; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\ModelNotFoundException; +use Kanvas\Companies\Models\CompaniesBranches; +use Kanvas\Exceptions\ModelNotFoundException as ExceptionsModelNotFoundException; use Kanvas\Guild\Leads\Models\Lead; +use Kanvas\Guild\Leads\Models\LeadReceiver; class LeadsRepository { @@ -16,4 +21,14 @@ public static function getModel(): Model { return new Lead(); } + + /** + * @psalm-suppress MixedReturnStatement + */ + public static function getDefaultReceiver(CompaniesBranches $branch): LeadReceiver + { + return LeadReceiver::where('companies_branches_id', $branch->getId()) + ->where('is_default', StateEnums::YES->getValue()) + ->firstOrFail(); + } } diff --git a/src/Guild/Models/BaseModel.php b/src/Guild/Models/BaseModel.php index bb1f36256..0d7c9bed5 100644 --- a/src/Guild/Models/BaseModel.php +++ b/src/Guild/Models/BaseModel.php @@ -22,7 +22,7 @@ class BaseModel extends EloquentModel use SourceTrait; use KanvasModelTrait; use AppsIdTrait; - use CompaniesIdTrait; + //use CompaniesIdTrait; //use KanvasScopesTrait; use HasCustomFields; use HasFilesystemTrait; diff --git a/src/Guild/Organizations/Actions/CreateOrganizationAction.php b/src/Guild/Organizations/Actions/CreateOrganizationAction.php new file mode 100644 index 000000000..fd6095ca4 --- /dev/null +++ b/src/Guild/Organizations/Actions/CreateOrganizationAction.php @@ -0,0 +1,33 @@ + $this->organizationData->name, + 'companies_id' => $this->organizationData->company->getId(), + ], [ + 'address' => $this->organizationData->address, + 'users_id' => $this->organizationData->user->getId(), + ]); + } +} diff --git a/src/Guild/Organizations/Actions/UpdateOrganizationAction.php b/src/Guild/Organizations/Actions/UpdateOrganizationAction.php new file mode 100644 index 000000000..25c3723d9 --- /dev/null +++ b/src/Guild/Organizations/Actions/UpdateOrganizationAction.php @@ -0,0 +1,33 @@ +organization->update([ + 'name' => $this->organizationData->name, + 'address' => $this->organizationData->address, + ]); + + return $this->organization; + } +} diff --git a/src/Guild/Organizations/DataTransferObject/Organization.php b/src/Guild/Organizations/DataTransferObject/Organization.php new file mode 100644 index 000000000..a83467dd6 --- /dev/null +++ b/src/Guild/Organizations/DataTransferObject/Organization.php @@ -0,0 +1,23 @@ + $this->getId(), + 'peoples_id' => $people->getId(), + ], [ + 'created_at' => date('Y-m-d H:i:s'), + + ]); + } } diff --git a/src/Guild/Organizations/Models/OrganizationPeople.php b/src/Guild/Organizations/Models/OrganizationPeople.php index 5f90ce0a0..5dc7207f9 100644 --- a/src/Guild/Organizations/Models/OrganizationPeople.php +++ b/src/Guild/Organizations/Models/OrganizationPeople.php @@ -5,6 +5,7 @@ namespace Kanvas\Guild\Organizations\Models; use Baka\Traits\NoAppRelationshipTrait; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Kanvas\Guild\Customers\Models\People; use Kanvas\Guild\Models\BaseModel; @@ -14,6 +15,7 @@ * * @property int $organizations_id * @property int $peoples_id + * @property string $created_at */ class OrganizationPeople extends BaseModel { @@ -22,6 +24,9 @@ class OrganizationPeople extends BaseModel protected $table = 'organizations_peoples'; protected $guarded = []; + protected $attributes = []; + public $timestamps = false; + public function people(): BelongsTo { return $this->belongsTo(People::class, 'peoples_id', 'id'); @@ -31,4 +36,12 @@ public function organization(): BelongsTo { return $this->belongsTo(Organization::class, 'organizations_id', 'id'); } + + /** + * Not deleted scope. + */ + public function scopeNotDeleted(Builder $query): Builder + { + return $query; + } } diff --git a/src/Guild/Pipelines/Models/Pipeline.php b/src/Guild/Pipelines/Models/Pipeline.php index 653d28304..2a8b9b3d4 100644 --- a/src/Guild/Pipelines/Models/Pipeline.php +++ b/src/Guild/Pipelines/Models/Pipeline.php @@ -5,6 +5,7 @@ namespace Kanvas\Guild\Pipelines\Models; use Baka\Traits\NoAppRelationshipTrait; +use Baka\Traits\SlugTrait; use Illuminate\Database\Eloquent\Relations\HasMany; use Kanvas\Guild\Models\BaseModel; @@ -23,6 +24,7 @@ class Pipeline extends BaseModel { use NoAppRelationshipTrait; + use SlugTrait; protected $table = 'pipelines'; protected $guarded = []; diff --git a/src/Guild/Support/Setup.php b/src/Guild/Support/Setup.php new file mode 100644 index 000000000..d839e2b4e --- /dev/null +++ b/src/Guild/Support/Setup.php @@ -0,0 +1,136 @@ + 'Cold', + 'Warm' => 'Warm', + 'Hot' => 'Hot', + 'IQL' => 'Information Qualified Lead', + 'SRL' => 'Sales-Ready Lead', + 'MQL' => 'Marketing Qualified Leads', + 'SQL' => 'Sales Qualified Lead', + ]; + + public array $leadSources = [ + 'Google', + 'Facebook', + 'Twitter', + 'Instagram', + 'LinkedIn', + 'Youtube', + 'Chat', + 'Email', + 'Phone', + 'WalkIn', + ]; + + public array $defaultStages = [ + 'New', + 'Qualified', + 'Demo Scheduled', + 'Pending Commitment', + 'In Negotiation', + 'Won', + ]; + + /** + * Constructor. + */ + public function __construct( + protected AppInterface $app, + protected UserInterface $user, + protected CompanyInterface $company + ) { + } + + /** + * Setup all the default inventory data for this current company. + */ + public function run(): bool + { + $createSystemModule = new CreateInCurrentAppAction($this->app); + $leadSystemModule = $createSystemModule->execute(Lead::class); + $createSystemModule->execute(People::class); + $createSystemModule->execute(Organization::class); + $createSystemModule->execute(Pipeline::class); + + foreach ($this->leadTypes as $key => $value) { + LeadType::firstOrCreate([ + 'name' => $key, + 'companies_id' => $this->company->getId(), + 'apps_id' => $this->app->getId(), + ], [ + 'description' => $value, + ]); + } + + foreach ($this->leadSources as $key => $value) { + LeadSource::firstOrCreate([ + 'name' => $value, + 'companies_id' => $this->company->getId(), + 'apps_id' => $this->app->getId(), + ], [ + 'description' => $value ?? null, + 'leads_types_id' => null, + ]); + } + + $defaultPipelineName = 'Default Leads'; + $defaultPipeline = Pipeline::firstOrCreate([ + 'name' => $defaultPipelineName, + 'companies_id' => $this->company->getId(), + 'system_modules_id' => $leadSystemModule->getId(), + ], [ + 'users_id' => $this->user->getId(), + 'is_default' => StateEnums::YES->getValue(), + 'weight' => 0, + ]); + + $weight = 1; + foreach ($this->defaultStages as $key => $value) { + PipelineStage::firstOrCreate([ + 'name' => $value, + 'pipelines_id' => $defaultPipeline->getId(), + ], [ + 'weight' => $weight++, + ]); + } + + LeadReceiver::firstOrCreate([ + 'companies_branches_id' => $this->company->defaultBranch()->firstOrFail()->getId(), + 'companies_id' => $this->company->getId(), + 'is_default' => StateEnums::YES->getValue(), + ], [ + 'users_id' => $this->user->getId(), + 'agents_id' => $this->user->getId(), + 'name' => 'Default Receiver', + 'rotations_id' => 0, + 'source_name' => 'Default Receiver', + ]); + + return LeadType::fromCompany()->count() == count($this->leadTypes) && + LeadReceiver::fromCompany($this->company)->count() > 0 && + LeadSource::fromApp($this->app)->fromCompany($this->company)->count() == count($this->leadSources) && + Pipeline::fromCompany($this->company)->count() > 0 && + PipelineStage::where('pipelines_id', $defaultPipeline->getId())->count() == count($this->defaultStages); + } +} diff --git a/src/Inventory/Attributes/Actions/AddAttributeValue.php b/src/Inventory/Attributes/Actions/AddAttributeValue.php new file mode 100644 index 000000000..6797685bd --- /dev/null +++ b/src/Inventory/Attributes/Actions/AddAttributeValue.php @@ -0,0 +1,25 @@ + $this->attributeModel->getId(), + 'value' => $this->value, + ]); + } +} diff --git a/src/Inventory/Attributes/DataTransferObject/Attributes.php b/src/Inventory/Attributes/DataTransferObject/Attributes.php index 25a1755c0..fd3ca82f0 100644 --- a/src/Inventory/Attributes/DataTransferObject/Attributes.php +++ b/src/Inventory/Attributes/DataTransferObject/Attributes.php @@ -17,7 +17,8 @@ public function __construct( public CompanyInterface $company, public AppInterface $app, public UserInterface $user, - public string $name + public string $name, + public string $value, ) { } @@ -27,7 +28,8 @@ public static function viaRequest(array $request): self isset($request['company_id']) ? Companies::getById($request['company_id']) : auth()->user()->getCurrentCompany(), app(Apps::class), auth()->user(), - $request['name'] + $request['name'], + $request['value'] ); } } diff --git a/src/Inventory/Attributes/Models/Attributes.php b/src/Inventory/Attributes/Models/Attributes.php index 718772942..6db454c64 100644 --- a/src/Inventory/Attributes/Models/Attributes.php +++ b/src/Inventory/Attributes/Models/Attributes.php @@ -7,6 +7,7 @@ use Baka\Traits\UuidTrait; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Database\Eloquent\Relations\HasMany; use Kanvas\Apps\Models\Apps; use Kanvas\Companies\Models\Companies; use Kanvas\Inventory\Models\BaseModel; @@ -44,12 +45,20 @@ public function apps(): BelongsTo } /** - * Get the user's first name. + * attributes values */ - protected function value(): Attribute + public function value(): Attribute { return Attribute::make( get: fn () => $this->pivot->value, ); } + + /** + * Attributes can have a default list of values , so we can generate dropdown list + */ + public function defaultValues(): HasMany + { + return $this->hasMany(AttributesValues::class, 'attributes_id'); + } } diff --git a/src/Inventory/Attributes/Models/AttributesValues.php b/src/Inventory/Attributes/Models/AttributesValues.php new file mode 100644 index 000000000..b38b217de --- /dev/null +++ b/src/Inventory/Attributes/Models/AttributesValues.php @@ -0,0 +1,34 @@ +belongsTo(Attributes::class, 'attributes_id'); + } +} diff --git a/src/Inventory/Importer/Actions/ProductImporterAction.php b/src/Inventory/Importer/Actions/ProductImporterAction.php index 560d1050c..92cf79758 100644 --- a/src/Inventory/Importer/Actions/ProductImporterAction.php +++ b/src/Inventory/Importer/Actions/ProductImporterAction.php @@ -224,6 +224,7 @@ public function attributes(): void 'user' => $this->user, 'company' => $this->company, 'name' => $attribute['name'], + 'value' => $attribute['value'] ]); $attributeModel = (new CreateAttribute($attributesDto, $this->user))->execute(); @@ -314,6 +315,7 @@ public function variantsAttributes(VariantsModel $variantModel, array $variantDa 'user' => $this->user, 'company' => $this->company, 'name' => $attribute['name'], + 'value' => $attribute['value'] ]); $attributeModel = (new CreateAttribute($attributesDto, $this->user))->execute(); diff --git a/src/Inventory/Products/Actions/CreateProductAction.php b/src/Inventory/Products/Actions/CreateProductAction.php index c1431ef08..d0077795d 100644 --- a/src/Inventory/Products/Actions/CreateProductAction.php +++ b/src/Inventory/Products/Actions/CreateProductAction.php @@ -4,14 +4,18 @@ namespace Kanvas\Inventory\Products\Actions; +use App\GraphQL\Inventory\Mutations\Variants\Variants; use Baka\Support\Str; use Baka\Users\Contracts\UserInterface; use Carbon\Carbon; use Illuminate\Support\Facades\DB; +use Kanvas\Inventory\Attributes\DataTransferObject\Attributes as AttributesDto; +use Kanvas\Inventory\Attributes\Actions\CreateAttribute; use Kanvas\Companies\Repositories\CompaniesRepository; use Kanvas\Inventory\Categories\Repositories\CategoriesRepository; use Kanvas\Inventory\Products\DataTransferObject\Product as ProductDto; use Kanvas\Inventory\Products\Models\Products; +use Kanvas\Inventory\Variants\Services\Variants as VariantsServices; use Kanvas\Inventory\Warehouses\Repositories\WarehouseRepository; use Throwable; @@ -80,6 +84,25 @@ public function execute(): Products $products->warehouses()->attach($this->productDto->warehouses); } + if ($this->productDto->attributes) { + foreach ($this->productDto->attributes as $attribute) { + $attributesDto = AttributesDto::from([ + 'app' => $this->productDto->app, + 'user' => $this->user, + 'company' => $this->productDto->company, + 'name' => $attribute['name'], + 'value' => $attribute['value'] + ]); + + $attributeModel = (new CreateAttribute($attributesDto, $this->user))->execute(); + (new AddAttributeAction($products, $attributeModel, $attribute['value']))->execute(); + } + } + + if ($this->productDto->variants) { + VariantsServices::createVariantsFromArray($products, $this->productDto->variants, $this->user); + } + DB::connection('inventory')->commit(); } catch (Throwable $e) { DB::connection('inventory')->rollback(); diff --git a/src/Inventory/Products/DataTransferObject/Product.php b/src/Inventory/Products/DataTransferObject/Product.php index 585ea2688..a265b817a 100644 --- a/src/Inventory/Products/DataTransferObject/Product.php +++ b/src/Inventory/Products/DataTransferObject/Product.php @@ -60,6 +60,10 @@ public static function viaRequest(array $request): self $request['is_published'] ?? true, $request['categories'] ?? [], $request['warehouses'] ?? [], + $request['variants'] ?? [], + $request['attributes'] ?? [], + $request['productType'] ?? [], + $request['slug'] ?? null, ); } } diff --git a/src/Inventory/Products/Models/Products.php b/src/Inventory/Products/Models/Products.php index f3fa27ae0..a7d06c810 100644 --- a/src/Inventory/Products/Models/Products.php +++ b/src/Inventory/Products/Models/Products.php @@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; +use Kanvas\Companies\Models\Companies; use Kanvas\Inventory\Attributes\Models\Attributes; use Kanvas\Inventory\Categories\Models\Categories; use Kanvas\Inventory\Models\BaseModel; @@ -101,4 +102,12 @@ public function productsTypes(): BelongsTo { return $this->belongsTo(ProductsTypes::class, 'products_types_id'); } + + /** + * Get the companies that owns the product. + */ + public function companies(): BelongsTo + { + return $this->belongsTo(Companies::class, 'companies_id'); + } } diff --git a/src/Inventory/Traits/CompaniesIdTrait.php b/src/Inventory/Traits/CompaniesIdTrait.php index c8b4c8ace..3ebe51362 100644 --- a/src/Inventory/Traits/CompaniesIdTrait.php +++ b/src/Inventory/Traits/CompaniesIdTrait.php @@ -4,6 +4,9 @@ namespace Kanvas\Inventory\Traits; +/** + * @todo remove this trait + */ trait CompaniesIdTrait { public static function bootCompaniesIdTrait() diff --git a/src/Inventory/Variants/Models/Variants.php b/src/Inventory/Variants/Models/Variants.php index 56e6fcebe..a2a90602e 100644 --- a/src/Inventory/Variants/Models/Variants.php +++ b/src/Inventory/Variants/Models/Variants.php @@ -6,10 +6,15 @@ use Baka\Traits\SlugTrait; use Baka\Traits\UuidTrait; +use Baka\Users\Contracts\UserInterface; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Kanvas\Apps\Models\Apps; use Kanvas\Inventory\Attributes\Models\Attributes; use Kanvas\Inventory\Channels\Models\Channels; +use Kanvas\Inventory\Attributes\DataTransferObject\Attributes as AttributesDto; +use Kanvas\Inventory\Attributes\Actions\CreateAttribute; +use Kanvas\Inventory\Variants\Actions\AddAttributeAction; use Kanvas\Inventory\Enums\AppEnums; use Kanvas\Inventory\Models\BaseModel; use Kanvas\Inventory\Products\Models\Products; @@ -148,4 +153,27 @@ public function channels(): BelongsToMany 'warehouses_id' ); } + + /** + * Add/create new attributes from a variant. + * + * @param ModelVariants $variants + * @param array $attributes + * @return void + */ + public function addAttributes(UserInterface $user, array $attributes): void + { + foreach ($attributes as $attribute) { + $attributesDto = AttributesDto::from([ + 'app' => app(Apps::class), + 'user' => $user, + 'company' => $this->product->companies, + 'name' => $attribute['name'], + 'value' => $attribute['value'] + ]); + + $attributeModel = (new CreateAttribute($attributesDto, $user))->execute(); + (new AddAttributeAction($this, $attributeModel, $attribute['value']))->execute(); + } + } } diff --git a/src/Inventory/Variants/Services/Variants.php b/src/Inventory/Variants/Services/Variants.php new file mode 100644 index 000000000..b7d00dcb9 --- /dev/null +++ b/src/Inventory/Variants/Services/Variants.php @@ -0,0 +1,42 @@ + $product, + 'products_id' => $product->getId(), + ...$variant, + ]); + + $variantModel = (new CreateVariantsAction($variantDto, $user))->execute(); + if (isset($variant['attributes'])) { + $variantModel->addAttributes($user, $variant['attributes']); + } + + $variantsData[] = $variantModel; + } + + return $variantsData; + } +} diff --git a/src/Kanvas/AccessControlList/Actions/AssignAction.php b/src/Kanvas/AccessControlList/Actions/AssignAction.php deleted file mode 100644 index 85b8111b4..000000000 --- a/src/Kanvas/AccessControlList/Actions/AssignAction.php +++ /dev/null @@ -1,28 +0,0 @@ -role)->to($this->entity); - } -} diff --git a/src/Kanvas/AccessControlList/Actions/AssignRoleAction.php b/src/Kanvas/AccessControlList/Actions/AssignRoleAction.php new file mode 100644 index 000000000..f3ba06854 --- /dev/null +++ b/src/Kanvas/AccessControlList/Actions/AssignRoleAction.php @@ -0,0 +1,58 @@ +app = $app ?? app(Apps::class); + } + + /** + * execute. + */ + public function execute(): void + { + // we will only allow one role per user per app + $userRole = Models::query('assigned_roles') + ->where('entity_id', $this->entity->getId()) + ->where('entity_type', Users::class) + ->where('scope', RolesEnums::getScope($this->app)) + ->whereNot('role_id', $this->role->id); + + if ($userRole->count()) { + $userRole->delete(); + } + + Bouncer::assign($this->role->name)->to($this->entity); + + try { + if ($this->entity instanceof Users) { + $this->entity->getAppProfile($this->app)->update([ + 'user_role' => $this->role->id, + ]); + } + } catch(Exception $e) { + //on signups this record might not exist yet , so we ignore it + //the assign company will handle it, not great we will refactor in v2 + } + } +} diff --git a/src/Kanvas/AccessControlList/Actions/CreateRoleAction.php b/src/Kanvas/AccessControlList/Actions/CreateRoleAction.php index 72f65ea23..f504e749e 100644 --- a/src/Kanvas/AccessControlList/Actions/CreateRoleAction.php +++ b/src/Kanvas/AccessControlList/Actions/CreateRoleAction.php @@ -5,9 +5,11 @@ namespace Kanvas\AccessControlList\Actions; use Bouncer; +use Illuminate\Support\Facades\Validator; use Kanvas\AccessControlList\Enums\RolesEnums; use Kanvas\Apps\Models\Apps; use Kanvas\Companies\Models\Companies; +use Kanvas\Exceptions\ValidationException; use Silber\Bouncer\Database\Role as SilberRole; class CreateRoleAction @@ -22,19 +24,29 @@ public function __construct( public string $title, public ?Apps $app = null ) { - if ($app === null) { - $this->app = app(Apps::class); - } + $this->app = $app ?? app(Apps::class); } /** * execute. - * - * @return SilberRole */ public function execute(?Companies $company = null): SilberRole { - Bouncer::scope()->to(RolesEnums::getKey($this->app, $company)); + //Bouncer::scope()->to(RolesEnums::getScope($this->app, $company)); + Bouncer::scope()->to(RolesEnums::getScope($this->app)); + + $validator = Validator::make( + [ + 'name' => $this->name + ], + [ + 'name' => 'required|unique:roles,name,null,id,scope,' . RolesEnums::getScope($this->app), + ] + ); + + if ($validator->fails()) { + throw new ValidationException($validator->errors()->first() . 'for roles in the current app'); + } $role = Bouncer::role()->firstOrCreate([ 'name' => $this->name, diff --git a/src/Kanvas/AccessControlList/Actions/UpdateRoleAction.php b/src/Kanvas/AccessControlList/Actions/UpdateRoleAction.php index 43ba5147e..3f0388b7b 100644 --- a/src/Kanvas/AccessControlList/Actions/UpdateRoleAction.php +++ b/src/Kanvas/AccessControlList/Actions/UpdateRoleAction.php @@ -5,10 +5,12 @@ namespace Kanvas\AccessControlList\Actions; use Illuminate\Auth\Access\AuthorizationException; +use Illuminate\Support\Facades\Validator; use Kanvas\AccessControlList\Enums\RolesEnums; use Kanvas\AccessControlList\Models\Role; use Kanvas\Apps\Models\Apps; use Kanvas\Companies\Models\Companies; +use Kanvas\Exceptions\ValidationException; class UpdateRoleAction { @@ -23,23 +25,32 @@ public function __construct( public ?string $title = null, public ?Apps $app = null ) { - if ($app === null) { - $this->app = app(Apps::class); - } + $this->app = $app ?? app(Apps::class); } /** * execute. - * - * @return Role */ public function execute(?Companies $company = null): Role { + $validator = Validator::make( + [ + 'name' => $this->name, + ], + [ + 'name' => 'required|unique:roles,name,' . $this->id . ',id,scope,' . RolesEnums::getScope($this->app), + ] + ); + + if ($validator->fails()) { + throw new ValidationException($validator->errors()->first() . 'for roles in the current app'); + } + $role = Role::find($this->id); - if ($role->scope !== RolesEnums::getKey($this->app, $company)) { - throw new AuthorizationException('You don\'t have permission to update this role'); - } + /* if ($role->scope !== RolesEnums::getScope($this->app)) { + throw new AuthorizationException('You don\'t have permission to update this role'); + } */ $role->name = $this->name; $role->title = $this->title; diff --git a/src/Kanvas/AccessControlList/Enums/RolesEnums.php b/src/Kanvas/AccessControlList/Enums/RolesEnums.php index 03088cfd9..38e873312 100644 --- a/src/Kanvas/AccessControlList/Enums/RolesEnums.php +++ b/src/Kanvas/AccessControlList/Enums/RolesEnums.php @@ -11,14 +11,10 @@ enum RolesEnums { /** - * Get role Key. - * - * @param Apps $app - * @param Companies|null $company - * - * @return string + * Roles are scoped by app + * in the future companies may create there own roles */ - public static function getKey(Apps $app, ?Companies $company = null): string + public static function getScope(Apps $app, ?Companies $company = null): string { $companyId = $company ? $company->getKey() : AppEnums::GLOBAL_COMPANY_ID->getValue(); diff --git a/src/Kanvas/AccessControlList/Models/Role.php b/src/Kanvas/AccessControlList/Models/Role.php index 5f22eb2aa..5b94fef10 100644 --- a/src/Kanvas/AccessControlList/Models/Role.php +++ b/src/Kanvas/AccessControlList/Models/Role.php @@ -6,6 +6,13 @@ use Silber\Bouncer\Database\Role as SilberRole; +/** + * @property int $id + * @property string $name + * @property string $title + * @property string $scope + */ class Role extends SilberRole { + protected $connection = 'mysql'; } diff --git a/src/Kanvas/AccessControlList/Repositories/RolesRepository.php b/src/Kanvas/AccessControlList/Repositories/RolesRepository.php index b36ace28e..dd3b60076 100644 --- a/src/Kanvas/AccessControlList/Repositories/RolesRepository.php +++ b/src/Kanvas/AccessControlList/Repositories/RolesRepository.php @@ -5,7 +5,6 @@ namespace Kanvas\AccessControlList\Repositories; use Illuminate\Database\Eloquent\Collection; -use Illuminate\Database\Eloquent\Model; use Kanvas\AccessControlList\Enums\RolesEnums; use Kanvas\AccessControlList\Models\Role; use Kanvas\Apps\Models\Apps; @@ -13,42 +12,47 @@ class RolesRepository { + public static function getByMixedParamFromCompany(int|string $param, ?Companies $company = null): Role + { + return is_numeric($param) ? RolesRepository::getByIdFromCompany((int) $param) : RolesRepository::getByNameFromCompany($param); + } + /** - * getAllRoles. - * - * @return ?Collection + * @psalm-suppress MixedReturnStatement */ - public static function getAllRoles(): ?Collection + public static function getByNameFromCompany(string $name, ?Companies $company = null): Role { - return Role::whereNull('scope') - ->orWhere('scope', self::getScope()) - ->orderBy('id', 'desc') - ->get(); + return Role::where('name', $name) + ->where('scope', RolesEnums::getScope(app(Apps::class), null)) + ->firstOrFail(); } /** - * getScope. - * - * @return string + * @psalm-suppress MixedReturnStatement */ - public static function getScope(?Model $user = null, ?Companies $company = null): string + public static function getByIdFromCompany(int $id, ?Companies $company = null): Role { - $app = app(Apps::class); - $user = $user ?? auth()->user(); - $company = $company ?? $user->getCurrentCompany(); + return Role::where('id', $id) + ->where('scope', RolesEnums::getScope(app(Apps::class), null)) + ->firstOrFail(); + } - return RolesEnums::getKey($app, $company); + /** + * getAllRoles. + * @psalm-suppress MixedReturnStatement + */ + public static function getAllRoles(): Collection + { + return Role::where('scope', RolesEnums::getScope(app(Apps::class), null)) + ->orderBy('id', 'desc') + ->get(); } /** * Get app list of default roles. - * - * @param Apps $app - * - * @return Collection */ public static function getAppRoles(Apps $app): Collection { - return Role::where('scope', RolesEnums::getKey($app))->get(); + return Role::where('scope', RolesEnums::getScope($app))->get(); } } diff --git a/src/Kanvas/Apps/Actions/CreateAppsAction.php b/src/Kanvas/Apps/Actions/CreateAppsAction.php index b4cee73bc..9fa4dd92d 100644 --- a/src/Kanvas/Apps/Actions/CreateAppsAction.php +++ b/src/Kanvas/Apps/Actions/CreateAppsAction.php @@ -5,6 +5,7 @@ namespace Kanvas\Apps\Actions; use Illuminate\Support\Facades\DB; +use Kanvas\AccessControlList\Actions\CreateRoleAction; use Kanvas\Apps\DataTransferObject\AppInput; use Kanvas\Apps\Enums\DefaultRoles; use Kanvas\Apps\Models\Apps; @@ -158,6 +159,13 @@ public function acl(Apps $app): void 'is_active' => 1, 'scope' => 0, ]); + + $newRole = new CreateRoleAction( + $role, + $role, + $app + ); + $newRole->execute(); } } } diff --git a/src/Kanvas/Apps/Models/Settings.php b/src/Kanvas/Apps/Models/Settings.php index 8b52959fd..51c376a50 100644 --- a/src/Kanvas/Apps/Models/Settings.php +++ b/src/Kanvas/Apps/Models/Settings.php @@ -29,6 +29,10 @@ class Settings extends BaseModel protected $primaryKey = ['apps_id', 'name']; + protected $casts = [ + 'value' => 'array', + ]; + /** * Apps relationship. * diff --git a/src/Kanvas/Auth/Actions/RegisterUsersAction.php b/src/Kanvas/Auth/Actions/RegisterUsersAction.php index 1f29274cf..1abb81a83 100644 --- a/src/Kanvas/Auth/Actions/RegisterUsersAction.php +++ b/src/Kanvas/Auth/Actions/RegisterUsersAction.php @@ -7,6 +7,9 @@ use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Illuminate\Validation\ValidationException; +use Kanvas\AccessControlList\Actions\AssignRoleAction; +use Kanvas\AccessControlList\Repositories\RolesRepository; +use Kanvas\Apps\Enums\DefaultRoles; use Kanvas\Apps\Models\Apps; use Kanvas\Auth\DataTransferObject\RegisterInput; use Kanvas\Auth\Exceptions\AuthenticationException; @@ -18,7 +21,6 @@ use Kanvas\Notifications\Templates\Welcome; use Kanvas\Users\Enums\StatusEnums; use Kanvas\Users\Models\Users; -use Kanvas\Users\Models\UsersAssociatedApps; use Kanvas\Users\Repositories\UsersRepository; class RegisterUsersAction @@ -102,13 +104,21 @@ public function execute(): Users $user->password = $this->data->password; $user->language = $user->language ?: AppEnums::DEFAULT_LANGUAGE->getValue(); $user->user_activation_key = Hash::make(time()); - $user->roles_id = $this->data->roles_id ?? AppEnums::DEFAULT_ROLE_ID->getValue(); + $user->roles_id = $this->data->roles_id ?? AppEnums::DEFAULT_ROLE_ID->getValue(); //@todo : remove this , legacy code //create a new user assign it to the app and create the default company $user->saveOrFail(); $userRegisterInApp = new RegisterUsersAppAction($user); $userRegisterInApp->execute($this->data->password); + + $userRole = RolesRepository::getByMixedParamFromCompany($this->data->roles_id ?? DefaultRoles::ADMIN->getValue()); + + $assignRole = new AssignRoleAction( + $user, + $userRole + ); + $assignRole->execute(); } try { diff --git a/src/Kanvas/Auth/Actions/SocialLoginAction.php b/src/Kanvas/Auth/Actions/SocialLoginAction.php index 7bcc7d55f..4573c2480 100644 --- a/src/Kanvas/Auth/Actions/SocialLoginAction.php +++ b/src/Kanvas/Auth/Actions/SocialLoginAction.php @@ -4,13 +4,13 @@ namespace Kanvas\Auth\Actions; +use Illuminate\Support\Str; use Kanvas\Apps\Models\Apps; use Kanvas\Auth\DataTransferObject\RegisterInput; -use Kanvas\Users\Models\Users; -use Laravel\Socialite\Two\User as SocialiteUser; use Kanvas\Users\Models\Sources; use Kanvas\Users\Models\UserLinkedSources; -use Illuminate\Support\Str; +use Kanvas\Users\Models\Users; +use Laravel\Socialite\Two\User as SocialiteUser; class SocialLoginAction { @@ -20,7 +20,7 @@ class SocialLoginAction * Construct function. */ public function __construct( - protected SocialiteUser $socialUser, + protected SocialiteUser $socialUser, protected string $provider ) { } @@ -30,22 +30,21 @@ public function __construct( * * @param SocialiteUser $socialUser * @param string $provider - * @return Users */ public function execute(): Users { $source = Sources::where('title', $this->provider)->firstOrFail(); $userLinkedSource = UserLinkedSources::where('source_users_id', $this->socialUser->id)->where('source_id', $source->id)->first(); - if (!$userLinkedSource) { + if (! $userLinkedSource) { $existedUser = Users::where('email', $this->socialUser->email)->first(); - if (!$existedUser) { + if (! $existedUser) { $userData = [ 'firstname' => $this->socialUser->name, 'email' => $this->socialUser->email, 'password' => Str::random(11), - 'displayname' => $this->socialUser->nickname + 'displayname' => $this->socialUser->nickname, ]; $userData = RegisterInput::fromArray($userData); @@ -53,7 +52,15 @@ public function execute(): Users $existedUser = $registeredUser->execute(); } - $userLinkedSource = UserLinkedSources::createSocial($this->socialUser, $existedUser, $source); + //$userLinkedSource = UserLinkedSources::createSocial($this->socialUser, $existedUser, $source); + UserLinkedSources::firstOrCreate([ + 'users_id' => $existedUser->getId(), + 'source_id' => $source->getId(), + 'source_users_id' => $this->socialUser->id, + ], [ + 'source_users_id_text' => $this->socialUser->token, + 'source_username' => $this->socialUser->nickname ?? $this->socialUser->name, + ]); } return $userLinkedSource->user; diff --git a/src/Kanvas/Auth/Services/ForgotPassword.php b/src/Kanvas/Auth/Services/ForgotPassword.php index c7a14ebd3..fd5b0506d 100644 --- a/src/Kanvas/Auth/Services/ForgotPassword.php +++ b/src/Kanvas/Auth/Services/ForgotPassword.php @@ -15,9 +15,6 @@ class ForgotPassword { protected Apps $app; - /** - * Construct function. - */ public function __construct() { $this->app = app(Apps::class); @@ -25,8 +22,6 @@ public function __construct() /** * Send email forgot password. - * - * @param array $data */ public function forgot(string $email): Users { @@ -44,18 +39,16 @@ public function forgot(string $email): Users /** * Get user and update password to the new one. - * - * @param array $data */ public function reset(string $newPassword, string $hashKey): bool { - $recoverUser = UsersAssociatedApps::fromApp() + $recoverUser = UsersAssociatedApps::fromApp($this->app) ->notDeleted() ->where([ - 'companies_id' => AppEnums::GLOBAL_APP_ID->getValue(), + 'companies_id' => AppEnums::GLOBAL_COMPANY_ID->getValue(), 'user_activation_forgot' => $hashKey, ])->firstOrFail(); - return $recoverUser->resetPassword($newPassword); + return $recoverUser->user()->firstOrFail()->resetPassword($newPassword, $this->app); } } diff --git a/src/Kanvas/Auth/Services/UserManagement.php b/src/Kanvas/Auth/Services/UserManagement.php index 63155e631..94e57b9ed 100644 --- a/src/Kanvas/Auth/Services/UserManagement.php +++ b/src/Kanvas/Auth/Services/UserManagement.php @@ -4,6 +4,7 @@ namespace Kanvas\Auth\Services; +use Illuminate\Support\Arr; use Kanvas\Apps\Models\Apps; use Kanvas\Exceptions\InternalServerErrorException; use Kanvas\Users\Models\Users; @@ -27,7 +28,16 @@ public function __construct( public function update(array $data): Users { try { + $customFields = null; + if (Arr::exists($data, 'custom_fields')) { + $customFields = $data['custom_fields']; + unset($data['custom_fields']); + } $this->user->update(array_filter($data)); + + if ($customFields) { + $this->user->setAll($customFields); + } } catch (InternalServerErrorException $e) { throw new InternalServerErrorException($e->getMessage()); } diff --git a/src/Kanvas/Companies/Models/Companies.php b/src/Kanvas/Companies/Models/Companies.php index 14108ddee..8964c62b2 100644 --- a/src/Kanvas/Companies/Models/Companies.php +++ b/src/Kanvas/Companies/Models/Companies.php @@ -76,6 +76,7 @@ public function branches(): HasMany /** * Default Branch. + * @psalm-suppress MixedReturnStatement */ public function defaultBranch(): HasOne { @@ -95,8 +96,6 @@ public function branch(): HasOne /** * CompaniesGroups relationship. - * - * @return hasMany */ public function groups(): BelongsToMany { @@ -149,6 +148,7 @@ public function branchCacheKey(): string /** * Associate user to this company. + * @psalm-suppress MixedReturnStatement */ public function associateUser( Users $user, @@ -173,7 +173,7 @@ public function associateUser( /** * Associate user to the app. - * @deprecated v2.0.0 use registerUserApp instead + * @psalm-suppress MixedReturnStatement */ public function associateUserApp( Users $user, @@ -197,6 +197,7 @@ public function associateUserApp( /** * Associate company to the app. + * @psalm-suppress MixedReturnStatement */ public function associateApp(Apps $app): UserCompanyApps { diff --git a/src/Kanvas/Companies/Repositories/CompaniesRepository.php b/src/Kanvas/Companies/Repositories/CompaniesRepository.php index 78920541b..225cc38b9 100644 --- a/src/Kanvas/Companies/Repositories/CompaniesRepository.php +++ b/src/Kanvas/Companies/Repositories/CompaniesRepository.php @@ -19,6 +19,7 @@ class CompaniesRepository { /** * Get company by Id. + * @psalm-suppress MixedReturnStatement * * @throws ModelNotFoundException */ @@ -31,6 +32,7 @@ public static function getById(int $id): Companies /** * Get by uuid. + * @psalm-suppress MixedReturnStatement */ public static function getByUuid(string $uuid): Companies { @@ -41,6 +43,7 @@ public static function getByUuid(string $uuid): Companies /** * User belongs / has permission in this company. + * @psalm-suppress MixedReturnStatement * * @throws ExceptionsModelNotFoundException */ @@ -58,7 +61,7 @@ public static function userAssociatedToCompany(Companies $company, Users $user): /** * User belongs / has permission in this company. - * + * @psalm-suppress MixedReturnStatement * @throws ExceptionsModelNotFoundException */ public static function userAssociatedToCompanyAndBranch(Companies $company, CompaniesBranches $branch, Users $user): UsersAssociatedCompanies @@ -76,7 +79,7 @@ public static function userAssociatedToCompanyAndBranch(Companies $company, Comp /** * User associated to this company on the current app. - * + * @psalm-suppress MixedReturnStatement * @throws ExceptionsModelNotFoundException */ public static function userAssociatedToCompanyInThisApp(Apps $app, Companies $company, Users $user): UsersAssociatedApps diff --git a/src/Kanvas/CustomFields/Traits/HasCustomFields.php b/src/Kanvas/CustomFields/Traits/HasCustomFields.php index 884edc858..514350231 100644 --- a/src/Kanvas/CustomFields/Traits/HasCustomFields.php +++ b/src/Kanvas/CustomFields/Traits/HasCustomFields.php @@ -26,8 +26,6 @@ trait HasCustomFields /** * Get the custom field primary key * for faster access via redis. - * - * @return string */ public function getCustomFieldPrimaryKey(): string { @@ -36,8 +34,6 @@ public function getCustomFieldPrimaryKey(): string /** * Get all custom fields of the given object. - * - * @return array */ public function getAllCustomFields(): array { @@ -46,12 +42,10 @@ public function getAllCustomFields(): array /** * Get all the custom fields. - * - * @return array */ public function getAll(): array { - if (!empty($listOfCustomFields = $this->getAllFromRedis())) { + if (! empty($listOfCustomFields = $this->getAllFromRedis())) { return $listOfCustomFields; } @@ -67,13 +61,13 @@ public function getAll(): array ', [ $companyId, get_class($this), - $this->getKey() + $this->getKey(), ]); $listOfCustomFields = []; foreach ($results as $row) { - $listOfCustomFields[$row['name']] = Str::jsonToArray($row['value']); + $listOfCustomFields[$row->name] = Str::jsonToArray($row->value); } return $listOfCustomFields; @@ -81,8 +75,6 @@ public function getAll(): array /** * Get all the custom fields from redis. - * - * @return array */ public function getAllFromRedis(): array { @@ -100,8 +92,6 @@ public function getAllFromRedis(): array /** * Get the Custom Field. * - * @param string $name - * * @return mixed */ public function get(string $name) @@ -119,10 +109,6 @@ public function get(string $name) /** * Delete key from custom Fields. - * - * @param string $name - * - * @return bool */ public function del(string $name): bool { @@ -140,10 +126,6 @@ public function del(string $name): bool /** * Get a Custom Field. - * - * @param string $name - * - * @return AppsCustomFields|null */ public function getCustomField(string $name): ?AppsCustomFields { @@ -156,10 +138,6 @@ public function getCustomField(string $name): ?AppsCustomFields /** * Get custom field from redis. - * - * @param string $name - * - * @return mixed */ protected function getFromRedis(string $name): mixed { @@ -174,10 +152,7 @@ protected function getFromRedis(string $name): mixed /** * Set value. * - * @param string $name * @param mixed $value - * - * @return AppsCustomFields */ public function set(string $name, $value): AppsCustomFields { @@ -193,7 +168,7 @@ public function set(string $name, $value): AppsCustomFields 'companies_id' => $companyId, 'model_name' => $modelName, 'entity_id' => $this->getKey(), - 'name' => $name + 'name' => $name, ], [ 'companies_id' => $companyId, 'users_id' => $user !== null ? $user->getKey() : AppEnums::GLOBAL_USER_ID->getValue(), @@ -201,16 +176,12 @@ public function set(string $name, $value): AppsCustomFields 'entity_id' => $this->getKey(), 'label' => $name, 'name' => $name, - 'value' => !is_array($value) ? $value : json_encode($value) + 'value' => ! is_array($value) ? $value : json_encode($value), ]); } /** * Create a new Custom Fields. - * - * @param string $name - * - * @return CustomFields */ public function createCustomField(string $name): CustomFields { @@ -223,11 +194,11 @@ public function createCustomField(string $name): CustomFields $customFieldModules = CustomFieldsModules::firstOrCreate([ 'model_name' => get_class($this), - 'apps_id' => $appsId + 'apps_id' => $appsId, ], [ 'model_name' => get_class($this), 'name' => get_class($this), - 'apps_id' => $appsId + 'apps_id' => $appsId, ]); $customField = CustomFields::firstOrCreate([ @@ -249,18 +220,13 @@ public function createCustomField(string $name): CustomFields /** * Set custom field in redis. - * - * @param string $name - * @param mixed $value - * - * @return bool */ protected function setInRedis(string $name, mixed $value): bool { return (bool) Redis::hSet( $this->getCustomFieldPrimaryKey(), $name, - !is_array($value) ? $value : json_encode($value) + ! is_array($value) ? $value : json_encode($value) ); } @@ -275,7 +241,7 @@ public function saveCustomFields(): bool { if ($this->hasCustomFields()) { foreach ($this->customFields as $key => $value) { - if (!self::schemaHasColumn($key)) { + if (! self::schemaHasColumn($key)) { $this->set($key, $value); } } @@ -288,8 +254,6 @@ public function saveCustomFields(): bool * Remove all the custom fields from the entity. * * @param int $id - * - * @return bool */ public function deleteAllCustomFields(): bool { @@ -306,14 +270,12 @@ public function deleteAllCustomFields(): bool AND entity_id = :entity_id', [ 'companies_id' => $companyId, 'model_name' => get_class($this), - 'entity_id' => $this->getKey() + 'entity_id' => $this->getKey(), ]); } /** * Delete all custom fields from redis. - * - * @return bool */ protected function deleteAllCustomFieldsFromRedis(): bool { @@ -324,30 +286,36 @@ protected function deleteAllCustomFieldsFromRedis(): bool /** * Set the custom field to update a custom field module. - * - * @param array $fields */ public function setCustomFields(array $fields) { + if (empty($fields)) { + return; + } + + /*** + * if column name exist this is a CustomFieldEntityInput + * we need to convert it to key value + */ + if (isset($fields[0]) && array_key_exists('name', $fields[0])) { + $fields = array_column($fields, 'data', 'name'); + } + $this->customFields = $fields; } /** * Does this model have custom fields? - * - * @return bool */ public function hasCustomFields(): bool { - return !empty($this->customFields); + return ! empty($this->customFields); } /** * If something happened to redis * And we need to re insert all the custom fields * for this entity , we run this method. - * - * @return void */ public function reCacheCustomFields(): void { @@ -359,16 +327,13 @@ public function reCacheCustomFields(): void /** * Get a model from a custom field. * - * @param string $name - * @param mixed $value * @param Companies $company - * - * @return Model|null */ public static function getByCustomField(string $name, mixed $value, ?Companies $company = null): ?Model { $company = $company ? $company->getKey() : AppEnums::GLOBAL_COMPANY_ID->getValue(); $table = (new static())->getTable(); + return self::join(DB::connection('ecosystem')->getDatabaseName() . '.apps_custom_fields', 'apps_custom_fields.entity_id', '=', $table . '.id') ->where('apps_custom_fields.companies_id', $company) ->where('apps_custom_fields.model_name', static::class) diff --git a/src/Kanvas/Enums/AppEnums.php b/src/Kanvas/Enums/AppEnums.php index 884767531..1a6087bbf 100644 --- a/src/Kanvas/Enums/AppEnums.php +++ b/src/Kanvas/Enums/AppEnums.php @@ -70,7 +70,7 @@ public function getValue(): mixed self::DEFAULT_APP_NAME => 'Default', self::DEFAULT_COUNTRY => 'USA', self::DEFAULT_USER_LEVEL => 3, - self::DEFAULT_ROLE_ID => 2, + self::DEFAULT_ROLE_ID => 1, self::CURRENCY => 'USD', self::FILESYSTEM => 's3', self::ALLOW_USER_REGISTRATION => 1, @@ -92,7 +92,7 @@ public function getValue(): mixed self::KANVAS_APP_BRANCH_HEADER => 'X-Kanvas-Location', self::KANVAS_APP_COMPANY_AUTH_HEADER => 'Company-Authorization', //@deprecated self::DISPLAYNAME_LOGIN => 'displayname_login', - self::VERSION => '1.0-BETA-5', + self::VERSION => '1.0-BETA-6', }; } diff --git a/src/Kanvas/Enums/SourceEnum.php b/src/Kanvas/Enums/SourceEnum.php new file mode 100644 index 000000000..14944360f --- /dev/null +++ b/src/Kanvas/Enums/SourceEnum.php @@ -0,0 +1,13 @@ + + */ + public function definition() + { + return [ + 'name' => fake()->name(), + 'title' => fake()->name(), + 'order' => 0, + 'id' => Languages::latest()->first() ? Languages::latest()->first()->id + 1 : 1, + ]; + } +} diff --git a/src/Kanvas/Languages/Models/Languages.php b/src/Kanvas/Languages/Models/Languages.php index 0a53afb40..badf14986 100644 --- a/src/Kanvas/Languages/Models/Languages.php +++ b/src/Kanvas/Languages/Models/Languages.php @@ -6,6 +6,8 @@ use GeneaLabs\LaravelModelCaching\Traits\Cachable; use Kanvas\Models\BaseModel; +use Illuminate\Database\Eloquent\Factories\HasFactory; +use Kanvas\Languages\Factories\LanguagesFactory; /** * Languages Class. @@ -16,7 +18,9 @@ */ class Languages extends BaseModel { - use Cachable; + // use Cachable; + use HasFactory; + public $incrementing = false; /** * The table associated with the model. @@ -24,4 +28,9 @@ class Languages extends BaseModel * @var string */ protected $table = 'languages'; + + protected static function newFactory() + { + return LanguagesFactory::new(); + } } diff --git a/src/Kanvas/Notifications/Notification.php b/src/Kanvas/Notifications/Notification.php index c0f4a9405..23d5f8ba7 100644 --- a/src/Kanvas/Notifications/Notification.php +++ b/src/Kanvas/Notifications/Notification.php @@ -34,7 +34,7 @@ class Notification extends LaravelNotification implements EmailInterfaces, Shoul protected ?UserInterface $toUser = null; public array $channels = [ - 'mail' + 'mail', ]; public function __construct(Model $entity) @@ -44,7 +44,6 @@ public function __construct(Model $entity) $this->data = [ 'entity' => $this->entity, 'app' => $this->app, - 'user' => $this->toUser ? $this->toUser : null, ]; } @@ -72,6 +71,10 @@ public function via(object $notifiable): array $channels = array_values($enabledChannels); } + //set the user + $this->data['user'] = $notifiable; + $this->toUser = $notifiable; + return [ KanvasDatabaseChannel::class, ...$channels, @@ -87,7 +90,6 @@ public function toMail($notifiable): ?MailMessage { $fromEmail = $this->app->get('from_email_address') ?? config('mail.from.address'); $fromName = $this->app->get('from_email_name') ?? config('mail.from.name'); - $this->toUser = $notifiable; return (new MailMessage()) ->from($fromEmail, $fromName) diff --git a/src/Kanvas/Notifications/Templates/ResetPassword.php b/src/Kanvas/Notifications/Templates/ResetPassword.php index c2eeb795f..7b0441c4d 100644 --- a/src/Kanvas/Notifications/Templates/ResetPassword.php +++ b/src/Kanvas/Notifications/Templates/ResetPassword.php @@ -10,9 +10,10 @@ class ResetPassword extends Notification public function getData(): array { + //replace url for app link return [ ...parent::getData(), - 'resetUrl' => $this->app->url . '/users/reset-password/' . $this->toUser->user_activation_forgot, + 'resetUrl' => $this->app->get('url') . '/reset-password/' . $this->toUser->getAppProfile($this->app)->user_activation_forgot, ]; } } diff --git a/src/Kanvas/SystemModules/Actions/CreateInCurrentAppAction.php b/src/Kanvas/SystemModules/Actions/CreateInCurrentAppAction.php index 300d4de2e..6d7d56c89 100644 --- a/src/Kanvas/SystemModules/Actions/CreateInCurrentAppAction.php +++ b/src/Kanvas/SystemModules/Actions/CreateInCurrentAppAction.php @@ -20,9 +20,7 @@ public function __construct( } /** - * Invoke function. - * - * @return SystemModules + * @psalm-suppress MixedReturnStatement */ public function execute(string $class): SystemModules { diff --git a/src/Kanvas/Users/Actions/AssignCompanyAction.php b/src/Kanvas/Users/Actions/AssignCompanyAction.php index 98824588c..4e83e2392 100644 --- a/src/Kanvas/Users/Actions/AssignCompanyAction.php +++ b/src/Kanvas/Users/Actions/AssignCompanyAction.php @@ -4,8 +4,7 @@ namespace Kanvas\Users\Actions; -use Bouncer; -use Kanvas\AccessControlList\Actions\AssignAction; +use Kanvas\AccessControlList\Actions\AssignRoleAction; use Kanvas\AccessControlList\Models\Role; use Kanvas\AccessControlList\Repositories\RolesRepository; use Kanvas\Apps\Enums\DefaultRoles; @@ -31,7 +30,7 @@ public function __construct( ?Apps $app = null ) { $this->user = $user; - $this->company = $branch->company()->first(); + $this->company = $branch->company()->firstOrFail(); $this->branch = $branch; $this->role = $role ?? DefaultRoles::ADMIN; $this->app = $app ?? app(Apps::class); @@ -57,22 +56,17 @@ public function execute(): void $this->branch ); - $this->company->associateUserApp( + $userAssociatedAppCompany = $this->company->associateUserApp( $this->user, $app, StateEnums::ON->getValue() ); - Bouncer::scope()->to(RolesRepository::getScope($this->user)); - - if ($this->user->roles_id) { - $role = Role::find($this->user->roles_id)->name; - $assignRole = new AssignAction($this->user, $role); - $assignRole->execute(); - } else { - $assignRole = new AssignAction($this->user, $this->role::ADMIN->getValue()); - $assignRole->execute(); - } + $assignRole = new AssignRoleAction( + $userAssociatedAppCompany, + RolesRepository::getByNameFromCompany($this->role->getValue()), + ); + $assignRole->execute(); if (! $roleLegacy = $app->get(AppSettingsEnums::DEFAULT_ROLE_NAME->getValue())) { $roleLegacy = $app->name . '.' . $this->user->role()->first()->name; diff --git a/src/Kanvas/Users/Actions/CreateInviteAction.php b/src/Kanvas/Users/Actions/CreateInviteAction.php index 00855a36b..4d0587d27 100644 --- a/src/Kanvas/Users/Actions/CreateInviteAction.php +++ b/src/Kanvas/Users/Actions/CreateInviteAction.php @@ -5,6 +5,7 @@ namespace Kanvas\Users\Actions; use Illuminate\Support\Str; +use Kanvas\AccessControlList\Repositories\RolesRepository; use Kanvas\Apps\Models\Apps; use Kanvas\Companies\Models\CompaniesBranches; use Kanvas\Companies\Repositories\CompaniesRepository; @@ -35,6 +36,12 @@ public function execute(): UsersInvite $this->user ); + //validate role + RolesRepository::getByIdFromCompany( + $this->inviteDto->role_id, + $company + ); + $invite = new UsersInvite(); $invite->fill([ 'invite_hash' => Str::random(50), diff --git a/src/Kanvas/Users/Actions/RemoveCompanyAction.php b/src/Kanvas/Users/Actions/RemoveCompanyAction.php index c0585830c..a0e0abaff 100644 --- a/src/Kanvas/Users/Actions/RemoveCompanyAction.php +++ b/src/Kanvas/Users/Actions/RemoveCompanyAction.php @@ -8,8 +8,10 @@ use Kanvas\Apps\Models\Apps; use Kanvas\Companies\Models\Companies; use Kanvas\Companies\Models\CompaniesBranches; +use Kanvas\Enums\AppEnums; use Kanvas\Enums\StateEnums; use Kanvas\Users\Models\Users; +use Kanvas\Users\Models\UsersAssociatedApps; class RemoveCompanyAction { @@ -41,24 +43,27 @@ public function execute(): void StateEnums::YES->getValue(), )->delete(); - $this->company->associateUser( - $this->user, - StateEnums::YES->getValue(), - $this->branch - )->delete(); - - $this->company->associateUser( - $this->user, - StateEnums::YES->getValue(), - CompaniesBranches::getGlobalBranch() - )->delete(); + $otherAssociation = UsersAssociatedApps::where('users_id', $this->user->getId()) + ->where('apps_id', $this->app->getId()) + ->whereNot('companies_id', AppEnums::GLOBAL_COMPANY_ID->getValue()) + ->get(); - if ($this->user->get(Companies::cacheKey())) { - $this->user->del(Companies::cacheKey()); + if ($otherAssociation->count()) { + $newPrimaryCompany = $otherAssociation->first(); + $newCompany = Companies::getById($newPrimaryCompany->companies_id); + $this->user->set(Companies::cacheKey(), $newCompany->getId()); } - if ($this->user->get($this->company->branchCacheKey())) { - $this->user->del($this->company->branchCacheKey()); + $stillHasAccessToThisCompany = UsersAssociatedApps::where('users_id', $this->user->getId()) + ->where('companies_id', $this->company->getId()) + ->get(); + + if (! $stillHasAccessToThisCompany->count()) { + $this->company->associateUser( + $this->user, + StateEnums::YES->getValue(), + $this->branch + )->delete(); } } } diff --git a/src/Kanvas/Users/Models/UserConfig.php b/src/Kanvas/Users/Models/UserConfig.php index c8bc016c7..8032ccef1 100644 --- a/src/Kanvas/Users/Models/UserConfig.php +++ b/src/Kanvas/Users/Models/UserConfig.php @@ -30,10 +30,12 @@ class UserConfig extends BaseModel protected $attributes = [ ]; + protected $casts = [ + 'value' => 'array', + ]; + /** * Users relationship. - * - * @return BelongsTo */ public function user(): BelongsTo { diff --git a/src/Kanvas/Users/Models/UserLinkedSources.php b/src/Kanvas/Users/Models/UserLinkedSources.php index a33a80cb5..50aaaa53d 100644 --- a/src/Kanvas/Users/Models/UserLinkedSources.php +++ b/src/Kanvas/Users/Models/UserLinkedSources.php @@ -6,7 +6,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Kanvas\Models\BaseModel; -use Laravel\Socialite\Two\User as SocialiteUser; /** * User Linked Sources Model. @@ -29,13 +28,11 @@ class UserLinkedSources extends BaseModel 'source_id', 'source_users_id', 'source_users_id_text', - 'source_username' + 'source_username', ]; /** * Users relationship. - * - * @return Users */ public function user(): BelongsTo { @@ -44,32 +41,9 @@ public function user(): BelongsTo /** * Users relationship. - * - * @return Users */ public function source(): BelongsTo { return $this->belongsTo(Sources::class, 'source_id'); } - - /** - * Create user link source based on social provider - * - * @param SocialiteUser $socialUser - * @param Users $user - * @param Sources $source - * @return UserLinkedSources - */ - public static function createSocial(SocialiteUser $socialUser, Users $user, Sources $source): self - { - $linked = new self(); - $linked->users_id = $user->id; - $linked->source_id = $source->id; - $linked->source_users_id = $socialUser->id; - $linked->source_users_id_text = $socialUser->token; - $linked->source_username = $socialUser->nickname ?? $socialUser->name; - $linked->saveOrFail(); - - return $linked; - } } diff --git a/src/Kanvas/Users/Models/Users.php b/src/Kanvas/Users/Models/Users.php index 29b56bd78..8d550e3ce 100644 --- a/src/Kanvas/Users/Models/Users.php +++ b/src/Kanvas/Users/Models/Users.php @@ -439,12 +439,9 @@ public function resetPassword(string $newPassword, AppInterface $app): bool { $user = $this->getAppProfile($app); $user->password = Hash::make($newPassword); - $user->saveOrFail(); - $user->user_activation_forgot = ''; - $user->saveOrFail(); - return true; + return $user->saveOrFail(); } public function updateEmail(string $email): bool diff --git a/src/Kanvas/Users/Models/UsersAssociatedApps.php b/src/Kanvas/Users/Models/UsersAssociatedApps.php index 76555436a..e62f5941d 100644 --- a/src/Kanvas/Users/Models/UsersAssociatedApps.php +++ b/src/Kanvas/Users/Models/UsersAssociatedApps.php @@ -7,12 +7,10 @@ use Baka\Traits\HasCompositePrimaryKeyTrait; use Baka\Users\Contracts\UserAppInterface; use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Support\Facades\Hash; +use Kanvas\AccessControlList\Models\Role; use Kanvas\Apps\Models\Apps; use Kanvas\Auth\Contracts\Authenticatable; use Kanvas\Companies\Models\Companies; -use Kanvas\Enums\AppEnums; -use Kanvas\Enums\StateEnums; use Kanvas\Models\BaseModel; use Kanvas\Users\Enums\StatusEnums; @@ -50,12 +48,12 @@ class UsersAssociatedApps extends BaseModel implements Authenticatable, UserAppI protected $primaryKey = [ 'users_id', 'apps_id', + 'companies_id', ]; protected $fillable = [ 'users_id', 'apps_id', - 'roles_id', 'companies_id', 'identify_id', 'password', @@ -78,8 +76,6 @@ class UsersAssociatedApps extends BaseModel implements Authenticatable, UserAppI /** * Users relationship. - * - * @return BelongsTo */ public function user(): BelongsTo { @@ -88,18 +84,19 @@ public function user(): BelongsTo /** * Users relationship. - * - * @return BelongsTo */ public function company(): BelongsTo { return $this->belongsTo(Companies::class, 'companies_id'); } + public function role(): BelongsTo + { + return $this->belongsTo(Role::class, 'user_role'); + } + /** * Users relationship. - * - * @return BelongsTo */ public function app(): BelongsTo { @@ -132,4 +129,14 @@ public function isBanned(): bool { return $this->banned === StatusEnums::ACTIVE->getValue(); } + + /** + * since we store this entity for user role of the given company + * we need to create a composite key + * @override + */ + public function getKey() + { + return $this->users_id . $this->apps_id . $this->companies_id; + } } diff --git a/src/Kanvas/Users/Repositories/UsersRepository.php b/src/Kanvas/Users/Repositories/UsersRepository.php index da8e0422f..7a930c239 100644 --- a/src/Kanvas/Users/Repositories/UsersRepository.php +++ b/src/Kanvas/Users/Repositories/UsersRepository.php @@ -21,6 +21,7 @@ class UsersRepository { /** * findUsersByIds + * @psalm-suppress MixedReturnStatement */ public static function findUsersByIds(array $usersIds): Collection { @@ -35,14 +36,15 @@ public static function findUsersByIds(array $usersIds): Collection */ public static function getById(int $id, int $companiesId): Users { - return Users::join('users_associated_company', 'users_associated_company.users_id', 'users.id') - ->where('users_associated_company.companies_id', $companiesId) - ->where('id', $id) - ->firstOrFail(); + return self::getUserOfCompanyById( + Companies::getById($companiesId), + $id + ); } /** * Get the user by email. + * @psalm-suppress MixedReturnStatement */ public static function getByEmail(string $email): Users { @@ -52,17 +54,25 @@ public static function getByEmail(string $email): Users /** * Get the user if he exist in the current company. + * @psalm-suppress MixedReturnStatement */ public static function getUserOfCompanyById(Companies $company, int $id): Users { - return Users::join('users_associated_company', 'users_associated_company.users_id', 'users.id') - ->where('users_associated_company.companies_id', $company->getKey()) - ->where('users.id', $id) - ->firstOrFail(); + try { + return Users::join('users_associated_company', 'users_associated_company.users_id', 'users.id') + ->where('users_associated_company.companies_id', $company->getKey()) + ->where('users.id', $id) + ->firstOrFail(); + } catch (ModelNotFoundException) { + throw new ExceptionsModelNotFoundException( + 'User not found' + ); + } } /** * Get the user if he exist in the current app. + * @psalm-suppress MixedReturnStatement */ public static function getUserOfAppById(int $id): Users { @@ -74,6 +84,7 @@ public static function getUserOfAppById(int $id): Users /** * getAll. + * @psalm-suppress MixedReturnStatement */ public static function getAll(int $companiesId): Collection { @@ -85,7 +96,7 @@ public static function getAll(int $companiesId): Collection /** * User belongs / has permission in this company. - * + * @psalm-suppress MixedReturnStatement * @throws ExceptionsModelNotFoundException */ public static function belongsToCompany(Users $user, Companies $company): UsersAssociatedCompanies @@ -104,7 +115,7 @@ public static function belongsToCompany(Users $user, Companies $company): UsersA /** * User belongs / has permission in this company. - * + * @psalm-suppress MixedReturnStatement * @throws ExceptionsModelNotFoundException */ public static function belongsToCompanyBranch(Users $user, Companies $company, CompaniesBranches $branch): UsersAssociatedCompanies @@ -124,7 +135,7 @@ public static function belongsToCompanyBranch(Users $user, Companies $company, C /** * User associated to this company on the current app. - * + * @psalm-suppress MixedReturnStatement * @throws ExceptionsModelNotFoundException */ public static function belongsToThisApp(Users $user, Apps $app, ?Companies $company = null): UsersAssociatedApps @@ -148,7 +159,7 @@ public static function belongsToThisApp(Users $user, Apps $app, ?Companies $comp /** * Is this user owner of the app? - * + * @psalm-suppress MixedReturnStatement * @throws ExceptionsModelNotFoundException */ public static function userOwnsThisApp(Users $user, Apps $app): UsersAssociatedApps diff --git a/src/Social/Follows/Models/UsersFollows.php b/src/Social/Follows/Models/UsersFollows.php index bf10f9edb..15479d950 100644 --- a/src/Social/Follows/Models/UsersFollows.php +++ b/src/Social/Follows/Models/UsersFollows.php @@ -8,6 +8,15 @@ use Kanvas\Social\Models\BaseModel; use Kanvas\Users\Models\Users; +/** + * class UsersFollows + * @property int $id + * @property int $users_id + * @property int $entity_id + * @property int $companies_id + * @property int $companies_branches_id + * @property int $entity_namespace +*/ class UsersFollows extends BaseModel { protected $guarded = []; diff --git a/src/Social/Messages/Actions/AssociateMessageToSystemModule.php b/src/Social/Messages/Actions/AssociateMessageToSystemModule.php new file mode 100644 index 000000000..559014756 --- /dev/null +++ b/src/Social/Messages/Actions/AssociateMessageToSystemModule.php @@ -0,0 +1,41 @@ + $this->message->id, + 'message_types_id' => $this->message->message_types_id, + 'apps_id' => $this->message->apps_id, + 'companies_id' => $this->message->companies_id, + 'system_modules' => $this->systemModule->model_name, + 'entity_id' => $this->entityId, + ]); + } +} diff --git a/src/Social/Messages/Actions/CreateMessageAction.php b/src/Social/Messages/Actions/CreateMessageAction.php new file mode 100644 index 000000000..24f4340c0 --- /dev/null +++ b/src/Social/Messages/Actions/CreateMessageAction.php @@ -0,0 +1,56 @@ + $this->messageInput->apps_id, + 'parent_id' => $this->messageInput->parent_id, + 'parent_unique_id' => $this->messageInput->parent_unique_id, + 'companies_id' => $this->messageInput->companies_id, + 'users_id' => $this->messageInput->users_id, + 'message_types_id' => $this->messageInput->message_types_id, + 'message' => $this->messageInput->message, + 'reactions_count' => $this->messageInput->reactions_count, + 'comments_count' => $this->messageInput->comments_count, + 'total_liked' => $this->messageInput->total_liked, + 'total_saved' => $this->messageInput->total_saved, + 'total_shared' => $this->messageInput->total_shared, + ]); + + $associateMessage = new AssociateMessageToSystemModule( + $message, + $this->systemModule, + $this->entityId + ); + $associateMessage->execute(); + + return $message; + } +} diff --git a/src/Social/Messages/Actions/CreateUserMessageAction.php b/src/Social/Messages/Actions/CreateUserMessageAction.php new file mode 100644 index 000000000..455843bce --- /dev/null +++ b/src/Social/Messages/Actions/CreateUserMessageAction.php @@ -0,0 +1,47 @@ + $this->message->id, + 'users_id' => $this->user->id, + ]); + $userMessageActivity = UserMessageActivity::firstOrCreate([ + 'user_messages_id' => $userMessage->id, + 'from_entity_id' => $this->message->appModuleMessage->entity_id, + 'entity_namespace' => $this->activity['entity_namespace'], + 'username' => $this->activity['username'], + 'type' => $this->activity['type'], + 'text' => $this->activity['text'], + ]); + } +} diff --git a/src/Social/Messages/DataTransferObject/MessageInput.php b/src/Social/Messages/DataTransferObject/MessageInput.php new file mode 100644 index 000000000..63fafa45b --- /dev/null +++ b/src/Social/Messages/DataTransferObject/MessageInput.php @@ -0,0 +1,31 @@ + null, + 'parent_unique_id' => null, + 'apps_id' => 1, + 'companies_id' => 1, + 'users_id' => 1, + 'message_types_id' => 1, + 'message' => [ + 'message' => $this->faker->text, + 'params' => [], + ], + ]; + } +} diff --git a/src/Social/Messages/Jobs/FillUserMessage.php b/src/Social/Messages/Jobs/FillUserMessage.php new file mode 100644 index 000000000..5c75ff299 --- /dev/null +++ b/src/Social/Messages/Jobs/FillUserMessage.php @@ -0,0 +1,45 @@ +onQueue('messages'); + } + + public function handle() + { + $followers = UsersFollowsRepository::getFollowersBuilder($this->entityFollow)->paginate(25); + + foreach ($followers as $follower) { + $action = new CreateUserMessageAction( + $this->message, + $follower, + $this->activity + ); + $action->execute(); + } + } +} diff --git a/src/Social/Messages/Models/AppModuleMessage.php b/src/Social/Messages/Models/AppModuleMessage.php new file mode 100644 index 000000000..fc23711a3 --- /dev/null +++ b/src/Social/Messages/Models/AppModuleMessage.php @@ -0,0 +1,50 @@ +belongsTo(MessageType::class, 'message_types_id'); + } + + public function app(): BelongsTo + { + return $this->belongsTo(Apps::class, 'apps_id'); + } + + public function company(): BelongsTo + { + return $this->belongsTo(Companies::class, 'companies_id'); + } + + public function message(): BelongsTo + { + return $this->belongTo(Message::class, 'message_id'); + } +} diff --git a/src/Social/Messages/Models/Message.php b/src/Social/Messages/Models/Message.php new file mode 100644 index 000000000..9eaec3960 --- /dev/null +++ b/src/Social/Messages/Models/Message.php @@ -0,0 +1,116 @@ + Json::class, + ]; + + /** + * Create a new factory instance for the model. + */ + protected static function newFactory(): Factory + { + return MessageFactory::new(); + } + /** + * Get the name of the index associated with the model. + */ + public function searchableAs(): string + { + return 'messages_index_app_' . app(Apps::class)->getId(); + } + + /** + * parent + */ + public function parent(): BelongsTo + { + return $this->belongsTo(Message::class, 'parent_id', 'id'); + } + + /** + * app + */ + public function app(): BelongsTo + { + return $this->setConnection('ecosystem')->belongsTo(Apps::class, 'apps_id'); + } + + /** + * company + */ + public function company(): BelongsTo + { + return $this->setConnection('ecosystem')->belongsTo(Companies::class, 'companies_id'); + } + + /** + * user + */ + public function user(): BelongsTo + { + return $this->setConnection('ecosystem')->belongsTo(Users::class, 'users_id'); + } + + /** + * messageType + */ + public function messageType(): BelongsTo + { + return $this->belongsTo(MessageType::class, 'message_types_id'); + } + + /** + * appModuleMessage + */ + public function appModuleMessage(): HasOne + { + return $this->setConnection('ecosystem')->hasOne(AppModuleMessage::class, 'message_id'); + } +} diff --git a/src/Social/Messages/Models/UserMessage.php b/src/Social/Messages/Models/UserMessage.php new file mode 100644 index 000000000..d5f19f995 --- /dev/null +++ b/src/Social/Messages/Models/UserMessage.php @@ -0,0 +1,43 @@ +setConnection('ecosystem')->belongsTo(Users::class, 'users_id'); + } + + /** + * message + */ + public function message(): BelongsTo + { + return $this->belongsTo(Message::class, 'messages_id'); + } + + /** + * Get all of the activities for the UserMessage + */ + public function activities(): HasMany + { + return $this->hasMany(UserMessageActivity::class, 'user_messages_id'); + } +} diff --git a/src/Social/Messages/Models/UserMessageActivity.php b/src/Social/Messages/Models/UserMessageActivity.php new file mode 100644 index 000000000..d7a5fd147 --- /dev/null +++ b/src/Social/Messages/Models/UserMessageActivity.php @@ -0,0 +1,35 @@ +belongsTo(UserMessage::class, 'user_messages_id'); + } +} diff --git a/src/Social/Messages/Models/UserMessageActivityType.php b/src/Social/Messages/Models/UserMessageActivityType.php new file mode 100644 index 000000000..6274e4f00 --- /dev/null +++ b/src/Social/Messages/Models/UserMessageActivityType.php @@ -0,0 +1,14 @@ +type) + ->where('user_messages_id', $activity->user_messages_id) + ->count(); + $notes = [ + 'notes' => $activity->userMessage->notes, + 'message_activity_count' => $count, + 'message_activity_username' => $activity->username, + 'message_type_activity' => $activity->type, + 'message_activity_text' => $activity->text, + ]; + $userMessage = $activity->userMessage; + $userMessage->activities = json_encode($notes); + $userMessage->saveOrFail(); + } +} diff --git a/src/Social/Messages/Repositories/MessageRepository.php b/src/Social/Messages/Repositories/MessageRepository.php new file mode 100644 index 000000000..71364540d --- /dev/null +++ b/src/Social/Messages/Repositories/MessageRepository.php @@ -0,0 +1,18 @@ + $this->messageTypeInput->verb, + 'apps_id' => $this->messageTypeInput->apps_id, + 'languages_id' => $this->messageTypeInput->languages_id, + ], + [ + 'apps_id' => $this->messageTypeInput->apps_id, + 'languages_id' => $this->messageTypeInput->languages_id, + 'name' => $this->messageTypeInput->name, + 'verb' => $this->messageTypeInput->verb, + 'template' => $this->messageTypeInput->template, + 'templates_plura' => $this->messageTypeInput->templates_plura, + ] + ); + } +} diff --git a/src/Social/MessagesTypes/DataTransferObject/MessageTypeInput.php b/src/Social/MessagesTypes/DataTransferObject/MessageTypeInput.php new file mode 100644 index 000000000..f136b655e --- /dev/null +++ b/src/Social/MessagesTypes/DataTransferObject/MessageTypeInput.php @@ -0,0 +1,34 @@ +create(); + + return [ + 'name' => fake()->name, + 'apps_id' => 1, + 'languages_id' => $languages->id, + 'verb' => 'create', + 'template' => '', + 'templates_plura' => '', + ]; + } +} diff --git a/src/Social/MessagesTypes/Models/MessageType.php b/src/Social/MessagesTypes/Models/MessageType.php new file mode 100644 index 000000000..7063a0f05 --- /dev/null +++ b/src/Social/MessagesTypes/Models/MessageType.php @@ -0,0 +1,40 @@ +data->toArray()); + if ($this->data->files) { + foreach ($this->data->files as $file) { + $userList->addFileFromUrl($file['url'], $file['name']); + } + } + + return $userList; + } +} diff --git a/src/Social/UsersLists/DataTransferObject/UserList.php b/src/Social/UsersLists/DataTransferObject/UserList.php new file mode 100644 index 000000000..fef1df5da --- /dev/null +++ b/src/Social/UsersLists/DataTransferObject/UserList.php @@ -0,0 +1,22 @@ +belongsTo(Users::class, 'users_id'); + } + + public function app(): BelongsTo + { + return $this->belongsTo(Apps::class, 'apps_id'); + } + + public function company(): BelongsTo + { + return $this->belongsTo(Companies::class, 'companies_id'); + } + + public function items(): BelongsToMany + { + return $this->belongsToMany(Message::class, 'users_lists_messages', 'users_lists_id', 'messages_id'); + } + + /** + * Get the name of the index associated with the model. + */ + public function searchableAs(): string + { + return 'users_lists_index_app_' . app(Apps::class)->getId(); + } + + /** + * Get the indexable data array for the model. + * + * @return array + */ + public function toSearchableArray(): array + { + $array = $this->toArray(); + $array['items'] = $this->items->toArray(); + + // Customize the data array... + + return $array; + } +} diff --git a/src/Social/UsersLists/Observers/UsersListsObserver.php b/src/Social/UsersLists/Observers/UsersListsObserver.php new file mode 100644 index 000000000..78ac407c3 --- /dev/null +++ b/src/Social/UsersLists/Observers/UsersListsObserver.php @@ -0,0 +1,22 @@ +where('id', '!=', $usersLists->getId()) + ->where('users_id', $usersLists->users_id) + ->first(); + if ($defaultUsersLists) { + $defaultUsersLists->is_default = 0; + $defaultUsersLists->saveQuietly(); + } + } +} diff --git a/src/Social/UsersLists/Repositories/UserListRepository.php b/src/Social/UsersLists/Repositories/UserListRepository.php new file mode 100644 index 000000000..988c4b9cc --- /dev/null +++ b/src/Social/UsersLists/Repositories/UserListRepository.php @@ -0,0 +1,20 @@ +when($user, function ($userList) use ($user) { + $userList->where('users_id', $user->getId()); + }); + + return $userList->firstOrFail(); + } +} diff --git a/tests/Ecosystem/Integration/Sessions/SessionTest.php b/tests/Ecosystem/Integration/Sessions/SessionTest.php index 7e98d0d7e..77c624229 100644 --- a/tests/Ecosystem/Integration/Sessions/SessionTest.php +++ b/tests/Ecosystem/Integration/Sessions/SessionTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Tests\Ecosystem\Integration\Filesystem; +namespace Tests\Ecosystem\Integration\Sessions; use Baka\Support\Str; use Kanvas\Apps\Models\Apps; diff --git a/tests/GraphQL/Ecosystem/AccessControlListTest.php b/tests/GraphQL/Ecosystem/AccessControlListTest.php deleted file mode 100644 index 292791f67..000000000 --- a/tests/GraphQL/Ecosystem/AccessControlListTest.php +++ /dev/null @@ -1,178 +0,0 @@ -user(); - - $this->graphQL( /** @lang GraphQL */ - ' - mutation( - $name: String! - $title: String - ) { - createRole( - name: $name - title: $title - ) { - id, - name - title - } - }', - [ - 'name' => 'No Admin', - 'title' => 'No Admin' - ] - )->assertJson([ - 'data' => [ - 'createRole' => [ - 'name' => 'No Admin', - 'title' => 'No Admin' - ] - ] - ]); - } - - /** - * testGetRole. - * - * @return void - */ - public function testGetRole(): void - { - $user = auth()->user(); - - $this->graphQL( /** @lang GraphQL */ - ' - mutation( - $name: String! - $title: String - ) { - createRole( - name: $name - title: $title - ) { - id, - name - title - } - }', - [ - 'name' => 'No Admin', - 'title' => 'No Admin' - ] - )->assertJson([ - 'data' => [ - 'createRole' => [ - 'name' => 'No Admin', - 'title' => 'No Admin' - ] - ] - ]); - $response = $this->graphQL(/** @lang GraphQL */ - ' - { - roles{ - name, - id - } - } - ' - ); - $this->assertArrayHasKey('data', $response); - } - - /** - * testUpdateRole. - * - * @return void - */ - public function testUpdateRole(): void - { - $user = auth()->user(); - - $this->graphQL( /** @lang GraphQL */ - ' - mutation( - $name: String! - $title: String - ) { - createRole( - name: $name - title: $title - ) { - id, - name - title - } - }', - [ - 'name' => 'No Admin', - 'title' => 'No Admin' - ] - )->assertJson([ - 'data' => [ - 'createRole' => [ - 'name' => 'No Admin', - 'title' => 'No Admin' - ] - ] - ]); - $response = $this->graphQL(/** @lang GraphQL */ - ' - { - roles{ - name, - id - } - } - ' - ); - $id = $response->json('data.roles.*.id'); - - $this->graphQL(/** @lang GraphQL */ - ' - mutation( - $id: Int! - $name: String! - $title: String - ) { - updateRole( - id: $id - name: $name - title: $title - ) { - id, - name - title - } - }', - [ - 'id' => $id[0], - 'name' => 'Role Updated', - 'title' => 'Role Updated' - ] - )->assertJson([ - 'data' => [ - 'updateRole' => [ - 'name' => 'Role Updated', - 'title' => 'Role Updated', - 'id' => $id[0] - ] - ] - ]); - } -} diff --git a/tests/GraphQL/Ecosystem/CustomFieldsTest.php b/tests/GraphQL/Ecosystem/CustomFieldsTest.php index f01105f91..a657f62c2 100644 --- a/tests/GraphQL/Ecosystem/CustomFieldsTest.php +++ b/tests/GraphQL/Ecosystem/CustomFieldsTest.php @@ -32,6 +32,9 @@ public function testSetCustomField(): void ]); } + /** + * @deprecated + */ public function testGetCustomField(): void { $key = fake()->word; @@ -70,6 +73,51 @@ public function testGetCustomField(): void )->assertSee($value); } + public function testGetCustomFieldQuery(): void + { + $key = fake()->word; + $value = fake()->numberBetween(1, 100); + + $results = $this->graphQL( /** @lang GraphQL */ + ' + mutation ($input: CustomFieldInput!) { + setCustomField(input: $input) + }', + [ + 'input' => [ + 'name' => $key, + 'data' => [ + 'hellos' => $value, + ], + 'system_module_uuid' => get_class(auth()->user()), + 'entity_id' => auth()->user()->uuid, + ], + ], + )->json(); + + $this->graphQL( /** @lang GraphQL */ + ' + query customField( + $name : String!, + $system_module_uuid: String! , + $entity_id : String!) { + customField( + name: $name, + system_module_uuid: $system_module_uuid, + entity_id : $entity_id + ) + }', + [ + 'name' => $key, + 'system_module_uuid' => get_class(auth()->user()), + 'entity_id' => auth()->user()->uuid, + ], + )->assertSee($value); + } + + /** + * @deprecated + */ public function testGetAllCustomField(): void { $key = fake()->word; @@ -125,6 +173,65 @@ public function testGetAllCustomField(): void )->assertSee($value); } + public function testGetAllCustomFieldQuery(): void + { + $key = fake()->word; + $value = fake()->numberBetween(1, 100); + + $results = $this->graphQL( /** @lang GraphQL */ + ' + mutation ($input: CustomFieldInput!) { + setCustomField(input: $input) + }', + [ + 'input' => [ + 'name' => $key, + 'data' => [ + 'hellos' => $value, + ], + 'system_module_uuid' => get_class(auth()->user()), + 'entity_id' => auth()->user()->uuid, + ], + ], + )->json(); + + $results = $this->graphQL( /** @lang GraphQL */ + ' + mutation ($input: CustomFieldInput!) { + setCustomField(input: $input) + }', + [ + 'input' => [ + 'name' => fake()->word, + 'data' => [ + 'hellos' => $value, + ], + 'system_module_uuid' => get_class(auth()->user()), + 'entity_id' => auth()->user()->uuid, + ], + ], + )->json(); + + $this->graphQL( /** @lang GraphQL */ + ' + query customFields( + $name : String!, + $system_module_uuid: String! , + $entity_id : String!) { + customFields( + name: $name, + system_module_uuid: $system_module_uuid, + entity_id : $entity_id + ) + }', + [ + 'name' => $key, + 'system_module_uuid' => get_class(auth()->user()), + 'entity_id' => auth()->user()->uuid, + ], + )->assertSee($value); + } + public function testDeleteCustomField(): void { $key = fake()->word; diff --git a/tests/GraphQL/Ecosystem/Roles/RolesTest.php b/tests/GraphQL/Ecosystem/Roles/RolesTest.php new file mode 100644 index 000000000..cd9f39ebe --- /dev/null +++ b/tests/GraphQL/Ecosystem/Roles/RolesTest.php @@ -0,0 +1,313 @@ +user(); + + $this->graphQL( /** @lang GraphQL */ + ' + mutation( + $name: String! + $title: String + ) { + createRole( + name: $name + title: $title + ) { + id, + name + title + } + }', + [ + 'name' => 'No Admin', + 'title' => 'No Admin', + ] + )->assertJson([ + 'data' => [ + 'createRole' => [ + 'name' => 'No Admin', + 'title' => 'No Admin', + ], + ], + ]); + } + + /** + * testGetRole. + */ + public function testGetRole(): void + { + $user = auth()->user(); + + $this->graphQL( /** @lang GraphQL */ + ' + mutation( + $name: String! + $title: String + ) { + createRole( + name: $name + title: $title + ) { + id, + name + title + } + }', + [ + 'name' => 'No Admin', + 'title' => 'No Admin', + ] + ); + + $response = $this->graphQL(/** @lang GraphQL */ + ' + { + roles{ + name, + id + } + } + ' + ); + $this->assertArrayHasKey('data', $response); + } + + /** + * testUpdateRole. + */ + public function testUpdateRole(): void + { + $user = auth()->user(); + + $this->graphQL( /** @lang GraphQL */ + ' + mutation( + $name: String! + $title: String + ) { + createRole( + name: $name + title: $title + ) { + id, + name + title + } + }', + [ + 'name' => 'No Admin', + 'title' => 'No Admin', + ] + ); + + $response = $this->graphQL(/** @lang GraphQL */ + ' + { + roles{ + name, + id + } + } + ' + ); + $id = $response->json('data.roles.*.id'); + + $faker = \Faker\Factory::create(); + $newName = $faker->name; + + $this->graphQL(/** @lang GraphQL */ + ' + mutation( + $id: Int! + $name: String! + $title: String + ) { + updateRole( + id: $id + name: $name + title: $title + ) { + id, + name + title + } + }', + [ + 'id' => $id[0], + 'name' => $newName, + 'title' => 'Role Updated', + ] + )->assertJson([ + 'data' => [ + 'updateRole' => [ + 'name' => $newName, + 'title' => 'Role Updated', + 'id' => $id[0], + ], + ], + ]); + } + + public function testAssignUserRole() + { + $user = auth()->user(); + $faker = \Faker\Factory::create(); + $newName = $faker->name; + + $this->graphQL( /** @lang GraphQL */ + ' + mutation( + $name: String! + $title: String + ) { + createRole( + name: $name + title: $title + ) { + id, + name + title + } + }', + [ + 'name' => $newName, + 'title' => 'No Admin', + ] + ); + + + $this->graphQL(/** @lang GraphQL */ + ' + mutation( + $userId: Int! + $role: Mixed! + ) { + assignRoleToUser( + userId: $userId + role: $role + ) + }', + [ + 'userId' => $user->getId(), + 'role' => $newName, + ] + )->assertJson([ + 'data' => [ + 'assignRoleToUser' => true, + ], + ]); + } + + public function testHasRole() + { + $user = auth()->user(); + $faker = \Faker\Factory::create(); + $newName = $faker->name; + + $this->graphQL(/** @lang GraphQL */ + ' + query( + $userId: Int! + $role: Mixed! + ) { + hasRole( + userId: $userId + role: $role + ) + }', + [ + 'userId' => $user->getId(), + 'role' => DefaultRoles::ADMIN->getValue(), + ] + )->assertJson([ + 'data' => [ + 'hasRole' => true, + ], + ]); + } + + public function testRemoveAssignUserRole() + { + $user = auth()->user(); + $faker = \Faker\Factory::create(); + $newName = $faker->name; + + $this->graphQL( /** @lang GraphQL */ + ' + mutation( + $name: String! + $title: String + ) { + createRole( + name: $name + title: $title + ) { + id, + name + title + } + }', + [ + 'name' => $newName, + 'title' => 'No Admin', + ] + ); + + + $this->graphQL(/** @lang GraphQL */ + ' + mutation( + $userId: Int! + $role: Mixed! + ) { + assignRoleToUser( + userId: $userId + role: $role + ) + }', + [ + 'userId' => $user->getId(), + 'role' => $newName, + ] + )->assertJson([ + 'data' => [ + 'assignRoleToUser' => true, + ], + ]); + + $this->graphQL(/** @lang GraphQL */ + ' + mutation( + $userId: Int! + $role: Mixed! + ) { + removeRole( + userId: $userId + role: $role + ) + }', + [ + 'userId' => $user->getId(), + 'role' => $newName, + ] + )->assertJson([ + 'data' => [ + 'removeRole' => true, + ], + ]); + } +} diff --git a/tests/GraphQL/Ecosystem/Roles/UsersAbilitiesTest.php b/tests/GraphQL/Ecosystem/Roles/UsersAbilitiesTest.php new file mode 100644 index 000000000..9e7c5dee8 --- /dev/null +++ b/tests/GraphQL/Ecosystem/Roles/UsersAbilitiesTest.php @@ -0,0 +1,153 @@ +user(); + + $this->graphQL(/** @lang GraphQL */ + ' + query getAllAbilities( + $userId: Int! + ) { + getAllAbilities( + userId: $userId + ) + }', + [ + 'userId' => $user->getId(), + ] + )->assertJson([ + 'data' => [ + 'getAllAbilities' => [], + ], + ]); + } + + public function testGiveUserPermission() + { + $user = auth()->user(); + + $this->graphQL(/** @lang GraphQL */ + ' + mutation( + $userId: Int! + $permission: String! + ) { + givePermissionToUser( + userId: $userId + permission: $permission + ) + }', + [ + 'userId' => $user->getId(), + 'permission' => 'invite-users', + ] + )->assertJson([ + 'data' => [ + 'givePermissionToUser' => true, + ], + ]); + } + + public function testRemoveUserPermission() + { + $user = auth()->user(); + + $this->graphQL(/** @lang GraphQL */ + ' + mutation( + $userId: Int! + $permission: String! + ) { + givePermissionToUser( + userId: $userId + permission: $permission + ) + }', + [ + 'userId' => $user->getId(), + 'permission' => 'invite-users', + ] + )->assertJson([ + 'data' => [ + 'givePermissionToUser' => true, + ], + ]); + + $this->graphQL(/** @lang GraphQL */ + ' + mutation( + $userId: Int! + $permission: String! + ) { + removePermissionToUser( + userId: $userId + permission: $permission + ) + }', + [ + 'userId' => $user->getId(), + 'permission' => 'invite-users', + ] + )->assertJson([ + 'data' => [ + 'removePermissionToUser' => true, + ], + ]); + } + + public function testDoesUserHaveThisPermission() + { + $user = auth()->user(); + + $this->graphQL(/** @lang GraphQL */ + ' + mutation( + $userId: Int! + $permission: String! + ) { + givePermissionToUser( + userId: $userId + permission: $permission + ) + }', + [ + 'userId' => $user->getId(), + 'permission' => 'invite-users', + ] + )->assertJson([ + 'data' => [ + 'givePermissionToUser' => true, + ], + ]); + + $this->graphQL(/** @lang GraphQL */ + ' + query( + $userId: Int! + $permission: String! + ) { + can( + userId: $userId + permission: $permission + ) + }', + [ + 'userId' => $user->getId(), + 'permission' => 'invite-users', + ] + )->assertJson([ + 'data' => [ + 'can' => true, + ], + ]); + } +} diff --git a/tests/GraphQL/Ecosystem/Users/UserDeviceTest.php b/tests/GraphQL/Ecosystem/Users/UserDeviceTest.php new file mode 100644 index 000000000..0d9a1373a --- /dev/null +++ b/tests/GraphQL/Ecosystem/Users/UserDeviceTest.php @@ -0,0 +1,71 @@ + $source->title, + 'device_id' => Str::uuid(), + 'source_username' => 'kanvasniche', + ]; + } + + public function testLinkUserDevice() + { + $source = Sources::firstOrFail(); + + $this->graphQL(/** @lang GraphQL */ ' + mutation linkDevice($data: DeviceInput!) { + linkDevice(data: $data) + } + ', [ + 'data' => $this->generateDevice(), + ])->assertJson([ + 'data' => [ + 'linkDevice' => true, + ], + ]); + } + + public function testUnLinkUserDevice() + { + $source = Sources::firstOrFail(); + $deviceData = $this->generateDevice(); + + $this->graphQL(/** @lang GraphQL */ ' + mutation linkDevice($data: DeviceInput!) { + linkDevice(data: $data) + } + ', [ + 'data' => $deviceData, + ])->assertJson([ + 'data' => [ + 'linkDevice' => true, + ], + ]); + + $this->graphQL(/** @lang GraphQL */ ' + mutation unLinkDevice($data: DeviceInput!) { + unLinkDevice(data: $data) + } + ', [ + 'data' => $deviceData, + + ])->assertJson([ + 'data' => [ + 'unLinkDevice' => true, + ], + ]); + } +} diff --git a/tests/GraphQL/Ecosystem/UserTest.php b/tests/GraphQL/Ecosystem/Users/UserTest.php similarity index 70% rename from tests/GraphQL/Ecosystem/UserTest.php rename to tests/GraphQL/Ecosystem/Users/UserTest.php index 3789d664d..3decf2abd 100644 --- a/tests/GraphQL/Ecosystem/UserTest.php +++ b/tests/GraphQL/Ecosystem/Users/UserTest.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Tests\GraphQL\Ecosystem; +namespace Tests\GraphQL\Ecosystem\Users; use Kanvas\Auth\DataTransferObject\LoginInput; use Tests\TestCase; @@ -13,8 +13,6 @@ class UserTest extends TestCase /** * Set login credentials. - * - * @return LoginInput */ public static function loginData(): LoginInput { @@ -22,14 +20,14 @@ public static function loginData(): LoginInput self::$loginData = LoginInput::from([ 'email' => fake()->email, 'password' => fake()->password(8), - 'ip' => request()->ip() + 'ip' => request()->ip(), ]); } return self::$loginData; } - public function editUserdata(): void + public function testEditUserdata(): void { $loginData = self::loginData(); $firstname = fake()->firstName(); @@ -38,17 +36,24 @@ public function editUserdata(): void $response = $this->graphQL( /** @lang GraphQL */ ' - mutation updateUser($data: UpdateUserInput!) { - updateUser(data: $data) + mutation updateUser($id: ID!, $data: UpdateUserInput!) { + updateUser(id: $id, data: $data) { firstname lastname displayname description - sex + sex, + custom_fields{ + data{ + name, + value + } + } } }', [ + 'id' => 0, 'data' => [ 'firstname' => $firstname, 'lastname' => $lastname, @@ -56,7 +61,13 @@ public function editUserdata(): void 'description' => fake()->text(30), 'sex' => 'U', 'phone_number' => fake()->phoneNumber(), - 'address_1' => fake()->address() + 'address_1' => fake()->address(), + 'custom_fields' => [ + [ + 'name' => 'test', + 'data' => 'test', + ] + ], ], ] ) @@ -65,6 +76,7 @@ public function editUserdata(): void ->assertSee('lastname', $lastname) ->assertSee('displayname', $displayname) ->assertSee('description') + ->assertSee('custom_fields') ->assertSee('sex'); } @@ -81,11 +93,11 @@ public function testChangePassword() } ', [ 'new_password' => 'abc123456', - 'new_password_confirmation' => 'abc123456' + 'new_password_confirmation' => 'abc123456', ])->assertJson([ 'data' => [ - 'changePassword' => true - ] + 'changePassword' => true, + ], ]); } } diff --git a/tests/GraphQL/Guild/LeadTest.php b/tests/GraphQL/Guild/LeadTest.php index b6a699d47..3b88cbe30 100644 --- a/tests/GraphQL/Guild/LeadTest.php +++ b/tests/GraphQL/Guild/LeadTest.php @@ -20,4 +20,309 @@ public function testGetLeads(): void } }')->assertOk(); } + + protected function createLeadAndGetResponse(array $input = []) + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $title = fake()->title(); + + if (empty($input)) { + $input = [ + 'branch_id' => $branch->getId(), + 'title' => $title, + 'pipeline_stage_id' => 0, + 'people' => [ + 'firstname' => fake()->firstName(), + 'lastname' => fake()->lastName(), + 'contacts' => [ + [ + 'value' => fake()->email(), + 'contacts_types_id' => 1, + 'weight' => 0, + ], + ], + 'address' => [ + [ + 'address' => fake()->address(), + 'city' => fake()->city(), + 'state' => fake()->state(), + 'country' => fake()->country(), + 'zip' => fake()->postcode(), + ], + ], + ], + 'custom_fields' => [], + ]; + } + + return $this->graphQL(' + mutation($input: LeadInput!) { + createLead(input: $input) { + id + people { + id + } + } + } + ', [ + 'input' => $input, + ])->json(); + } + + public function testCreateLead() + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $title = fake()->title(); + + $input = [ + 'branch_id' => $branch->getId(), + 'title' => $title, + 'pipeline_stage_id' => 0, + 'people' => [ + 'firstname' => fake()->firstName(), + 'lastname' => fake()->lastName(), + 'contacts' => [ + [ + 'value' => fake()->email(), + 'contacts_types_id' => 1, + 'weight' => 0, + ], + ], + 'address' => [ + [ + 'address' => fake()->address(), + 'city' => fake()->city(), + 'state' => fake()->state(), + 'country' => fake()->country(), + 'zip' => fake()->postcode(), + ], + ], + 'custom_fields' => [], + ], + 'organization' => [ + 'name' => fake()->company(), + 'address' => fake()->address(), + ], + 'custom_fields' => [ + [ + 'name' => 'test', + 'data' => 'test', + ], + ], + ]; + + $this->graphQL(' + mutation($input: LeadInput!) { + createLead(input: $input) { + title + } + } + ', [ + 'input' => $input, + ])->assertJson([ + 'data' => [ + 'createLead' => [ + 'title' => $title, + ], + ], + ]); + } + + public function testUpdateLead() + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $title = fake()->title(); + + $input = [ + 'branch_id' => $branch->getId(), + 'title' => $title, + 'pipeline_stage_id' => 0, + 'people' => [ + 'firstname' => fake()->firstName(), + 'lastname' => fake()->lastName(), + 'contacts' => [ + [ + 'value' => fake()->email(), + 'contacts_types_id' => 1, + 'weight' => 0, + ], + ], + 'address' => [ + [ + 'address' => fake()->address(), + 'city' => fake()->city(), + 'state' => fake()->state(), + 'country' => fake()->country(), + 'zip' => fake()->postcode(), + ], + ], + 'custom_fields' => [], + ], + 'custom_fields' => [ + [ + 'name' => 'test', + 'data' => 'test', + ], + ], + ]; + + $response = $this->createLeadAndGetResponse($input); + + $leadId = $response['data']['createLead']['id']; + $peopleId = $response['data']['createLead']['people']['id']; + + $input = [ + 'branch_id' => $branch->getId(), + 'title' => $title, + 'people_id' => $peopleId, + 'custom_fields' => [], + ]; + + $this->graphQL(' + mutation($id: ID!, $input: LeadUpdateInput!) { + updateLead(id: $id, input: $input) { + id + title + } + } + ', [ + 'id' => $leadId, + 'input' => $input, + ])->assertJson([ + 'data' => [ + 'updateLead' => [ + 'id' => $leadId, + 'title' => $title, + + ], + ], + ]); + } + + public function testDeleteLead() + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $title = fake()->title(); + + $input = [ + 'branch_id' => $branch->getId(), + 'title' => $title, + 'pipeline_stage_id' => 0, + 'people' => [ + 'firstname' => fake()->firstName(), + 'lastname' => fake()->lastName(), + 'contacts' => [ + [ + 'value' => fake()->email(), + 'contacts_types_id' => 1, + 'weight' => 0, + ], + ], + 'address' => [ + [ + 'address' => fake()->address(), + 'city' => fake()->city(), + 'state' => fake()->state(), + 'country' => fake()->country(), + 'zip' => fake()->postcode(), + ], + ], + 'custom_fields' => [], + ], + 'custom_fields' => [ + [ + 'name' => 'test', + 'data' => 'test', + ], + ], + ]; + + $response = $this->createLeadAndGetResponse($input); + + $leadId = $response['data']['createLead']['id']; + + $this->graphQL(' + mutation($id: ID!) { + deleteLead(id: $id) + } + ', [ + 'id' => $leadId, + ])->assertJson([ + 'data' => [ + 'deleteLead' => true, + ], + ]); + } + + public function testRestoreLead() + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $title = fake()->title(); + + $input = [ + 'branch_id' => $branch->getId(), + 'title' => $title, + 'pipeline_stage_id' => 0, + 'people' => [ + 'firstname' => fake()->firstName(), + 'lastname' => fake()->lastName(), + 'contacts' => [ + [ + 'value' => fake()->email(), + 'contacts_types_id' => 1, + 'weight' => 0, + ], + ], + 'address' => [ + [ + 'address' => fake()->address(), + 'city' => fake()->city(), + 'state' => fake()->state(), + 'country' => fake()->country(), + 'zip' => fake()->postcode(), + ], + ], + 'custom_fields' => [], + ], + 'custom_fields' => [ + [ + 'name' => 'test', + 'data' => 'test', + ], + ], + ]; + + $response = $this->createLeadAndGetResponse($input); + + $leadId = $response['data']['createLead']['id']; + + $this->graphQL(' + mutation($id: ID!) { + deleteLead(id: $id) + } + ', [ + 'id' => $leadId, + ])->assertJson([ + 'data' => [ + 'deleteLead' => true, + ], + ]); + + $this->graphQL(' + mutation($id: ID!) { + restoreLead(id: $id) + } + ', [ + 'id' => $leadId, + ])->assertJson([ + 'data' => [ + 'restoreLead' => true, + ], + ]); + } } diff --git a/tests/GraphQL/Guild/OrganizationTest.php b/tests/GraphQL/Guild/OrganizationTest.php new file mode 100644 index 000000000..4386fd334 --- /dev/null +++ b/tests/GraphQL/Guild/OrganizationTest.php @@ -0,0 +1,188 @@ +graphQL(' + query { + leads { + data { + id + uuid + name + address + } + } + }')->assertOk(); + } + + protected function createOrganizationAndGetResponse(array $input = []) + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $name = fake()->company(); + + if (empty($input)) { + $input = [ + 'name' => $name, + 'address' => fake()->address(), + ]; + } + + return $this->graphQL(' + mutation($input: OrganizationInput!) { + createOrganization(input: $input) { + id + name + } + } + ', [ + 'input' => $input, + ])->json(); + } + + public function testOrganizationLead() + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $name = fake()->company(); + + $input = [ + 'name' => $name, + 'address' => fake()->address(), + ]; + + $this->graphQL(' + mutation($input: OrganizationInput!) { + createOrganization(input: $input) { + name + } + } + ', [ + 'input' => $input, + ])->assertJson([ + 'data' => [ + 'createOrganization' => [ + 'name' => $name, + ], + ], + ]); + } + + public function testUpdateOrganization() + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $name = fake()->company(); + + $input = [ + 'name' => $name, + 'address' => fake()->address(), + ]; + + $response = $this->createOrganizationAndGetResponse($input); + + $organizationId = $response['data']['createOrganization']['id']; + + $newName = fake()->company(); + + $input = [ + 'name' => $newName, + ]; + + $this->graphQL(' + mutation($id: ID!, $input: OrganizationInput!) { + updateOrganization(id: $id, input: $input) { + id + name + } + } + ', [ + 'id' => $organizationId, + 'input' => $input, + ])->assertJson([ + 'data' => [ + 'updateOrganization' => [ + 'id' => $organizationId, + 'name' => $newName, + + ], + ], + ]); + } + + public function testDeleteOrganization() + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $name = fake()->company(); + + $input = [ + 'name' => $name, + 'address' => fake()->address(), + ]; + + $response = $this->createOrganizationAndGetResponse($input); + + $leadId = $response['data']['createOrganization']['id']; + + $this->graphQL(' + mutation($id: ID!) { + deleteOrganization(id: $id) + } + ', [ + 'id' => $leadId, + ])->assertJson([ + 'data' => [ + 'deleteOrganization' => true, + ], + ]); + } + + public function testRestoreOrganization() + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $name = fake()->company(); + + $input = [ + 'name' => $name, + 'address' => fake()->address(), + ]; + + $response = $this->createOrganizationAndGetResponse($input); + + $leadId = $response['data']['createOrganization']['id']; + + $this->graphQL(' + mutation($id: ID!) { + deleteOrganization(id: $id) + } + ', [ + 'id' => $leadId, + ])->assertJson([ + 'data' => [ + 'deleteOrganization' => true, + ], + ]); + + $this->graphQL(' + mutation($id: ID!) { + restoreOrganization(id: $id) + } + ', [ + 'id' => $leadId, + ])->assertJson([ + 'data' => [ + 'restoreOrganization' => true, + ], + ]); + } +} diff --git a/tests/GraphQL/Guild/PeopleTest.php b/tests/GraphQL/Guild/PeopleTest.php new file mode 100644 index 000000000..6dd7ff0e4 --- /dev/null +++ b/tests/GraphQL/Guild/PeopleTest.php @@ -0,0 +1,304 @@ +graphQL(' + query { + peoples { + data { + uuid + name + } + } + }')->assertOk(); + } + + protected function createPeopleAndResponse(array $input = []) + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $title = fake()->title(); + + if (empty($input)) { + $input = [ + 'firstname' => fake()->firstName(), + 'lastname' => fake()->lastName(), + 'contacts' => [ + [ + 'value' => fake()->email(), + 'contacts_types_id' => 1, + 'weight' => 0, + ], + [ + 'value' => fake()->phoneNumber(), + 'contacts_types_id' => 2, + 'weight' => 0, + ], + ], + 'address' => [ + [ + 'address' => fake()->address(), + 'city' => fake()->city(), + 'state' => fake()->state(), + 'country' => fake()->country(), + 'zip' => fake()->postcode(), + ], + ], + 'custom_fields' => [], + ]; + } + + return $this->graphQL(' + mutation($input: PeopleInput!) { + createPeople(input: $input) { + id, + uuid, + name, + dob + } + } + ', [ + 'input' => $input, + ])->json(); + } + + public function testCreatePeople() + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $firstname = fake()->firstName(); + $lastname = fake()->lastName(); + $name = $firstname . ' ' . $lastname; + + $input = [ + 'firstname' => $firstname, + 'lastname' => $lastname, + 'contacts' => [ + [ + 'value' => fake()->email(), + 'contacts_types_id' => 1, + 'weight' => 0, + ], + [ + 'value' => fake()->phoneNumber(), + 'contacts_types_id' => 2, + 'weight' => 0, + ], + ], + 'address' => [ + [ + 'address' => fake()->address(), + 'city' => fake()->city(), + 'state' => fake()->state(), + 'country' => fake()->country(), + 'zip' => fake()->postcode(), + ], + ], + 'custom_fields' => [], + ]; + + $this->graphQL(' + mutation($input: PeopleInput!) { + createPeople(input: $input) { + name + } + } + ', [ + 'input' => $input, + ])->assertJson([ + 'data' => [ + 'createPeople' => [ + 'name' => $name, + ], + ], + ]); + } + + public function testUpdatePeople() + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $firstname = fake()->firstName(); + $lastname = fake()->lastName(); + + $input = [ + 'firstname' => $firstname, + 'lastname' => $lastname, + 'contacts' => [ + [ + 'value' => fake()->email(), + 'contacts_types_id' => 1, + 'weight' => 0, + ], + [ + 'value' => fake()->phoneNumber(), + 'contacts_types_id' => 2, + 'weight' => 0, + ], + ], + 'address' => [ + [ + 'address' => fake()->address(), + 'city' => fake()->city(), + 'state' => fake()->state(), + 'country' => fake()->country(), + 'zip' => fake()->postcode(), + ], + ], + 'custom_fields' => [], + ]; + + $response = $this->createPeopleAndResponse($input); + + $peopleId = $response['data']['createPeople']['id']; + $firstname = fake()->firstName(); + $lastname = fake()->lastName(); + $name = $firstname . ' ' . $lastname; + $input = [ + 'firstname' => $firstname, + 'lastname' => $lastname, + 'contacts' => [], + 'address' => [], + 'custom_fields' => [], + ]; + $this->graphQL(' + mutation($id: ID!, $input: PeopleInput!) { + updatePeople(id: $id, input: $input) { + id + name + } + } + ', [ + 'id' => $peopleId, + 'input' => $input, + ])->assertJson([ + 'data' => [ + 'updatePeople' => [ + 'id' => $peopleId, + 'name' => $name, + + ], + ], + ]); + } + + public function testDeletePeople() + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $title = fake()->title(); + + $input = [ + 'firstname' => fake()->firstName(), + 'lastname' => fake()->lastName(), + 'contacts' => [ + [ + 'value' => fake()->email(), + 'contacts_types_id' => 1, + 'weight' => 0, + ], + [ + 'value' => fake()->phoneNumber(), + 'contacts_types_id' => 2, + 'weight' => 0, + ], + ], + 'address' => [ + [ + 'address' => fake()->address(), + 'city' => fake()->city(), + 'state' => fake()->state(), + 'country' => fake()->country(), + 'zip' => fake()->postcode(), + ], + ], + 'custom_fields' => [], + ]; + + $response = $this->createPeopleAndResponse($input); + + $peopleId = $response['data']['createPeople']['id']; + + $this->graphQL(' + mutation($id: ID!) { + deletePeople(id: $id) + } + ', [ + 'id' => $peopleId, + ])->assertJson([ + 'data' => [ + 'deletePeople' => true, + ], + ]); + } + + public function testRestoreLead() + { + $user = auth()->user(); + $branch = $user->getCurrentBranch(); + $title = fake()->title(); + + $input = [ + 'firstname' => fake()->firstName(), + 'lastname' => fake()->lastName(), + 'contacts' => [ + [ + 'value' => fake()->email(), + 'contacts_types_id' => 1, + 'weight' => 0, + ], + [ + 'value' => fake()->phoneNumber(), + 'contacts_types_id' => 2, + 'weight' => 0, + ], + ], + 'address' => [ + [ + 'address' => fake()->address(), + 'city' => fake()->city(), + 'state' => fake()->state(), + 'country' => fake()->country(), + 'zip' => fake()->postcode(), + ], + ], + 'custom_fields' => [], + ]; + + $response = $this->createPeopleAndResponse($input); + + $peopleId = $response['data']['createPeople']['id']; + + $this->graphQL(' + mutation($id: ID!) { + deletePeople(id: $id) + } + ', [ + 'id' => $peopleId, + ])->assertJson([ + 'data' => [ + 'deletePeople' => true, + ], + ]); + + $this->graphQL(' + mutation($id: ID!) { + restorePeople(id: $id) + } + ', [ + 'id' => $peopleId, + ])->assertJson([ + 'data' => [ + 'restorePeople' => true, + ], + ]); + } +} diff --git a/tests/GraphQL/Inventory/VariantAttributeTest.php b/tests/GraphQL/Inventory/VariantAttributeTest.php index 1aa416682..326b8e778 100644 --- a/tests/GraphQL/Inventory/VariantAttributeTest.php +++ b/tests/GraphQL/Inventory/VariantAttributeTest.php @@ -52,6 +52,7 @@ public function testAddAttributeToVariant(): void $dataAtribute = [ 'name' => fake()->name, + 'value' => fake()->name ]; $response = $this->graphQL(' mutation($data: AttributeInput!) { @@ -59,10 +60,11 @@ public function testAddAttributeToVariant(): void { id name + values { + value + } } - }', ['data' => $dataAtribute])->assertJson([ - 'data' => ['createAttribute' => $dataAtribute] - ]); + }', ['data' => $dataAtribute]); $attributeId = $response->json()['data']['createAttribute']['id']; $response = $this->graphQL(' mutation($id: Int! $attributes_id: Int! $input: VariantsAttributesInput!) { @@ -127,6 +129,7 @@ public function testRemoveAttributeFromVariant(): void $dataAtribute = [ 'name' => fake()->name, + 'value' => fake()->name ]; $response = $this->graphQL(' mutation($data: AttributeInput!) { @@ -135,9 +138,7 @@ public function testRemoveAttributeFromVariant(): void id name } - }', ['data' => $dataAtribute])->assertJson([ - 'data' => ['createAttribute' => $dataAtribute] - ]); + }', ['data' => $dataAtribute]); $attributeId = $response->json()['data']['createAttribute']['id']; $response = $this->graphQL(' mutation($id: Int! $attributes_id: Int! $input: VariantsAttributesInput!) { diff --git a/tests/GraphQL/Social/MessageTest.php b/tests/GraphQL/Social/MessageTest.php new file mode 100644 index 000000000..f378ed3ec --- /dev/null +++ b/tests/GraphQL/Social/MessageTest.php @@ -0,0 +1,196 @@ +create(); + $message = fake()->text(); + Message::makeAllSearchable(); + + $this->graphQL( + ' + mutation createMessage($input: MessageInput!) { + createMessage(input: $input) { + id + message + message_types_id + } + } + ', + [ + 'input' => [ + 'message' => $message, + 'message_types_id' => $messageType->id, + 'system_modules_id' => 1, + 'entity_id' => '1', + ], + ] + )->assertJson([ + 'data' => [ + 'createMessage' => [ + 'message' => $message, + 'message_types_id' => $messageType->id, + ], + ], + ]); + } + + public function testGetMessages() + { + $messageType = MessageType::factory()->create(); + $message = fake()->text(); + $response = $this->graphQL( + ' + mutation createMessage($input: MessageInput!) { + createMessage(input: $input) { + id + message + message_types_id + } + } + ', + [ + 'input' => [ + 'message' => $message, + 'message_types_id' => $messageType->id, + 'system_modules_id' => 1, + 'entity_id' => '1', + ], + ] + ); + + $this->graphQL( + ' + query { + messages { + data { + message + message_types_id + } + } + } + ' + )->assertSuccessful(); + } + + public function testGetMessageFilter() + { + $messageType = MessageType::factory()->create(); + $message = fake()->text(); + $response = $this->graphQL( + ' + mutation createMessage($input: MessageInput!) { + createMessage(input: $input) { + id + message + message_types_id + } + } + ', + [ + 'input' => [ + 'message' => $message, + 'message_types_id' => $messageType->id, + 'system_modules_id' => 1, + 'entity_id' => '1', + ], + ] + ); + + $createdMessageId = $response['data']['createMessage']['id']; + + $this->graphQL( + ' + query { + messages( + where: { + column: ID, operator: EQ, value: ' . $createdMessageId . ' + } + ) { + data { + message + message_types_id + } + } + } + ' + )->assertJson([ + 'data' => [ + 'messages' => [ + 'data' => [ + [ + 'message' => $message, + 'message_types_id' => $messageType->id, + ], + ], + ], + ], + ]); + } + + public function testMessageSearch() + { + $messageType = MessageType::factory()->create(); + $message = fake()->text(); + $this->graphQL( + ' + mutation createMessage($input: MessageInput!) { + createMessage(input: $input) { + id + message + message_types_id + } + } + ', + [ + 'input' => [ + 'message' => $message, + 'message_types_id' => $messageType->id, + 'system_modules_id' => 1, + 'entity_id' => '1', + ], + ] + ); + + $this->graphQL( + ' + query messages($text: String!) { + messages(search: $text) { + data { + message + message_types_id + } + } + } + ', + [ + 'text' => $message, + ] + )->assertJson([ + 'data' => [ + 'messages' => [ + 'data' => [ + [ + 'message' => $message, + 'message_types_id' => $messageType->id, + ], + ], + ], + ], + ]); + } +} diff --git a/tests/GraphQL/Social/MessageTypeTest.php b/tests/GraphQL/Social/MessageTypeTest.php new file mode 100644 index 000000000..bb0f49026 --- /dev/null +++ b/tests/GraphQL/Social/MessageTypeTest.php @@ -0,0 +1,145 @@ +create(); + $name = fake()->name(); + $this->graphQL(/** @lang GRAPHQL */ + ' + mutation createMessageType( + $input: CreateMessageTypeInput! + ) + { + createMessageType(input: $input) { + id + name + } + } + ', + [ + 'input' => [ + 'name' => $name, + 'languages_id' => $language->id, + 'verb' => 'test - ' . $name, + 'template' => '', + 'templates_plura' => '', + ], + ] + )->assertJson([ + 'data' => [ + 'createMessageType' => [ + 'name' => $name, + ], + ], + ]); + } + + public function testUpdateMessageType() + { + $language = Languages::factory()->create(); + $name = fake()->name(); + $response = $this->graphQL(/** @lang GRAPHQL */ + ' + mutation createMessageType( + $input: CreateMessageTypeInput! + ) + { + createMessageType(input: $input) { + id + name + } + } + ', + [ + 'input' => [ + 'name' => $name, + 'languages_id' => $language->id, + 'verb' => 'test - ' . $name, + 'template' => '', + 'templates_plura' => '', + ], + ] + ); + $this->graphQL(/** @lang GRAPHQL */ + ' + mutation updateMessageType( + $id: Int! + $input: CreateMessageTypeInput! + ) + { + updateMessageType(id: $id, input: $input) { + id + name + } + } + ', + [ + 'id' => $response->json('data.createMessageType.id'), + 'input' => [ + 'name' => $name . ' - updated', + 'languages_id' => $language->id, + 'verb' => 'test - ' . $name, + 'template' => '', + 'templates_plura' => '', + ], + ] + )->assertJson([ + 'data' => [ + 'updateMessageType' => [ + 'name' => $name . ' - updated', + ], + ], + ]); + } + + public function testGetMessageType() + { + $language = Languages::factory()->create(); + $name = fake()->name(); + $response = $this->graphQL(/** @lang GRAPHQL */ + ' + mutation createMessageType( + $input: CreateMessageTypeInput! + ) + { + createMessageType(input: $input) { + id + name + } + } + ', + [ + 'input' => [ + 'name' => $name, + 'languages_id' => $language->id, + 'verb' => 'test - ' . $name, + 'template' => '', + 'templates_plura' => '', + ], + ] + ); + $this->graphQL(/** @lang GRAPHQL */ + ' + { + messageTypes { + data { + id + name + } + } + } + ' + )->assertJsonFragment([ + 'name' => $name, + ]); + } +} diff --git a/tests/GraphQL/Social/UsersListsTest.php b/tests/GraphQL/Social/UsersListsTest.php new file mode 100644 index 000000000..190c62c45 --- /dev/null +++ b/tests/GraphQL/Social/UsersListsTest.php @@ -0,0 +1,238 @@ + fake()->name(), + 'description' => fake()->text(), + 'is_public' => fake()->boolean(), + 'is_default' => fake()->boolean(), + ]; + $this->graphQL( + ' + mutation createUserList($input: UserListInput!) { + createUserList(input: $input) { + name, + description, + is_public, + is_default + } + } + ', + [ + 'input' => $input, + ] + )->assertJson([ + 'data' => [ + 'createUserList' => $input, + ], + ]); + } + + /** + * testUpdateUsersLists + * + * @return void + */ + public function testUpdateUsersLists() + { + $input = [ + 'name' => fake()->name(), + 'description' => fake()->text(), + 'is_public' => fake()->boolean(), + 'is_default' => fake()->boolean(), + ]; + $response = $this->graphQL( + ' + mutation createUserList($input: UserListInput!) { + createUserList(input: $input) { + id + } + } + ', + [ + 'input' => $input, + ] + ); + $id = $response->json('data.createUserList.id'); + $newName = fake()->name(); + $this->graphQL( + ' + mutation updateUserList($id: Int!, $input: UserListInput!) { + updateUserList(id: $id, input: $input) { + id + name + } + } + ', + [ + 'id' => $id, + 'input' => [ + 'name' => $newName, + 'description' => fake()->text(), + 'is_public' => fake()->boolean(), + 'is_default' => fake()->boolean(), + ], + ] + )->assertJson([ + 'data' => [ + 'updateUserList' => [ + 'id' => $id, + 'name' => $newName, + ], + ], + ]); + } + + /** + * testDeleteUsersLists + * + * @return void + */ + public function testDeleteUsersLists() + { + $input = [ + 'name' => fake()->name(), + 'description' => fake()->text(), + 'is_public' => fake()->boolean(), + 'is_default' => fake()->boolean(), + ]; + $response = $this->graphQL( + ' + mutation createUserList($input: UserListInput!) { + createUserList(input: $input) { + id + } + } + ', + [ + 'input' => $input, + ] + ); + $id = $response->json('data.createUserList.id'); + $this->graphQL( + ' + mutation deleteUserList($id: Int!) { + deleteUserList(id: $id) + } + ', + [ + 'id' => $id, + ] + )->assertJson([ + 'data' => [ + 'deleteUserList' => true, + ], + ]); + } + + public function testAddToList() + { + $message = Message::factory()->create(); + $input = [ + 'name' => fake()->name(), + 'description' => fake()->text(), + 'is_public' => fake()->boolean(), + 'is_default' => fake()->boolean(), + ]; + $response = $this->graphQL( + ' + mutation createUserList($input: UserListInput!) { + createUserList(input: $input) { + id + } + } + ', + [ + 'input' => $input, + ] + ); + $id = $response->json('data.createUserList.id'); + + $this->graphQL( + ' + mutation addToUserList($users_lists_id: Int!, $messages_id: Int!) { + addToUserList(users_lists_id: $users_lists_id, messages_id: $messages_id) + } + ', + [ + 'users_lists_id' => $id, + 'messages_id' => $message->id, + ] + )->assertJson([ + 'data' => [ + 'addToUserList' => true, + ], + ]); + } + + public function testRemoveFromList() + { + $message = Message::factory()->create(); + $input = [ + 'name' => fake()->name(), + 'description' => fake()->text(), + 'is_public' => fake()->boolean(), + 'is_default' => fake()->boolean(), + ]; + $response = $this->graphQL( + ' + mutation createUserList($input: UserListInput!) { + createUserList(input: $input) { + id + } + } + ', + [ + 'input' => $input, + ] + ); + $id = $response->json('data.createUserList.id'); + + $this->graphQL( + ' + mutation addToUserList($users_lists_id: Int!, $messages_id: Int!) { + addToUserList(users_lists_id: $users_lists_id, messages_id: $messages_id) + } + ', + [ + 'users_lists_id' => $id, + 'messages_id' => $message->id, + ] + )->assertJson([ + 'data' => [ + 'addToUserList' => true, + ], + ]); + + $this->graphQL( + ' + mutation removeFromUserList($users_lists_id: Int!, $messages_id: Int!) { + removeFromUserList(users_lists_id: $users_lists_id, messages_id: $messages_id) + } + ', + [ + 'users_lists_id' => $id, + 'messages_id' => $message->id, + ] + )->assertJson([ + 'data' => [ + 'removeFromUserList' => true, + ], + ]); + } +} diff --git a/tests/Guild/Integration/SetupTest.php b/tests/Guild/Integration/SetupTest.php new file mode 100644 index 000000000..d495fdf78 --- /dev/null +++ b/tests/Guild/Integration/SetupTest.php @@ -0,0 +1,24 @@ +user()->getCurrentCompany(); + $setupCompany = new Setup( + app(Apps::class), + auth()->user(), + $company + ); + + $this->assertTrue($setupCompany->run()); + } +}